diff --git a/commercialoperator/__init__.py b/commercialoperator/__init__.py deleted file mode 100755 index 99e3a86a7b..0000000000 --- a/commercialoperator/__init__.py +++ /dev/null @@ -1 +0,0 @@ -default_app_config = 'commercialoperator.apps.CommercialOperatorConfig' diff --git a/commercialoperator/admin.py b/commercialoperator/admin.py deleted file mode 100755 index 5cb3f76674..0000000000 --- a/commercialoperator/admin.py +++ /dev/null @@ -1,47 +0,0 @@ -from django.contrib.admin import AdminSite -from django.contrib import admin -from django.contrib.auth.admin import UserAdmin -from django.contrib.auth.models import Group -from django.conf import settings - -from ledger.accounts import admin as ledger_admin -#from ledger.accounts.models import EmailUser, Document, Address, Profile -from ledger.accounts.models import EmailUser -from copy import deepcopy - - -class CommercialOperatorAdminSite(AdminSite): - site_header = 'Commercial Operator Administration' - site_title = 'Commercial Operator Licensing' - index_title = 'Commercial Operator Licensing' - -commercialoperator_admin_site = CommercialOperatorAdminSite(name='commercialoperatoradmin') - -admin.site.unregister(EmailUser) # because this base classAdmin alsready registered in ledger.accounts.admin -@admin.register(EmailUser) -class EmailUserAdmin(ledger_admin.EmailUserAdmin): - """ - Overriding the EmailUserAdmin from ledger.accounts.admin, to remove is_superuser checkbox field on Admin page - """ - - def get_fieldsets(self, request, obj=None): - """ Remove the is_superuser checkbox from the Admin page, if user is CommercialOperatorAdmin and NOT superuser """ - fieldsets = super(UserAdmin, self).get_fieldsets(request, obj) - #if not obj: - # return fieldsets - - if request.user.is_superuser: - return fieldsets - - # User is not a superuser, remove is_superuser checkbox - fieldsets = deepcopy(fieldsets) - for fieldset in fieldsets: - if 'is_superuser' in fieldset[1]['fields']: - if type(fieldset[1]['fields']) == tuple : - fieldset[1]['fields'] = list(fieldset[1]['fields']) - fieldset[1]['fields'].remove('is_superuser') - break - - return fieldsets - - diff --git a/commercialoperator/apps.py b/commercialoperator/apps.py deleted file mode 100755 index a156d7ae12..0000000000 --- a/commercialoperator/apps.py +++ /dev/null @@ -1,16 +0,0 @@ -from __future__ import unicode_literals -from django.conf import settings - -from django.apps import AppConfig - -class CommercialOperatorConfig(AppConfig): - name = 'commercialoperator' - verbose_name = settings.SYSTEM_NAME - - run_once = False - def ready(self): - if not self.run_once: - from commercialoperator.components.organisations import signals - from commercialoperator.components.proposals import signals - - self.run_once = True diff --git a/commercialoperator/components/__init__.py b/commercialoperator/components/__init__.py deleted file mode 100755 index e69de29bb2..0000000000 diff --git a/commercialoperator/components/approvals/__init__.py b/commercialoperator/components/approvals/__init__.py deleted file mode 100755 index e69de29bb2..0000000000 diff --git a/commercialoperator/components/approvals/admin.py b/commercialoperator/components/approvals/admin.py deleted file mode 100755 index e69de29bb2..0000000000 diff --git a/commercialoperator/components/approvals/api.py b/commercialoperator/components/approvals/api.py deleted file mode 100755 index e4c2b37d60..0000000000 --- a/commercialoperator/components/approvals/api.py +++ /dev/null @@ -1,446 +0,0 @@ -import traceback -import os -import datetime -import base64 -import geojson -from six.moves.urllib.parse import urlparse -from wsgiref.util import FileWrapper -from django.db.models import Q, Min -from django.db import transaction -from django.http import HttpResponse -from django.core.files.base import ContentFile -from django.core.exceptions import ValidationError -from django.conf import settings -from django.contrib import messages -from django.views.decorators.http import require_http_methods -from django.views.decorators.csrf import csrf_exempt -from django.utils import timezone -from rest_framework import viewsets, serializers, status, generics, views -from rest_framework.decorators import detail_route, list_route, renderer_classes -from rest_framework.response import Response -from rest_framework.renderers import JSONRenderer -from rest_framework.permissions import IsAuthenticated, AllowAny, IsAdminUser, BasePermission -from rest_framework.pagination import PageNumberPagination -from datetime import datetime, timedelta -from collections import OrderedDict -from django.core.cache import cache -from ledger.accounts.models import EmailUser, Address -from ledger.address.models import Country -from datetime import datetime, timedelta, date -from django.urls import reverse -from django.shortcuts import render, redirect, get_object_or_404 -from commercialoperator.components.proposals.models import Proposal, ApplicationType -from commercialoperator.components.approvals.models import ( - Approval, - ApprovalDocument -) -from commercialoperator.components.approvals.serializers import ( - ApprovalSerializer, - ApprovalCancellationSerializer, - ApprovalExtendSerializer, - ApprovalSuspensionSerializer, - ApprovalSurrenderSerializer, - ApprovalUserActionSerializer, - ApprovalLogEntrySerializer, - ApprovalPaymentSerializer -) -from commercialoperator.components.organisations.models import Organisation, OrganisationContact -from commercialoperator.helpers import is_customer, is_internal -from rest_framework_datatables.pagination import DatatablesPageNumberPagination -from commercialoperator.components.proposals.api import ProposalFilterBackend, ProposalRenderer - -class ApprovalPaginatedViewSet(viewsets.ModelViewSet): - filter_backends = (ProposalFilterBackend,) - pagination_class = DatatablesPageNumberPagination - renderer_classes = (ProposalRenderer,) - page_size = 10 - queryset = Approval.objects.none() - serializer_class = ApprovalSerializer - - def get_queryset(self): - if is_internal(self.request): - return Approval.objects.all() - elif is_customer(self.request): - user_orgs = [org.id for org in self.request.user.commercialoperator_organisations.all()] - queryset = Approval.objects.filter(Q(org_applicant_id__in = user_orgs) | Q(submitter = self.request.user)) - return queryset - return Approval.objects.none() - -# def list(self, request, *args, **kwargs): -# response = super(ProposalPaginatedViewSet, self).list(request, args, kwargs) -# -# # Add extra data to response.data -# #response.data['regions'] = self.get_queryset().filter(region__isnull=False).values_list('region__name', flat=True).distinct() -# return response - - @list_route(methods=['GET',]) - def approvals_external(self, request, *args, **kwargs): - """ - Paginated serializer for datatables - used by the internal and external dashboard (filtered by the get_queryset method) - - To test: - http://localhost:8000/api/approval_paginated/approvals_external/?format=datatables&draw=1&length=2 - """ - - #qs = self.queryset().order_by('lodgement_number', '-issue_date').distinct('lodgement_number') - #qs = ProposalFilterBackend().filter_queryset(self.request, qs, self) - - ids = self.get_queryset().order_by('lodgement_number', '-issue_date').distinct('lodgement_number').values_list('id', flat=True) - qs = Approval.objects.filter(id__in=ids) - qs = self.filter_queryset(qs) - - # on the internal organisations dashboard, filter the Proposal/Approval/Compliance datatables by applicant/organisation - applicant_id = request.GET.get('org_id') - if applicant_id: - qs = qs.filter(org_applicant_id=applicant_id) - submitter_id = request.GET.get('submitter_id', None) - if submitter_id: - qs = qs.filter(submitter_id=submitter_id) - - self.paginator.page_size = qs.count() - result_page = self.paginator.paginate_queryset(qs, request) - serializer = ApprovalSerializer(result_page, context={'request':request}, many=True) - return self.paginator.get_paginated_response(serializer.data) - - -from rest_framework import filters -class ApprovalPaymentFilterViewSet(generics.ListAPIView): - """ https://cop-internal.dbca.wa.gov.au/api/filtered_organisations?search=Org1 - """ - queryset = Approval.objects.none() - serializer_class = ApprovalPaymentSerializer - filter_backends = (filters.SearchFilter,) - #search_fields = ('applicant', 'applicant_id',) - search_fields = ('id',) - - def get_queryset(self): - """ - Return All approvals associated with user (proxy_applicant and org_applicant) - """ - #return Approval.objects.filter(proxy_applicant=self.request.user) - user = self.request.user - - # get all orgs associated with user - user_org_ids = OrganisationContact.objects.filter(email=user.email).values_list('organisation_id', flat=True) - - now = datetime.now().date() - approval_qs = Approval.objects.filter(Q(proxy_applicant=user) | Q(org_applicant_id__in=user_org_ids) | Q(submitter_id=user)) - approval_qs = approval_qs.exclude(current_proposal__application_type__name='E Class') - approval_qs = approval_qs.exclude(expiry_date__lt=now) - approval_qs = approval_qs.exclude(replaced_by__isnull=False) # get lastest licence, ignore the amended - return approval_qs - - @list_route(methods=['GET',]) - def _list(self, request, *args, **kwargs): - data = [] - for approval in self.get_queryset(): - data.append(dict(lodgement_number=approval.lodgement_number, current_proposal=approval.current_proposal_id)) - return Response(data) - #return Response(self.get_queryset().values_list('lodgement_number','current_proposal_id')) - - -class ApprovalViewSet(viewsets.ModelViewSet): - #queryset = Approval.objects.all() - queryset = Approval.objects.none() - serializer_class = ApprovalSerializer - - def get_queryset(self): - if is_internal(self.request): - return Approval.objects.all() - elif is_customer(self.request): - user_orgs = [org.id for org in self.request.user.commercialoperator_organisations.all()] - queryset = Approval.objects.filter(Q(org_applicant_id__in = user_orgs) | Q(submitter = self.request.user)) - return queryset - return Approval.objects.none() - - def list(self, request, *args, **kwargs): - #queryset = self.get_queryset() - queryset = self.get_queryset().order_by('lodgement_number', '-issue_date').distinct('lodgement_number') - # Filter by org - org_id = request.GET.get('org_id',None) - if org_id: - queryset = queryset.filter(org_applicant_id=org_id) - submitter_id = request.GET.get('submitter_id', None) - if submitter_id: - qs = qs.filter(submitter_id=submitter_id) - serializer = self.get_serializer(queryset, many=True) - return Response(serializer.data) - - @list_route(methods=['GET',]) - def filter_list(self, request, *args, **kwargs): - """ Used by the external dashboard filters """ - region_qs = self.get_queryset().filter(current_proposal__region__isnull=False).values_list('current_proposal__region__name', flat=True).distinct() - activity_qs = self.get_queryset().filter(current_proposal__activity__isnull=False).values_list('current_proposal__activity', flat=True).distinct() - data = dict( - regions=region_qs, - activities=activity_qs, - approval_status_choices = [i[1] for i in Approval.STATUS_CHOICES], - ) - return Response(data) - - @detail_route(methods=['POST']) - @renderer_classes((JSONRenderer,)) - def process_document(self, request, *args, **kwargs): - instance = self.get_object() - action = request.POST.get('action') - section = request.POST.get('input_name') - if action == 'list' and 'input_name' in request.POST: - pass - - elif action == 'delete' and 'document_id' in request.POST: - document_id = request.POST.get('document_id') - document = instance.qaofficer_documents.get(id=document_id) - - document.visible = False - document.save() - instance.save(version_comment='Licence ({}): {}'.format(section, document.name)) # to allow revision to be added to reversion history - - elif action == 'save' and 'input_name' in request.POST and 'filename' in request.POST: - proposal_id = request.POST.get('proposal_id') - filename = request.POST.get('filename') - _file = request.POST.get('_file') - if not _file: - _file = request.FILES.get('_file') - - document = instance.qaofficer_documents.get_or_create(input_name=section, name=filename)[0] - path = default_storage.save('{}/proposals/{}/approvals/{}'.format(settings.MEDIA_APP_DIR, proposal_id, filename), ContentFile(_file.read())) - - document._file = path - document.save() - instance.save(version_comment='Licence ({}): {}'.format(section, filename)) # to allow revision to be added to reversion history - #instance.current_proposal.save(version_comment='File Added: {}'.format(filename)) # to allow revision to be added to reversion history - - return Response( [dict(input_name=d.input_name, name=d.name,file=d._file.url, id=d.id, can_delete=d.can_delete) for d in instance.qaofficer_documents.filter(input_name=section, visible=True) if d._file] ) - - @detail_route(methods=['POST',]) - @renderer_classes((JSONRenderer,)) - def add_eclass_licence(self, request, *args, **kwargs): - - def raiser(exception): raise serializers.ValidationError(exception) - - try: - with transaction.atomic(): - #keys = request.data.keys() - #file_keys = [key for key in keys if 'file-upload' in i] - org_applicant = None - proxy_applicant = None - - _file = request.data.get('file-upload-0') if request.data.get('file-upload-0') else raiser('Licence File is required') - try: - if request.data.get('applicant_type') == 'org': - org_applicant = Organisation.objects.get(organisation_id=request.data.get('holder-selected')) - else: - proxy_applicant = EmailUser.objects.get(id=request.data.get('holder-selected')) - except: - raise serializers.ValidationError('Licence holder is required') - - start_date = datetime.strptime(request.data.get('start_date'), '%d/%m/%Y') if request.data.get('start_date') else raiser('Start Date is required') - issue_date = datetime.strptime(request.data.get('issue_date'), '%d/%m/%Y') if request.data.get('issue_date') else raiser('Issue Date is required') - expiry_date = datetime.strptime(request.data.get('expiry_date'), '%d/%m/%Y') if request.data.get('expiry_date') else raiser('Expiry Date is required') - - application_type, app_type_created = ApplicationType.objects.get_or_create( - name='E Class', - defaults={'visible':False, 'max_renewals':1, 'max_renewal_period':5} - ) - - proposal, proposal_created = Proposal.objects.get_or_create( # Dummy 'E Class' proposal - id=0, - defaults={'application_type':application_type, 'submitter':request.user, 'schema':[]} - ) - - approval = Approval.objects.create( - issue_date=issue_date, - expiry_date=expiry_date, - start_date=start_date, - org_applicant=org_applicant, - proxy_applicant=proxy_applicant, - current_proposal=proposal - ) - - doc = ApprovalDocument.objects.create(approval=approval, _file=_file) - approval.licence_document=doc - approval.save() - - return Response({'approval': approval.lodgement_number}) - - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - if hasattr(e,'error_dict'): - raise serializers.ValidationError(repr(e.error_dict)) - else: - raise serializers.ValidationError(repr(e[0].encode('utf-8'))) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - - - @detail_route(methods=['POST',]) - def approval_extend(self, request, *args, **kwargs): - try: - instance = self.get_object() - serializer = ApprovalExtendSerializer(data=request.data) - serializer.is_valid(raise_exception=True) - instance.approval_extend(request,serializer.validated_data) - serializer = ApprovalSerializer(instance,context={'request':request}) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - if hasattr(e,'error_dict'): - raise serializers.ValidationError(repr(e.error_dict)) - else: - raise serializers.ValidationError(repr(e[0].encode('utf-8'))) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['POST',]) - def approval_cancellation(self, request, *args, **kwargs): - try: - instance = self.get_object() - serializer = ApprovalCancellationSerializer(data=request.data) - serializer.is_valid(raise_exception=True) - instance.approval_cancellation(request,serializer.validated_data) - serializer = ApprovalSerializer(instance,context={'request':request}) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - if hasattr(e,'error_dict'): - raise serializers.ValidationError(repr(e.error_dict)) - else: - raise serializers.ValidationError(repr(e[0].encode('utf-8'))) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['POST',]) - def approval_suspension(self, request, *args, **kwargs): - try: - instance = self.get_object() - serializer = ApprovalSuspensionSerializer(data=request.data) - serializer.is_valid(raise_exception=True) - instance.approval_suspension(request,serializer.validated_data) - serializer = ApprovalSerializer(instance,context={'request':request}) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - if hasattr(e,'error_dict'): - raise serializers.ValidationError(repr(e.error_dict)) - else: - raise serializers.ValidationError(repr(e[0].encode('utf-8'))) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - - @detail_route(methods=['POST',]) - def approval_reinstate(self, request, *args, **kwargs): - try: - instance = self.get_object() - instance.reinstate_approval(request) - serializer = self.get_serializer(instance) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - if hasattr(e,'error_dict'): - raise serializers.ValidationError(repr(e.error_dict)) - else: - raise serializers.ValidationError(repr(e[0].encode('utf-8'))) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['POST',]) - def approval_surrender(self, request, *args, **kwargs): - try: - instance = self.get_object() - serializer = ApprovalSurrenderSerializer(data=request.data) - serializer.is_valid(raise_exception=True) - instance.approval_surrender(request,serializer.validated_data) - serializer = ApprovalSerializer(instance,context={'request':request}) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - if hasattr(e,'error_dict'): - raise serializers.ValidationError(repr(e.error_dict)) - else: - raise serializers.ValidationError(repr(e[0].encode('utf-8'))) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['GET',]) - def action_log(self, request, *args, **kwargs): - try: - instance = self.get_object() - qs = instance.action_logs.all() - serializer = ApprovalUserActionSerializer(qs,many=True) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['GET',]) - def comms_log(self, request, *args, **kwargs): - try: - instance = self.get_object() - qs = instance.comms_logs.all() - serializer = ApprovalLogEntrySerializer(qs,many=True) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['POST',]) - @renderer_classes((JSONRenderer,)) - def add_comms_log(self, request, *args, **kwargs): - try: - with transaction.atomic(): - instance = self.get_object() - request.data['approval'] = u'{}'.format(instance.id) - request.data['staff'] = u'{}'.format(request.user.id) - serializer = ApprovalLogEntrySerializer(data=request.data) - serializer.is_valid(raise_exception=True) - comms = serializer.save() - # Save the files - for f in request.FILES: - document = comms.documents.create() - document.name = str(request.FILES[f]) - document._file = request.FILES[f] - document.save() - # End Save Documents - - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) diff --git a/commercialoperator/components/approvals/email.py b/commercialoperator/components/approvals/email.py deleted file mode 100755 index 63f416444b..0000000000 --- a/commercialoperator/components/approvals/email.py +++ /dev/null @@ -1,368 +0,0 @@ -import logging - -from django.core.mail import EmailMultiAlternatives, EmailMessage -from django.utils.encoding import smart_text -from django.core.urlresolvers import reverse -from django.conf import settings - -from commercialoperator.components.emails.emails import TemplateEmailBase -from ledger.accounts.models import EmailUser - -logger = logging.getLogger(__name__) - -SYSTEM_NAME = settings.SYSTEM_NAME_SHORT + ' Automated Message' -class ApprovalExpireNotificationEmail(TemplateEmailBase): - subject = '{} - Commercial Operations Licence expired.'.format(settings.DEP_NAME) - html_template = 'commercialoperator/emails/approval_expire_notification.html' - txt_template = 'commercialoperator/emails/approval_expire_notification.txt' - - -class ApprovalCancelNotificationEmail(TemplateEmailBase): - subject = '{} - Commercial Operations Licence cancelled.'.format(settings.DEP_NAME) - html_template = 'commercialoperator/emails/approval_cancel_notification.html' - txt_template = 'commercialoperator/emails/approval_cancel_notification.txt' - -class ApprovalSuspendNotificationEmail(TemplateEmailBase): - subject = '{} - Commercial Operations Licence suspended.'.format(settings.DEP_NAME) - html_template = 'commercialoperator/emails/approval_suspend_notification.html' - txt_template = 'commercialoperator/emails/approval_suspend_notification.txt' - -class ApprovalSurrenderNotificationEmail(TemplateEmailBase): - subject = '{} - Commercial Operations Licence surrendered.'.format(settings.DEP_NAME) - html_template = 'commercialoperator/emails/approval_surrender_notification.html' - txt_template = 'commercialoperator/emails/approval_surrender_notification.txt' - -class ApprovalReinstateNotificationEmail(TemplateEmailBase): - subject = '{} - Commercial Operations Licence reinstated.'.format(settings.DEP_NAME) - html_template = 'commercialoperator/emails/approval_reinstate_notification.html' - txt_template = 'commercialoperator/emails/approval_reinstate_notification.txt' - -class ApprovalRenewalNotificationEmail(TemplateEmailBase): - subject = '{} - Commercial Operations licence renewal.'.format(settings.DEP_NAME) - html_template = 'commercialoperator/emails/approval_renewal_notification.html' - txt_template = 'commercialoperator/emails/approval_renewal_notification.txt' - -def send_approval_expire_email_notification(approval): - email = ApprovalExpireNotificationEmail() - proposal = approval.current_proposal - - url=settings.SITE_URL if settings.SITE_URL else '' - url += reverse('external') - - if "-internal" in url: - # remove '-internal'. This email is for external submitters - url = ''.join(url.split('-internal')) - - context = { - 'approval': approval, - 'proposal': proposal, - 'url': url - } - msg = email.send(proposal.submitter.email, context=context) - sender = settings.DEFAULT_FROM_EMAIL - try: - sender_user = EmailUser.objects.get(email__icontains=sender) - except: - EmailUser.objects.create(email=sender, password='') - sender_user = EmailUser.objects.get(email__icontains=sender) - - _log_approval_email(msg, approval, sender=sender_user) - #_log_org_email(msg, approval.applicant, proposal.submitter, sender=sender_user) - if approval.org_applicant: - _log_org_email(msg, approval.org_applicant, proposal.submitter, sender=sender_user) - else: - _log_user_email(msg, approval.submitter, proposal.submitter, sender=sender_user) - -def send_approval_cancel_email_notification(approval): - email = ApprovalCancelNotificationEmail() - proposal = approval.current_proposal - - context = { - 'approval': approval, - - } - sender = settings.DEFAULT_FROM_EMAIL - try: - sender_user = EmailUser.objects.get(email__icontains=sender) - except: - EmailUser.objects.create(email=sender, password='') - sender_user = EmailUser.objects.get(email__icontains=sender) - msg = email.send(proposal.submitter.email, context=context) - sender = settings.DEFAULT_FROM_EMAIL - _log_approval_email(msg, approval, sender=sender_user) - #_log_org_email(msg, approval.applicant, proposal.submitter, sender=sender_user) - if approval.org_applicant: - _log_org_email(msg, approval.org_applicant, proposal.submitter, sender=sender_user) - else: - _log_user_email(msg, approval.submitter, proposal.submitter, sender=sender_user) - -def send_approval_suspend_email_notification(approval, request=None): - email = ApprovalSuspendNotificationEmail() - proposal = approval.current_proposal - - if request and 'test-emails' in request.path_info: - details = 'This are my test details' - from_date = '01/01/1970' - to_date = '01/01/2070' - else: - details = approval.suspension_details['details'], - from_date = approval.suspension_details['from_date'], - to_date = approval.suspension_details['to_date'] - - context = { - 'approval': approval, - 'details': details, - 'from_date': from_date, - 'to_date': to_date - } - sender = settings.DEFAULT_FROM_EMAIL - try: - sender_user = EmailUser.objects.get(email__icontains=sender) - except: - EmailUser.objects.create(email=sender, password='') - sender_user = EmailUser.objects.get(email__icontains=sender) - msg = email.send(proposal.submitter.email, context=context) - sender = settings.DEFAULT_FROM_EMAIL - _log_approval_email(msg, approval, sender=sender_user) - #_log_org_email(msg, approval.applicant, proposal.submitter, sender=sender_user) - if approval.org_applicant: - _log_org_email(msg, approval.org_applicant, proposal.submitter, sender=sender_user) - else: - _log_user_email(msg, approval.submitter, proposal.submitter, sender=sender_user) - -def send_approval_surrender_email_notification(approval, request=None): - email = ApprovalSurrenderNotificationEmail() - proposal = approval.current_proposal - - if request and 'test-emails' in request.path_info: - details = 'This are my test details' - surrender_date = '01/01/1970' - else: - details = approval.surrender_details['details'], - surrender_date = approval.surrender_details['surrender_date'], - - context = { - 'approval': approval, - 'details': details, - 'surrender_date': surrender_date, - } - sender = settings.DEFAULT_FROM_EMAIL - try: - sender_user = EmailUser.objects.get(email__icontains=sender) - except: - EmailUser.objects.create(email=sender, password='') - sender_user = EmailUser.objects.get(email__icontains=sender) - msg = email.send(proposal.submitter.email, context=context) - sender = settings.DEFAULT_FROM_EMAIL - _log_approval_email(msg, approval, sender=sender_user) - if approval.org_applicant: - _log_org_email(msg, approval.org_applicant, proposal.submitter, sender=sender_user) - else: - _log_user_email(msg, approval.submitter, proposal.submitter, sender=sender_user) -#approval renewal notice -def send_approval_renewal_email_notification(approval): - email = ApprovalRenewalNotificationEmail() - proposal = approval.current_proposal - url=settings.SITE_URL if settings.SITE_URL else '' - url += reverse('external') - handbook_url= settings.COLS_HANDBOOK_URL - - if "-internal" in url: - # remove '-internal'. This email is for external submitters - url = ''.join(url.split('-internal')) - - - context = { - 'approval': approval, - 'proposal': approval.current_proposal, - 'url': url, - 'handbook_url': handbook_url - } - sender = settings.DEFAULT_FROM_EMAIL - try: - sender_user = EmailUser.objects.get(email__icontains=sender) - except: - EmailUser.objects.create(email=sender, password='') - sender_user = EmailUser.objects.get(email__icontains=sender) - #attach renewal notice - if approval.renewal_document and approval.renewal_document._file is not None: - renewal_document= approval.renewal_document._file - file_name = approval.renewal_document.name - attachment = (file_name, renewal_document.file.read(), 'application/pdf') - attachment = [attachment] - else: - attachment = [] - msg = email.send(proposal.submitter.email, attachments=attachment, context=context) - sender = settings.DEFAULT_FROM_EMAIL - _log_approval_email(msg, approval, sender=sender_user) - #_log_org_email(msg, approval.applicant, proposal.submitter, sender=sender_user) - if approval.org_applicant: - _log_org_email(msg, approval.org_applicant, proposal.submitter, sender=sender_user) - else: - _log_user_email(msg, approval.submitter, proposal.submitter, sender=sender_user) - - -def send_approval_reinstate_email_notification(approval, request): - email = ApprovalReinstateNotificationEmail() - proposal = approval.current_proposal - - context = { - 'approval': approval, - - } - msg = email.send(proposal.submitter.email, context=context) - sender = request.user if request else settings.DEFAULT_FROM_EMAIL - _log_approval_email(msg, approval, sender=sender) - #_log_org_email(msg, approval.applicant, proposal.submitter, sender=sender) - if approval.org_applicant: - _log_org_email(msg, approval.org_applicant, proposal.submitter, sender=sender) - else: - _log_user_email(msg, approval.submitter, proposal.submitter, sender=sender) - - - -def _log_approval_email(email_message, approval, sender=None): - from commercialoperator.components.approvals.models import ApprovalLogEntry - if isinstance(email_message, (EmailMultiAlternatives, EmailMessage,)): - # TODO this will log the plain text body, should we log the html instead - text = email_message.body - subject = email_message.subject - fromm = smart_text(sender) if sender else smart_text(email_message.from_email) - # the to email is normally a list - if isinstance(email_message.to, list): - to = ','.join(email_message.to) - else: - to = smart_text(email_message.to) - # we log the cc and bcc in the same cc field of the log entry as a ',' comma separated string - all_ccs = [] - if email_message.cc: - all_ccs += list(email_message.cc) - if email_message.bcc: - all_ccs += list(email_message.bcc) - all_ccs = ','.join(all_ccs) - - else: - text = smart_text(email_message) - subject = '' - to = approval.current_proposal.submitter.email - fromm = smart_text(sender) if sender else SYSTEM_NAME - all_ccs = '' - - customer = approval.current_proposal.submitter - - staff = sender - - kwargs = { - 'subject': subject, - 'text': text, - 'approval': approval, - 'customer': customer, - 'staff': staff, - 'to': to, - 'fromm': fromm, - 'cc': all_ccs - } - - email_entry = ApprovalLogEntry.objects.create(**kwargs) - - return email_entry - - - - -from commercialoperator.components.organisations.models import OrganisationLogEntry, Organisation -def _log_org_email(email_message, organisation, customer ,sender=None): - if not isinstance(organisation, Organisation): - # is a proxy_applicant - return None - - if isinstance(email_message, (EmailMultiAlternatives, EmailMessage,)): - # TODO this will log the plain text body, should we log the html instead - text = email_message.body - subject = email_message.subject - fromm = smart_text(sender) if sender else smart_text(email_message.from_email) - # the to email is normally a list - if isinstance(email_message.to, list): - to = ','.join(email_message.to) - else: - to = smart_text(email_message.to) - # we log the cc and bcc in the same cc field of the log entry as a ',' comma separated string - all_ccs = [] - if email_message.cc: - all_ccs += list(email_message.cc) - if email_message.bcc: - all_ccs += list(email_message.bcc) - all_ccs = ','.join(all_ccs) - - else: - text = smart_text(email_message) - subject = '' - to = customer - fromm = smart_text(sender) if sender else SYSTEM_NAME - all_ccs = '' - - customer = customer - - staff = sender - - kwargs = { - 'subject': subject, - 'text': text, - 'organisation': organisation, - 'customer': customer, - 'staff': staff, - 'to': to, - 'fromm': fromm, - 'cc': all_ccs - } - - email_entry = OrganisationLogEntry.objects.create(**kwargs) - - return email_entry - -def _log_user_email(email_message, emailuser, customer ,sender=None): - from ledger.accounts.models import EmailUserLogEntry - if isinstance(email_message, (EmailMultiAlternatives, EmailMessage,)): - # TODO this will log the plain text body, should we log the html instead - text = email_message.body - subject = email_message.subject - fromm = smart_text(sender) if sender else smart_text(email_message.from_email) - # the to email is normally a list - if isinstance(email_message.to, list): - to = ','.join(email_message.to) - else: - to = smart_text(email_message.to) - # we log the cc and bcc in the same cc field of the log entry as a ',' comma separated string - all_ccs = [] - if email_message.cc: - all_ccs += list(email_message.cc) - if email_message.bcc: - all_ccs += list(email_message.bcc) - all_ccs = ','.join(all_ccs) - - else: - text = smart_text(email_message) - subject = '' - to = customer - fromm = smart_text(sender) if sender else SYSTEM_NAME - all_ccs = '' - - customer = customer - - staff = sender - - kwargs = { - 'subject': subject, - 'text': text, - 'emailuser': emailuser, - 'customer': customer, - 'staff': staff, - 'to': to, - 'fromm': fromm, - 'cc': all_ccs - } - - email_entry = EmailUserLogEntry.objects.create(**kwargs) - - return email_entry - diff --git a/commercialoperator/components/approvals/models.py b/commercialoperator/components/approvals/models.py deleted file mode 100755 index 0f960f4451..0000000000 --- a/commercialoperator/components/approvals/models.py +++ /dev/null @@ -1,578 +0,0 @@ -from __future__ import unicode_literals - -import json -import datetime -from django.db import models,transaction -from django.dispatch import receiver -from django.db.models.signals import pre_delete -from django.utils.encoding import python_2_unicode_compatible -from django.core.exceptions import ValidationError -from django.contrib.postgres.fields.jsonb import JSONField -from django.utils import timezone -from django.contrib.sites.models import Site -from django.conf import settings -from django.db.models import Q -from taggit.managers import TaggableManager -from taggit.models import TaggedItemBase -from ledger.accounts.models import Organisation as ledger_organisation -from ledger.accounts.models import EmailUser, RevisionedMixin -from ledger.licence.models import Licence -from commercialoperator import exceptions -from commercialoperator.components.organisations.models import Organisation -from commercialoperator.components.proposals.models import Proposal, ProposalUserAction -from commercialoperator.components.main.models import CommunicationsLogEntry, UserAction, Document, ApplicationType -from commercialoperator.components.approvals.email import ( - send_approval_expire_email_notification, - send_approval_cancel_email_notification, - send_approval_suspend_email_notification, - send_approval_reinstate_email_notification, - send_approval_surrender_email_notification -) -from commercialoperator.utils import search_keys, search_multiple_keys -from commercialoperator.helpers import is_customer -#from commercialoperator.components.approvals.email import send_referral_email_notification - - -def update_approval_doc_filename(instance, filename): - return '{}/proposals/{}/approvals/{}'.format(settings.MEDIA_APP_DIR, instance.approval.current_proposal.id,filename) - -def update_approval_comms_log_filename(instance, filename): - return '{}/proposals/{}/approvals/communications/{}'.format(settings.MEDIA_APP_DIR, instance.log_entry.approval.current_proposal.id,filename) - - -class ApprovalDocument(Document): - approval = models.ForeignKey('Approval',related_name='documents') - _file = models.FileField(upload_to=update_approval_doc_filename) - can_delete = models.BooleanField(default=True) # after initial submit prevent document from being deleted - - def delete(self): - if self.can_delete: - return super(ApprovalDocument, self).delete() - logger.info('Cannot delete existing document object after Application has been submitted (including document submitted before Application pushback to status Draft): {}'.format(self.name)) - - - class Meta: - app_label = 'commercialoperator' - -#class Approval(models.Model): -class Approval(RevisionedMixin): - STATUS_CHOICES = ( - ('current','Current'), - ('expired','Expired'), - ('cancelled','Cancelled'), - ('surrendered','Surrendered'), - ('suspended','Suspended'), - ('extended','extended'), - ) - lodgement_number = models.CharField(max_length=9, blank=True, default='') - status = models.CharField(max_length=40, choices=STATUS_CHOICES, - default=STATUS_CHOICES[0][0]) - licence_document = models.ForeignKey(ApprovalDocument, blank=True, null=True, related_name='licence_document') - cover_letter_document = models.ForeignKey(ApprovalDocument, blank=True, null=True, related_name='cover_letter_document') - replaced_by = models.ForeignKey('self', blank=True, null=True) - #current_proposal = models.ForeignKey(Proposal,related_name = '+') - current_proposal = models.ForeignKey(Proposal,related_name='approvals', null=True) -# activity = models.CharField(max_length=255) -# region = models.CharField(max_length=255) -# tenure = models.CharField(max_length=255,null=True) -# title = models.CharField(max_length=255) - renewal_document = models.ForeignKey(ApprovalDocument, blank=True, null=True, related_name='renewal_document') - renewal_sent = models.BooleanField(default=False) - issue_date = models.DateTimeField() - original_issue_date = models.DateField(auto_now_add=True) - start_date = models.DateField() - expiry_date = models.DateField() - surrender_details = JSONField(blank=True,null=True) - suspension_details = JSONField(blank=True,null=True) - submitter = models.ForeignKey(EmailUser, on_delete=models.PROTECT, blank=True, null=True, related_name='commercialoperator_approvals') - org_applicant = models.ForeignKey(Organisation,on_delete=models.PROTECT, blank=True, null=True, related_name='org_approvals') - proxy_applicant = models.ForeignKey(EmailUser,on_delete=models.PROTECT, blank=True, null=True, related_name='proxy_approvals') - extracted_fields = JSONField(blank=True, null=True) - cancellation_details = models.TextField(blank=True) - extend_details = models.TextField(blank=True) - cancellation_date = models.DateField(blank=True, null=True) - set_to_cancel = models.BooleanField(default=False) - set_to_suspend = models.BooleanField(default=False) - set_to_surrender = models.BooleanField(default=False) - - #application_type = models.ForeignKey(ApplicationType, null=True, blank=True) - renewal_count = models.PositiveSmallIntegerField('Number of times an Approval has been renewed', default=0) - migrated=models.BooleanField(default=False) - - class Meta: - app_label = 'commercialoperator' - unique_together= ('lodgement_number', 'issue_date') - - @property - def bpay_allowed(self): - if self.org_applicant: - return self.org_applicant.bpay_allowed - return False - - @property - def monthly_invoicing_allowed(self): - if self.org_applicant: - return self.org_applicant.monthly_invoicing_allowed - return False - - @property - def monthly_invoicing_period(self): - if self.org_applicant: - return self.org_applicant.monthly_invoicing_period - return None - - @property - def monthly_payment_due_period(self): - if self.org_applicant: - return self.org_applicant.monthly_payment_due_period - return None - - @property - def applicant(self): - if self.org_applicant: - return self.org_applicant.organisation.name - elif self.proxy_applicant: - return "{} {}".format( - self.proxy_applicant.first_name, - self.proxy_applicant.last_name) - else: - #return None - try: - return "{} {}".format( - self.submitter.first_name, - self.submitter.last_name) - except: - return "Applicant Not Set" - - @property - def linked_applications(self): - ids = Proposal.objects.filter(approval__lodgement_number=self.lodgement_number).values_list('id', flat=True) - all_linked_ids = Proposal.objects.filter(Q(previous_application__in=ids) | Q(id__in=ids)).values_list('lodgement_number', flat=True) - return all_linked_ids - - @property - def applicant_type(self): - if self.org_applicant: - return "org_applicant" - elif self.proxy_applicant: - return "proxy_applicant" - else: - #return None - return "submitter" - - @property - def is_org_applicant(self): - return True if self.org_applicant else False - - @property - def applicant_id(self): - if self.org_applicant: - #return self.org_applicant.organisation.id - return self.org_applicant.id - elif self.proxy_applicant: - return self.proxy_applicant.id - else: - #return None - return self.submitter.id - - @property - def region(self): - return self.current_proposal.region.name - - @property - def district(self): - return self.current_proposal.district.name - - @property - def tenure(self): - return self.current_proposal.tenure.name - - @property - def activity(self): - return self.current_proposal.activity - - @property - def title(self): - return self.current_proposal.title - - @property - def next_id(self): - #ids = map(int,[(i.lodgement_number.split('A')[1]) for i in Approval.objects.all()]) - ids = map(int,[i.split('L')[1] for i in Approval.objects.all().values_list('lodgement_number', flat=True) if i]) - return max(ids) + 1 if ids else 1 - - def save(self, *args, **kwargs): - if self.lodgement_number in ['', None]: - self.lodgement_number = 'L{0:06d}'.format(self.next_id) - #self.save() - super(Approval, self).save(*args,**kwargs) - - def __str__(self): - return self.lodgement_number - - @property - def reference(self): - return 'L{}'.format(self.id) - - @property - def can_reissue(self): - return self.status == 'current' or self.status == 'suspended' - - @property - def can_reinstate(self): - return (self.status == 'cancelled' or self.status == 'suspended' or self.status == 'surrendered') and self.can_action - - @property - def allowed_assessors(self): - return self.current_proposal.allowed_assessors - - - def is_assessor(self,user): - return self.current_proposal.is_assessor(user) - - - def is_approver(self,user): - return self.current_proposal.is_approver(user) - - - @property - def is_issued(self): - return self.licence_number is not None and len(self.licence_number) > 0 - - @property - def can_action(self): - if not (self.set_to_cancel or self.set_to_suspend or self.set_to_surrender): - return True - else: - return False - - - - @property - def can_extend(self): - if self.current_proposal.application_type.name == 'E Class': - return self.current_proposal.application_type.max_renewals > self.renewal_count - return False - - - @property - def can_renew(self): - try: -# if self.current_proposal.application_type.name == 'E Class': -# #return (self.current_proposal.application_type.max_renewals is not None and self.current_proposal.application_type.max_renewals > self.renewal_count) -# return self.current_proposal.application_type.max_renewals > self.renewal_count -# #pass -# else: - renew_conditions = { - 'previous_application': self.current_proposal, - 'proposal_type': 'renewal' - } - proposal=Proposal.objects.get(**renew_conditions) - if proposal: - return False - except Proposal.DoesNotExist: - return True - - @property - def can_amend(self): - try: - amend_conditions = { - 'previous_application': self.current_proposal, - 'proposal_type': 'amendment' - } - proposal=Proposal.objects.get(**amend_conditions) - if proposal: - return False - except Proposal.DoesNotExist: - if self.can_renew: - return True - else: - return False - - - def generate_doc(self, user, preview=False): - from commercialoperator.components.approvals.pdf import create_approval_doc, create_approval_pdf_bytes - copied_to_permit = self.copiedToPermit_fields(self.current_proposal) #Get data related to isCopiedToPermit tag - - if preview: - return create_approval_pdf_bytes(self,self.current_proposal, copied_to_permit, user) - - self.licence_document = create_approval_doc(self,self.current_proposal, copied_to_permit, user) - self.save(version_comment='Created Approval PDF: {}'.format(self.licence_document.name)) - self.current_proposal.save(version_comment='Created Approval PDF: {}'.format(self.licence_document.name)) - -# def generate_preview_doc(self, user): -# from commercialoperator.components.approvals.pdf import create_approval_pdf_bytes -# copied_to_permit = self.copiedToPermit_fields(self.current_proposal) #Get data related to isCopiedToPermit tag - - def generate_renewal_doc(self): - from commercialoperator.components.approvals.pdf import create_renewal_doc - self.renewal_document = create_renewal_doc(self,self.current_proposal) - self.save(version_comment='Created Approval PDF: {}'.format(self.renewal_document.name)) - self.current_proposal.save(version_comment='Created Approval PDF: {}'.format(self.renewal_document.name)) - - def copiedToPermit_fields(self, proposal): - p=proposal - copied_data = [] - search_assessor_data = [] - search_schema = search_multiple_keys(p.schema, primary_search='isCopiedToPermit', search_list=['label', 'name']) - if p.assessor_data: - search_assessor_data=search_keys(p.assessor_data, search_list=['assessor', 'name']) - if search_schema: - for c in search_schema: - try: - if search_assessor_data: - for d in search_assessor_data: - if c['name'] == d['name']: - if d['assessor']: - #copied_data.append({c['label'], d['assessor']}) - copied_data.append({c['label']:d['assessor']}) - except: - raise - return copied_data - - - def log_user_action(self, action, request): - return ApprovalUserAction.log_action(self, action, request.user) - - - def expire_approval(self,user): - with transaction.atomic(): - try: - today = timezone.localtime(timezone.now()).date() - if self.status == 'current' and self.expiry_date < today: - self.status = 'expired' - self.save() - send_approval_expire_email_notification(self) - proposal = self.current_proposal - ApprovalUserAction.log_action(self,ApprovalUserAction.ACTION_EXPIRE_APPROVAL.format(self.id),user) - ProposalUserAction.log_action(proposal,ProposalUserAction.ACTION_EXPIRED_APPROVAL_.format(proposal.id),user) - except: - raise - - def approval_extend(self,request,details): - with transaction.atomic(): - try: - if not request.user in self.allowed_assessors: - raise ValidationError('You do not have access to extend this approval') - if not self.can_extend and self.can_action: - raise ValidationError('You cannot extend approval any further') - self.renewal_count += 1 - self.extend_details = details.get('extend_details') - self.expiry_date = datetime.date(self.expiry_date.year + self.current_proposal.application_type.max_renewal_period, self.expiry_date.month, self.expiry_date.day) - today = timezone.now().date() - if self.expiry_date <= today: - if not self.status == 'extended': - self.status = 'extended' - #send_approval_extend_email_notification(self) - self.save() - # Log proposal action - self.log_user_action(ApprovalUserAction.ACTION_EXTEND_APPROVAL.format(self.id),request) - # Log entry for organisation - self.current_proposal.log_user_action(ProposalUserAction.ACTION_EXTEND_APPROVAL.format(self.current_proposal.id),request) - except: - raise - - - def approval_cancellation(self,request,details): - with transaction.atomic(): - try: - if not request.user in self.allowed_assessors: - raise ValidationError('You do not have access to cancel this approval') - if not self.can_reissue and self.can_action: - raise ValidationError('You cannot cancel approval if it is not current or suspended') - self.cancellation_date = details.get('cancellation_date').strftime('%Y-%m-%d') - self.cancellation_details = details.get('cancellation_details') - cancellation_date = datetime.datetime.strptime(self.cancellation_date,'%Y-%m-%d') - cancellation_date = cancellation_date.date() - self.cancellation_date = cancellation_date # test hack - today = timezone.now().date() - if cancellation_date <= today: - if not self.status == 'cancelled': - self.status = 'cancelled' - self.set_to_cancel = False - send_approval_cancel_email_notification(self) - else: - self.set_to_cancel = True - self.save() - # Log proposal action - self.log_user_action(ApprovalUserAction.ACTION_CANCEL_APPROVAL.format(self.id),request) - # Log entry for organisation - self.current_proposal.log_user_action(ProposalUserAction.ACTION_CANCEL_APPROVAL.format(self.current_proposal.id),request) - except: - raise - - def approval_suspension(self,request,details): - with transaction.atomic(): - try: - if not request.user in self.allowed_assessors: - raise ValidationError('You do not have access to suspend this approval') - if not self.can_reissue and self.can_action: - raise ValidationError('You cannot suspend approval if it is not current or suspended') - if details.get('to_date'): - to_date= details.get('to_date').strftime('%d/%m/%Y') - else: - to_date='' - self.suspension_details = { - 'from_date' : details.get('from_date').strftime('%d/%m/%Y'), - 'to_date' : to_date, - 'details': details.get('suspension_details'), - } - today = timezone.now().date() - from_date = datetime.datetime.strptime(self.suspension_details['from_date'],'%d/%m/%Y') - from_date = from_date.date() - if from_date <= today: - if not self.status == 'suspended': - self.status = 'suspended' - self.set_to_suspend = False - self.save() - send_approval_suspend_email_notification(self) - else: - self.set_to_suspend = True - self.save() - # Log approval action - self.log_user_action(ApprovalUserAction.ACTION_SUSPEND_APPROVAL.format(self.id),request) - # Log entry for proposal - self.current_proposal.log_user_action(ProposalUserAction.ACTION_SUSPEND_APPROVAL.format(self.current_proposal.id),request) - except: - raise - - def reinstate_approval(self,request): - with transaction.atomic(): - try: - if not request.user in self.allowed_assessors: - raise ValidationError('You do not have access to reinstate this approval') - if not self.can_reinstate: - #if not self.status == 'suspended': - raise ValidationError('You cannot reinstate approval at this stage') - today = timezone.now().date() - if not self.can_reinstate and self.expiry_date>= today: - #if not self.status == 'suspended' and self.expiry_date >= today: - raise ValidationError('You cannot reinstate approval at this stage') - if self.status == 'cancelled': - self.cancellation_details = '' - self.cancellation_date = None - if self.status == 'surrendered': - self.surrender_details = {} - if self.status == 'suspended': - self.suspension_details = {} - - self.status = 'current' - #self.suspension_details = {} - self.save() - send_approval_reinstate_email_notification(self, request) - # Log approval action - self.log_user_action(ApprovalUserAction.ACTION_REINSTATE_APPROVAL.format(self.id),request) - # Log entry for proposal - self.current_proposal.log_user_action(ProposalUserAction.ACTION_REINSTATE_APPROVAL.format(self.current_proposal.id),request) - except: - raise - - def approval_surrender(self,request,details): - with transaction.atomic(): - try: - if not request.user.commercialoperator_organisations.filter(organisation_id = self.applicant_id): - if request.user not in self.allowed_assessors and not is_customer(request): - raise ValidationError('You do not have access to surrender this approval') - if not self.can_reissue and self.can_action: - raise ValidationError('You cannot surrender approval if it is not current or suspended') - self.surrender_details = { - 'surrender_date' : details.get('surrender_date').strftime('%d/%m/%Y'), - 'details': details.get('surrender_details'), - } - today = timezone.now().date() - surrender_date = datetime.datetime.strptime(self.surrender_details['surrender_date'],'%d/%m/%Y') - surrender_date = surrender_date.date() - if surrender_date <= today: - if not self.status == 'surrendered': - self.status = 'surrendered' - self.set_to_surrender = False - self.save() - send_approval_surrender_email_notification(self) - else: - self.set_to_surrender = True - self.save() - # Log approval action - self.log_user_action(ApprovalUserAction.ACTION_SURRENDER_APPROVAL.format(self.id),request) - # Log entry for proposal - self.current_proposal.log_user_action(ProposalUserAction.ACTION_SURRENDER_APPROVAL.format(self.current_proposal.id),request) - except: - raise - - -class PreviewTempApproval(Approval): - class Meta: - app_label = 'commercialoperator' - #unique_together= ('lodgement_number', 'issue_date') - - -class ApprovalLogEntry(CommunicationsLogEntry): - approval = models.ForeignKey(Approval, related_name='comms_logs') - - class Meta: - app_label = 'commercialoperator' - - def save(self, **kwargs): - # save the application reference if the reference not provided - if not self.reference: - self.reference = self.approval.id - super(ApprovalLogEntry, self).save(**kwargs) - -class ApprovalLogDocument(Document): - log_entry = models.ForeignKey('ApprovalLogEntry',related_name='documents', null=True,) - #approval = models.ForeignKey(Approval, related_name='comms_logs1') - _file = models.FileField(upload_to=update_approval_comms_log_filename, null=True) - #_file = models.FileField(upload_to=update_approval_doc_filename) - - class Meta: - app_label = 'commercialoperator' - -class ApprovalUserAction(UserAction): - ACTION_CREATE_APPROVAL = "Create licence {}" - ACTION_UPDATE_APPROVAL = "Create licence {}" - ACTION_EXPIRE_APPROVAL = "Expire licence {}" - ACTION_CANCEL_APPROVAL = "Cancel licence {}" - ACTION_EXTEND_APPROVAL = "Extend licence {}" - ACTION_SUSPEND_APPROVAL = "Suspend licence {}" - ACTION_REINSTATE_APPROVAL = "Reinstate licence {}" - ACTION_SURRENDER_APPROVAL = "surrender licence {}" - ACTION_RENEW_APPROVAL = "Create renewal Application for licence {}" - ACTION_AMEND_APPROVAL = "Create amendment Application for licence {}" - - - class Meta: - app_label = 'commercialoperator' - ordering = ('-when',) - - @classmethod - def log_action(cls, approval, action, user): - return cls.objects.create( - approval=approval, - who=user, - what=str(action) - ) - - approval= models.ForeignKey(Approval, related_name='action_logs') - -@receiver(pre_delete, sender=Approval) -def delete_documents(sender, instance, *args, **kwargs): - for document in instance.documents.all(): - try: - document.delete() - except: - pass - -#import reversion -#reversion.register(Approval, follow=['documents', 'approval_set', 'action_logs']) -#reversion.register(ApprovalDocument) -#reversion.register(ApprovalLogDocument, follow=['documents']) -#reversion.register(ApprovalLogEntry) -#reversion.register(ApprovalUserAction) - -import reversion -reversion.register(Approval, follow=['compliances', 'documents', 'comms_logs', 'action_logs']) -reversion.register(ApprovalDocument, follow=['licence_document', 'cover_letter_document', 'renewal_document']) -reversion.register(ApprovalLogEntry, follow=['documents']) -reversion.register(ApprovalLogDocument) -reversion.register(ApprovalUserAction) - diff --git a/commercialoperator/components/approvals/pdf.py b/commercialoperator/components/approvals/pdf.py deleted file mode 100755 index 8b8e6eeae1..0000000000 --- a/commercialoperator/components/approvals/pdf.py +++ /dev/null @@ -1,741 +0,0 @@ -import os -from io import BytesIO -from datetime import date - -from reportlab.lib import enums -from reportlab.lib.pagesizes import A4 -from reportlab.platypus import BaseDocTemplate, PageTemplate, Frame, Paragraph, Spacer, Table, TableStyle, ListFlowable, \ - KeepTogether, PageBreak, ListItem -from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle -from reportlab.lib.utils import ImageReader -from reportlab.lib.colors import HexColor, black - -from django.core.files import File -from django.conf import settings -from django.core.exceptions import ValidationError - -from commercialoperator.components.approvals.models import ApprovalDocument - -#BW_DPAW_HEADER_LOGO = os.path.join(settings.BASE_DIR, 'wildlifelicensing', 'static', 'wl', 'img', -# 'bw_dpaw_header_logo.png') - -BW_DPAW_HEADER_LOGO = os.path.join(settings.BASE_DIR, 'commercialoperator', 'static', 'commercialoperator', 'img', - 'dbca-logo.jpg') - -COLOUR_DPAW_HEADER_LOGO = os.path.join(settings.BASE_DIR, 'wildlifelicensing', 'static', 'wl', 'img', - 'colour_dpaw_header_logo.png') - -#LICENCE_HEADER_IMAGE_WIDTH = 170 -LICENCE_HEADER_IMAGE_WIDTH = 320 -#LICENCE_HEADER_IMAGE_HEIGHT = 42 -LICENCE_HEADER_IMAGE_HEIGHT = 60 - -DPAW_EMAIL = settings.SUPPORT_EMAIL -DPAW_URL = settings.DEP_URL -DPAW_PHONE = settings.DEP_PHONE -DPAW_FAX = settings.DEP_FAX -DPAW_PO_BOX = settings.DEP_POSTAL - - -PAGE_WIDTH, PAGE_HEIGHT = A4 - -DEFAULT_FONTNAME = 'Helvetica' -BOLD_FONTNAME = 'Helvetica-Bold' -ITALIC_FONTNAME = 'Helvetica-Oblique' -BOLD_ITALIC_FONTNAME = 'Helvetica-BoldOblique' - -VERY_LARGE_FONTSIZE = 14 -LARGE_FONTSIZE = 12 -MEDIUM_FONTSIZE = 10 -SMALL_FONTSIZE = 8 - -PARAGRAPH_BOTTOM_MARGIN = 5 - -SECTION_BUFFER_HEIGHT = 10 - -DATE_FORMAT = '%d/%m/%Y' -DATE_FORMAT2 = '%d %B %Y' - -HEADER_MARGIN = 10 -HEADER_SMALL_BUFFER = 3 - -PAGE_MARGIN = 20 -PAGE_TOP_MARGIN = 200 - -LETTER_HEADER_MARGIN = 30 -LETTER_PAGE_MARGIN = 60 -LETTER_IMAGE_WIDTH = 242 -LETTER_IMAGE_HEIGHT = 55 -LETTER_HEADER_RIGHT_LABEL_OFFSET = 400 -LETTER_HEADER_RIGHT_INFO_OFFSET = 450 -LETTER_HEADER_SMALL_BUFFER = 5 -LETTER_ADDRESS_BUFFER_HEIGHT = 40 -LETTER_BLUE_FONT = 0x045690 - -styles = getSampleStyleSheet() -styles.add(ParagraphStyle(name='InfoTitleLargeCenter', fontName=BOLD_FONTNAME, fontSize=LARGE_FONTSIZE, - spaceAfter=PARAGRAPH_BOTTOM_MARGIN, alignment=enums.TA_CENTER)) -styles.add(ParagraphStyle(name='InfoTitleVeryLargeCenter', fontName=BOLD_FONTNAME, fontSize=VERY_LARGE_FONTSIZE, - spaceAfter=PARAGRAPH_BOTTOM_MARGIN * 2, alignment=enums.TA_CENTER)) -styles.add(ParagraphStyle(name='InfoTitleLargeLeft', fontName=BOLD_FONTNAME, fontSize=LARGE_FONTSIZE, - spaceAfter=PARAGRAPH_BOTTOM_MARGIN, alignment=enums.TA_LEFT, - leftIndent=PAGE_WIDTH / 10, rightIndent=PAGE_WIDTH / 10)) -styles.add(ParagraphStyle(name='InfoTitleLargeRight', fontName=BOLD_FONTNAME, fontSize=LARGE_FONTSIZE, - spaceAfter=PARAGRAPH_BOTTOM_MARGIN, alignment=enums.TA_RIGHT, - rightIndent=PAGE_WIDTH / 10)) -styles.add(ParagraphStyle(name='BoldLeft', fontName=BOLD_FONTNAME, fontSize=MEDIUM_FONTSIZE, alignment=enums.TA_LEFT)) -styles.add(ParagraphStyle(name='BoldRight', fontName=BOLD_FONTNAME, fontSize=MEDIUM_FONTSIZE, alignment=enums.TA_RIGHT)) -styles.add(ParagraphStyle(name='BoldCenter', fontName=BOLD_FONTNAME, fontSize=MEDIUM_FONTSIZE, alignment=enums.TA_CENTER)) -styles.add(ParagraphStyle(name='ItalicLeft', fontName=ITALIC_FONTNAME, fontSize=MEDIUM_FONTSIZE, alignment=enums.TA_LEFT)) -styles.add(ParagraphStyle(name='ItalifRight', fontName=ITALIC_FONTNAME, fontSize=MEDIUM_FONTSIZE, alignment=enums.TA_RIGHT)) -styles.add(ParagraphStyle(name='ItalicCenter', fontName=ITALIC_FONTNAME, fontSize=MEDIUM_FONTSIZE, alignment=enums.TA_CENTER)) -styles.add(ParagraphStyle(name='Center', alignment=enums.TA_CENTER)) -styles.add(ParagraphStyle(name='Left', alignment=enums.TA_LEFT)) -styles.add(ParagraphStyle(name='Right', alignment=enums.TA_RIGHT)) -styles.add(ParagraphStyle(name='LetterLeft', fontSize=LARGE_FONTSIZE, alignment=enums.TA_LEFT)) -styles.add(ParagraphStyle(name='LetterBoldLeft', fontName=BOLD_FONTNAME, fontSize=LARGE_FONTSIZE, alignment=enums.TA_LEFT)) -styles.add(ParagraphStyle(name='WebAddress', alignment=enums.TA_LEFT, textColor='blue')) - -def _create_approval_header(canvas, doc, draw_page_number=True): - canvas.setFont(BOLD_FONTNAME, LARGE_FONTSIZE) - - current_y = PAGE_HEIGHT - HEADER_MARGIN - - #canvas.drawCentredString(PAGE_WIDTH / 2, current_y - LARGE_FONTSIZE, '{}'.format(settings.DEP_NAME.upper())) - - current_y -= 30 - - dpaw_header_logo = ImageReader(BW_DPAW_HEADER_LOGO) - canvas.drawImage(dpaw_header_logo, HEADER_MARGIN, current_y - 58, - width=LICENCE_HEADER_IMAGE_WIDTH, height=LICENCE_HEADER_IMAGE_HEIGHT) - - current_x = HEADER_MARGIN + LICENCE_HEADER_IMAGE_WIDTH + 5 - - - # canvas.setFont(DEFAULT_FONTNAME, SMALL_FONTSIZE) - - # canvas.drawString(current_x, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER), 'Enquiries:') - # canvas.drawString(current_x, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER) * 2, 'Telephone:') - # canvas.drawString(current_x, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER) * 3, 'Facsimile:') - # canvas.drawString(current_x, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER) * 4, 'Web Site:') - # canvas.drawString(current_x, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER) * 5, 'Correspondance:') - - # current_x += 80 - - # canvas.drawString(current_x, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER), - # '17 DICK PERRY AVE, KENSINGTON, WESTERN AUSTRALIA') - # canvas.drawString(current_x, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER) * 2, '08 9219 9000') - # canvas.drawString(current_x, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER) * 3, '08 9219 8242') - # canvas.drawString(current_x, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER) * 4, doc.site_url) - - # canvas.setFont(BOLD_FONTNAME, SMALL_FONTSIZE) - # canvas.drawString(current_x, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER) * 5, 'Locked Bag 30') - # canvas.drawString(current_x, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER) * 6, - # 'Bentley Delivery Centre WA 6983') - - canvas.setFont(BOLD_FONTNAME, LARGE_FONTSIZE) - - #print current_x, current_y - - #current_y -= 36 - current_y -= 2 - #current_x += 10 - current_x += 150 - - if draw_page_number: - canvas.drawString(current_x, current_y - (LARGE_FONTSIZE + HEADER_SMALL_BUFFER), 'PAGE') - - if hasattr(doc, 'approval'): - canvas.drawString(current_x, current_y - (LARGE_FONTSIZE + HEADER_SMALL_BUFFER) * 2, 'NO.') - - canvas.setFont(DEFAULT_FONTNAME, LARGE_FONTSIZE) - - current_x += 50 - - if draw_page_number: - canvas.drawString(current_x, current_y - (LARGE_FONTSIZE + HEADER_SMALL_BUFFER), str(canvas.getPageNumber())) - - if hasattr(doc, 'approval'): - canvas.drawString(current_x, current_y - (LARGE_FONTSIZE + HEADER_SMALL_BUFFER) * 2, - '{}'.format(doc.approval.lodgement_number)) - -def _create_approval(approval_buffer, approval, proposal, copied_to_permit, user): - site_url = settings.SITE_URL - every_page_frame = Frame(PAGE_MARGIN, PAGE_MARGIN, PAGE_WIDTH - 2 * PAGE_MARGIN, - PAGE_HEIGHT - 160, id='EveryPagesFrame') - every_page_template = PageTemplate(id='EveryPages', frames=[every_page_frame], onPage=_create_approval_header) - - doc = BaseDocTemplate(approval_buffer, pageTemplates=[every_page_template], pagesize=A4) - - # this is the only way to get data into the onPage callback function - doc.approval = approval - doc.site_url = site_url - region = approval.region if hasattr(approval, 'region') else '' - district = approval.district if hasattr(approval, 'district') else '' - region_district = '{} - {}'.format(region, district) if district else region - - approval_table_style = TableStyle([('VALIGN', (0, 0), (-1, -1), 'TOP')]) - - elements = [] - - - title = approval.title.encode('UTF-8') if approval.title else '' - - #Organization details - - address = proposal.applicant_address - # address = proposal.applicant_address - if proposal.org_applicant: - email = proposal.org_applicant.organisation.organisation_set.all().first().contacts.all().first().email - else: - email= proposal.submitter.email - elements.append(Paragraph(email,styles['BoldLeft'])) - elements.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - elements.append(Paragraph(_format_name(approval.applicant),styles['BoldLeft'])) - elements.append(Paragraph(address.line1, styles['BoldLeft'])) - elements.append(Paragraph(address.line2, styles['BoldLeft'])) - elements.append(Paragraph(address.line3, styles['BoldLeft'])) - # if proposal.org_applicant: - # elements.append(Paragraph('%s %s %s' % (address.locality, address.state, address.postcode), styles['BoldLeft'])) - # else: - # elements.append(Paragraph('%s %s' % (address.state, address.postcode), styles['BoldLeft'])) - elements.append(Paragraph('%s %s %s' % (address.locality, address.state, address.postcode), styles['BoldLeft'])) - elements.append(Paragraph(address.country.name, styles['BoldLeft'])) - elements.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - elements.append(Paragraph(approval.issue_date.strftime(DATE_FORMAT), styles['BoldLeft'])) - elements.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - - #elements.append(Paragraph(title, styles['InfoTitleVeryLargeCenter'])) - #elements.append(Paragraph(approval.activity, styles['InfoTitleLargeLeft'])) - elements.append(Paragraph('APPROVAL OF PROPOSAL {} {} TO UNDERTAKE Commercial Operator Licensing ACTIVITY IN {}'.format(title, proposal.lodgement_number, region_district), styles['InfoTitleLargeLeft'])) - #elements.append(Paragraph(approval.tenure if hasattr(approval, 'tenure') else '', styles['InfoTitleLargeRight'])) - - elements.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - elements.append(Paragraph('The submitted proposal {} {} has been assessed and approved. The approval is granted on the understanding that: '.format(title, proposal.lodgement_number), styles['BoldLeft'])) - elements.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - - list_of_bullets= [] - list_of_bullets.append('The potential impacts of the proposal on values the department manages have been removed or minimised to a level \'As Low As Reasonably Practicable\' (ALARP) and the proposal is consistent with departmental objectives, associated management plans and the land use category/s in the activity area.') - list_of_bullets.append('Approval is granted for the period {} to {}. This approval is not valid if {} makes changes to what has been proposed or the proposal has expired. To change the proposal or seek an extension, the proponent must re-submit the proposal for assessment.'.format(approval.start_date.strftime(DATE_FORMAT), approval.expiry_date.strftime(DATE_FORMAT),_format_name(approval.applicant))) - list_of_bullets.append('The proponent accepts responsibility for advising {} of new information or unforeseen threats that may affect the risk of the proposed activity.'.format(settings.DEP_NAME_SHORT)) - list_of_bullets.append('Information provided by {0} for the purposes of this proposal will not be provided to third parties without permission from {0}.'.format(settings.DEP_NAME_SHORT)) - list_of_bullets.append('The proponent accepts responsibility for supervising and monitoring implementation of activity/ies to ensure compliance with this proposal. {} reserves the right to request documents and records demonstrating compliance for departmental monitoring and auditing.'.format(settings.DEP_NAME_SHORT)) - list_of_bullets.append('Non-compliance with the conditions of the proposal may trigger a suspension or withdrawal of the approval for this activity.') - list_of_bullets.append('Management actions listed in Appendix 1 are implemented.') - - understandingList = ListFlowable( - [ListItem(Paragraph(a, styles['Left']), bulletColour='black', value='circle') for a in list_of_bullets], - bulletFontName=BOLD_FONTNAME, bulletFontSize=SMALL_FONTSIZE, bulletType='bullet') - #bulletFontName=BOLD_FONTNAME - elements.append(understandingList) - - # proposal requirements - requirements = proposal.requirements.all().exclude(is_deleted=True) - if requirements.exists(): - elements.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - elements.append(Paragraph('The following requirements must be satisfied for the approval of the proposal not to be withdrawn:', styles['BoldLeft'])) - elements.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - - conditionList = ListFlowable( - [Paragraph(a.requirement, styles['Left']) for a in requirements.order_by('order')], - bulletFontName=BOLD_FONTNAME, bulletFontSize=MEDIUM_FONTSIZE) - elements.append(conditionList) - - # if copied_to_permit: - # elements.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - # elements.append(Paragraph('Assessor Comments', styles['BoldLeft'])) - # elements.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - - # for k,v in copied_to_permit: - # elements.append(Paragraph(v.encode('UTF-8'), styles['Left'])) - # elements.append(Paragraph(k.encode('UTF-8'), styles['Left'])) - # elements.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - - elements += _layout_extracted_fields(approval.extracted_fields) - - # additional information - '''if approval.additional_information: - elements.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - elements.append(Paragraph('Additional Information', styles['BoldLeft'])) - elements += _layout_paragraphs(approval.additional_information)''' - - # delegation holds the dates, approvale and issuer details. - delegation = [] - - # dates and licensing officer - # dates_licensing_officer_table_style = TableStyle([('VALIGN', (0, 0), (-2, -1), 'TOP'), - # ('VALIGN', (0, 0), (-1, -1), 'BOTTOM')]) - - # delegation.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - # date_headings = [Paragraph('Date of Issue', styles['BoldLeft']), Paragraph('Valid From', styles['BoldLeft']), - # Paragraph('Date of Expiry', styles['BoldLeft'])] - # date_values = [Paragraph(approval.issue_date.strftime(DATE_FORMAT), styles['Left']), - # Paragraph(approval.start_date.strftime(DATE_FORMAT), styles['Left']), - # Paragraph(approval.expiry_date.strftime(DATE_FORMAT), styles['Left'])] - - # if approval.original_issue_date is not None: - # date_headings.insert(0, Paragraph('Original Date of Issue', styles['BoldLeft'])) - # date_values.insert(0, Paragraph(approval.original_issue_date.strftime(DATE_FORMAT), styles['Left'])) - - # delegation.append(Table([[date_headings, date_values]], - # colWidths=(120, PAGE_WIDTH - (2 * PAGE_MARGIN) - 120), - # style=dates_licensing_officer_table_style)) - - # proponent details - # delegation.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - # address = proposal.applicant.organisation.postal_address - # address_paragraphs = [Paragraph(address.line1, styles['Left']), Paragraph(address.line2, styles['Left']), - # Paragraph(address.line3, styles['Left']), - # Paragraph('%s %s %s' % (address.locality, address.state, address.postcode), styles['Left']), - # Paragraph(address.country.name, styles['Left'])] - # delegation.append(Table([[[Paragraph('Licensee:', styles['BoldLeft']), Paragraph('Address', styles['BoldLeft'])], - # [Paragraph(_format_name(approval.applicant), - # styles['Left'])] + address_paragraphs]], - # colWidths=(120, PAGE_WIDTH - (2 * PAGE_MARGIN) - 120), - # style=approval_table_style)) - - delegation.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - delegation.append(Paragraph('Should you have any queries about this approval, please contact {} {}, ' - 'on {} or by email at {}'.format(user.first_name, user.last_name, settings.DEP_PHONE, user.email), styles['Left'])) - delegation.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - delegation.append(Paragraph('To provide feedback on the system used to submit the approval or update contact details, please ' - 'contact {} Works Coordinator - {}'.format(settings.SYSTEM_NAME_SHORT, settings.SUPPORT_EMAIL), styles['Left'])) - delegation.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - delegation.append(Paragraph('Approved on behalf of the', styles['Left'])) - delegation.append(Paragraph('{}'.format(settings.DEP_NAME), styles['BoldLeft'])) - delegation.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - delegation.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - - delegation.append(Paragraph('{} {}'.format(user.first_name, user.last_name), styles['Left'])) - delegation.append(Paragraph('{}'.format(region_district), styles['Left'])) - delegation.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - delegation.append(Paragraph(approval.issue_date.strftime(DATE_FORMAT), styles['Left'])) - - elements.append(KeepTogether(delegation)) - - # Appendix section - elements.append(PageBreak()) - elements.append(Paragraph('Appendix 1 - Management Actions', styles['BoldLeft'])) - elements.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - if copied_to_permit: - # for k,v in copied_to_permit: - # elements.append(Paragraph(v.encode('UTF-8'), styles['Left'])) - # elements.append(Paragraph(k.encode('UTF-8'), styles['Left'])) - # elements.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - for item in copied_to_permit: - for key in item: - elements.append(Paragraph(key.encode('UTF-8'), styles['Left'])) - elements.append(Paragraph(item[key].encode('UTF-8'), styles['Left'])) - else: - elements.append(Paragraph('There are no management actions.', styles['Left'])) - - - doc.build(elements) - - return approval_buffer - -def _create_approval_cols(approval_buffer, approval, proposal, copied_to_permit, user): - site_url = settings.SITE_URL - every_page_frame = Frame(PAGE_MARGIN, PAGE_MARGIN, PAGE_WIDTH - 2 * PAGE_MARGIN, - PAGE_HEIGHT - 160, id='EveryPagesFrame') - every_page_template = PageTemplate(id='EveryPages', frames=[every_page_frame], onPage=_create_approval_header) - - doc = BaseDocTemplate(approval_buffer, pageTemplates=[every_page_template], pagesize=A4) - - # this is the only way to get data into the onPage callback function - doc.approval = approval - doc.site_url = site_url - - approval_table_style = TableStyle([('VALIGN', (0, 0), (-1, -1), 'TOP')]) - box_table_style = TableStyle([('VALIGN', (0, 0), (-1, -1), 'TOP'), ('BOX', (0,0), (-1,-1), 0.25, black), ('INNERGRID', (0,0), (-1,-1), 0.25, black), ('ALIGN', (0, 0), (-1, -1), 'RIGHT')]) - - elements = [] - - #Organization details - - address = proposal.applicant_address - # address = proposal.applicant_address - if proposal.org_applicant: - try: - email = proposal.org_applicant.organisation.organisation_set.all().first().contacts.all().first().email - except: - raise ValidationError('There is no contact for Organisation. Please create an Organisation contact') - else: - email= proposal.submitter.email - #elements.append(Paragraph(email,styles['BoldLeft'])) - elements.append(Paragraph('CONSERVATION AND LAND MANAGEMENT REGULATIONS 2002 (PART 7)', styles['ItalicCenter'])) - elements.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - elements.append(Paragraph('COMMERCIAL OPERATIONS LICENCE', styles['InfoTitleVeryLargeCenter'])) - elements.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - - elements.append(Paragraph('The Chief Executive Officer (CEO) of the Department of Biodiversity, Conservation and Attractions hereby grants a commercial operations licence to enter upon and conduct activities within the parks/reserves listed in Schedule 1 of this licence to:', styles['BoldLeft'])) - elements.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - - # delegation holds the Licence number and applicant name in table format. - delegation = [] - delegation.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - delegation.append(Table([[[Paragraph('Licensee:', styles['BoldLeft'])], - [Paragraph(_format_name(approval.applicant), - styles['Left'])]]], - colWidths=(120, PAGE_WIDTH - (2 * PAGE_MARGIN) - 120), - style=approval_table_style)) - - if approval.current_proposal.org_applicant and approval.current_proposal.org_applicant.organisation.trading_name: - delegation.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - delegation.append(Table([[[Paragraph('Trading Name:', styles['BoldLeft'])], - [Paragraph(_format_name(approval.current_proposal.org_applicant.organisation.trading_name), - styles['Left'])]]], - colWidths=(120, PAGE_WIDTH - (2 * PAGE_MARGIN) - 120), - style=approval_table_style)) - - - delegation.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - delegation.append(Table([[[Paragraph('Licence Number:', styles['BoldLeft'])], - [Paragraph(approval.lodgement_number, - styles['Left'])]]], - colWidths=(120, PAGE_WIDTH - (2 * PAGE_MARGIN) - 120), - style=approval_table_style)) - - delegation.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - - - elements.append(KeepTogether(delegation)) - - elements.append(Paragraph('Commencing on the {} and expiring on {}.'.format(approval.start_date.strftime(DATE_FORMAT2), approval.expiry_date.strftime(DATE_FORMAT2)),styles['BoldLeft'])) - - elements.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - elements.append(Paragraph('CONDITIONS', styles['BoldLeft'])) - elements.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - - list_of_bullets= [] - list_of_bullets.append('This Commercial Operations Licence is subject to the provisions of the Conservation and Land Management Act 1984 and all subsidiary legislation made under it.') - list_of_bullets.append('The Licensee must comply with and not contravene the conditions and restrictions set out in the Commercial Operator Handbook as varied from time to time by the CEO.') - list_of_bullets.append('The Licensee must comply with the conditions contained in any schedule of conditions attached to this Commercial Operations Licence.') - - understandingList = ListFlowable( - [ListItem(Paragraph(a, styles['Left']), bulletColour='black') for a in list_of_bullets], - bulletFontName=BOLD_FONTNAME, bulletFontSize=MEDIUM_FONTSIZE) - #bulletFontName=BOLD_FONTNAME - elements.append(understandingList) - - # proposal requirements - # requirements = proposal.requirements.all().exclude(is_deleted=True) - # if requirements.exists(): - # elements.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - # elements.append(Paragraph('The following requirements must be satisfied for the licence not to be withdrawn:', styles['BoldLeft'])) - # elements.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - - # conditionList = ListFlowable( - # [Paragraph(a.requirement, styles['Left']) for a in requirements.order_by('order')], - # bulletFontName=BOLD_FONTNAME, bulletFontSize=MEDIUM_FONTSIZE) - # elements.append(conditionList) - - elements += _layout_extracted_fields(approval.extracted_fields) - - elements.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - elements.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - - elements.append(Paragraph('{} {}'.format(user.first_name, user.last_name), styles['Left'])) - if user.position_title: - elements.append(Paragraph('{}'.format(user.position_title), styles['Left'])) - elements.append(Paragraph('As Delegate of CEO', styles['Left'])) - elements.append(Paragraph('Under Section 133(2) of the CALM Act 1984', styles['Left'])) - elements.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - elements.append(Paragraph(approval.issue_date.strftime(DATE_FORMAT), styles['Left'])) - - elements.append(PageBreak()) - elements.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - table_data=[[Paragraph('Licence Number', styles['BoldLeft']), Paragraph(_format_name(approval.lodgement_number), styles['Left'])], - [Paragraph('Commencement Date', styles['BoldLeft']), Paragraph(_format_name(approval.start_date).strftime(DATE_FORMAT), styles['Left'])], - [Paragraph('Expiry Date', styles['BoldLeft']), Paragraph(_format_name(approval.expiry_date).strftime(DATE_FORMAT), styles['Left'])]] - t=Table(table_data, colWidths=(120, PAGE_WIDTH - (2 * PAGE_MARGIN) - 120), - style=box_table_style) - elements.append(t) - - # Schedule 1 - elements.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - elements.append(Paragraph('SCHEDULE 1', styles['BoldCenter'])) - elements.append(Paragraph('COMMERCIAL OPERATIONS LICENCE ACTIVITIES', styles['BoldCenter'])) - - elements.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - park_data=[] - for p in approval.current_proposal.selected_parks_activities_pdf: - #park_data.append([Paragraph(_format_name(p['park']), styles['BoldLeft']), - # [Paragraph(a, styles['Left']) for a in p['activities']]]) - activities_str=[] - for ac in p['activities']: - activities_str.append(ac.encode('UTF-8')) - activities_str=str(activities_str).strip('[]').replace('\'', '') - park_data.append([Paragraph(_format_name(p['park']), styles['BoldLeft']), - Paragraph(activities_str, styles['Left'])]) - if park_data: - t=Table(park_data, colWidths=(120, PAGE_WIDTH - (2 * PAGE_MARGIN) - 120), - style=box_table_style) - elements.append(t) - - # Schedule 2 - elements.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - elements.append(Paragraph('SCHEDULE 2', styles['BoldCenter'])) - elements.append(Paragraph('COMMERCIAL OPERATIONS LICENCE LAND ACCESS TYPES', styles['BoldCenter'])) - - elements.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - park_data=[] - for p in approval.current_proposal.selected_parks_access_types_pdf: - access_types_str=[] - for ac in p['access_types']: - access_types_str.append(ac.encode('UTF-8')) - access_types_str = ', '.join(access_types_str).replace('\'', '') - park_data.append([Paragraph(_format_name(p['park']), styles['BoldLeft']), - Paragraph(access_types_str, styles['Left'])]) - if park_data: - t=Table(park_data, colWidths=(120, PAGE_WIDTH - (2 * PAGE_MARGIN) - 120), - style=box_table_style) - elements.append(t) - - # Schedule 3 - elements.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - elements.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - elements.append(Paragraph('SCHEDULE 3', styles['BoldCenter'])) - elements.append(Paragraph('COMMERCIAL OPERATIONS LICENCE CONDITIONS', styles['BoldCenter'])) - requirements = proposal.requirements.all().exclude(is_deleted=True) - if requirements.exists(): - elements.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - #elements.append(Paragraph('The following requirements must be satisfied for the licence not to be withdrawn:', styles['BoldLeft'])) - #elements.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - - conditionList = ListFlowable( - [Paragraph(a.requirement, styles['Left']) for a in requirements.order_by('order')], - bulletFontName=BOLD_FONTNAME, bulletFontSize=MEDIUM_FONTSIZE) - elements.append(conditionList) - - doc.build(elements) - - return approval_buffer - -def _format_name(applicant): - #return org.name - return applicant - -def _layout_extracted_fields(extracted_fields): - elements = [] - - def __children_have_data(field): - for group in field.get('children', []): - for child_field in group: - if child_field.get('data'): - return True - - return False - - # information extracted from application - if extracted_fields: - for field in extracted_fields: - if 'children' not in field: - if 'data' in field and field['data']: - elements.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - elements.append(Paragraph(field['label'], styles['BoldLeft'])) - - if field['help_text']: - elements.append(Paragraph(field['help_text'], styles['ItalicLeft'])) - - elements.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - - if field['type'] in ['text', 'text_area']: - elements += _layout_paragraphs(field['data']) - elif field['type'] in ['radiobuttons', 'select']: - elements.append(Paragraph(dict([i.values() for i in field['options']]). - get(field['data'], 'Not Specified'), styles['Left'])) - else: - elements.append(Paragraph(field['data'], styles['Left'])) - - elif field['type'] == 'label': - if any([option.get('data', 'off') == 'on' for option in field['options']]): - elements.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - elements.append(Paragraph(field['label'], styles['BoldLeft'])) - - if field['help_text']: - elements.append(Paragraph(field['help_text'], styles['ItalicLeft'])) - - elements.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - - elements.append(Paragraph(', '.join([option['label'] for option in field['options'] - if option.get('data', 'off') == 'on']), - styles['Left'])) - else: - if not __children_have_data(field): - continue - - elements.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - elements.append(Paragraph(field['label'], styles['BoldLeft'])) - - if field['help_text']: - elements.append(Paragraph(field['help_text'], styles['ItalicLeft'])) - - table_data = [] - for index, group in enumerate(field['children']): - if index == 0: - heading_row = [] - for child_field in group: - heading_row.append(Paragraph(child_field['label'], styles['BoldLeft'])) - if heading_row: - table_data.append(heading_row) - - row = [] - for child_field in group: - if child_field['type'] in ['radiobuttons', 'select']: - row.append(Paragraph(dict([i.values() for i in child_field['options']]). - get(child_field['data'], 'Not Specified'), styles['Left'])) - elif child_field['type'] == 'label': - if any([option.get('data', 'off') == 'on' for option in child_field['options']]): - row.append(Paragraph(', '.join([option['label'] for option in child_field['options'] - if option.get('data', 'off') == 'on']), - styles['Left'])) - else: - row.append(Paragraph('Not Specified', styles['Left'])) - else: - row.append(Paragraph(child_field['data'], styles['Left'])) - - if row: - table_data.append(row) - - if table_data: - elements.append(Table(table_data, style=TableStyle([('VALIGN', (0, 0), (-1, -1), 'TOP')]))) - - return elements - -def create_approval_doc(approval,proposal, copied_to_permit, user): - approval_buffer = BytesIO() - - #_create_approval(approval_buffer, approval, proposal, copied_to_permit, user) - _create_approval_cols(approval_buffer, approval, proposal, copied_to_permit, user) - filename = 'licence-{}.pdf'.format(approval.lodgement_number) - document = ApprovalDocument.objects.create(approval=approval,name=filename) - document._file.save(filename, File(approval_buffer), save=True) - - approval_buffer.close() - return document - -def create_approval_pdf_bytes(approval,proposal, copied_to_permit, user): - """ Essentially the same as create_approval_doc() - but used to preview the licence without creation """ - licence_buffer = BytesIO() - _create_approval_cols(licence_buffer, approval, proposal, copied_to_permit, user) - - # Get the value of the BytesIO buffer - value = licence_buffer.getvalue() - licence_buffer.close() - return value - -def create_renewal_doc(approval,proposal): - renewal_buffer = BytesIO() - - _create_renewal(renewal_buffer, approval, proposal) - filename = 'renewal-{}.pdf'.format(approval.id) - document = ApprovalDocument.objects.create(approval=approval,name=filename) - document._file.save(filename, File(renewal_buffer), save=True) - - renewal_buffer.close() - return document - -def _create_renewal(renewal_buffer, approval, proposal): - site_url = settings.SITE_URL - every_page_frame = Frame(PAGE_MARGIN, PAGE_MARGIN, PAGE_WIDTH - 2 * PAGE_MARGIN, - PAGE_HEIGHT - 160, id='EveryPagesFrame') - every_page_template = PageTemplate(id='EveryPages', frames=[every_page_frame], onPage=_create_approval_header) - - doc = BaseDocTemplate(renewal_buffer, pageTemplates=[every_page_template], pagesize=A4) - - # this is the only way to get data into the onPage callback function - doc.approval = approval - doc.site_url = site_url - - approval_table_style = TableStyle([('VALIGN', (0, 0), (-1, -1), 'TOP')]) - - elements = [] - - - #title = approval.title.encode('UTF-8') - title='' - # additional information - '''if approval.additional_information: - elements.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - elements.append(Paragraph('Additional Information', styles['BoldLeft'])) - elements += _layout_paragraphs(approval.additional_information)''' - - # delegation holds the dates, approvale and issuer details. - delegation = [] - # proponent details - delegation.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - #address = proposal.applicant.organisation.postal_address - address = proposal.applicant_address - address_paragraphs = [Paragraph(address.line1, styles['Left']), Paragraph(address.line2, styles['Left']), - Paragraph(address.line3, styles['Left']), - Paragraph('%s %s %s' % (address.locality, address.state, address.postcode), styles['Left']), - Paragraph(address.country.name, styles['Left'])] - # if proposal.org_applicant: - # address_paragraphs = [Paragraph(address.line1, styles['Left']), Paragraph(address.line2, styles['Left']), - # Paragraph(address.line3, styles['Left']), - # Paragraph('%s %s %s' % (address.locality, address.state, address.postcode), styles['Left']), - # Paragraph(address.country.name, styles['Left'])] - # else: - # address_paragraphs = [Paragraph(address.line1, styles['Left']), Paragraph(address.line2, styles['Left']), - # Paragraph(address.line3, styles['Left']), - # Paragraph('%s %s' % (address.state, address.postcode), styles['Left']), - # Paragraph(address.country.name, styles['Left'])] - delegation.append(Table([[[Paragraph('Licensee:', styles['BoldLeft']), Paragraph('Address', styles['BoldLeft'])], - [Paragraph(_format_name(approval.applicant), - styles['Left'])] + address_paragraphs]], - colWidths=(120, PAGE_WIDTH - (2 * PAGE_MARGIN) - 120), - style=approval_table_style)) - - expiry_date = approval.expiry_date.strftime(DATE_FORMAT) - full_name = proposal.submitter.get_full_name() - - delegation.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - delegation.append(Paragraph('Dear {} '.format(full_name), styles['Left'])) - - delegation.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - # delegation.append(Paragraph('This is a reminder that your approval: ', styles['Left'])) - - # delegation.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - - # title_with_number = '{} - {}'.format(approval.lodgement_number, title) - - # delegation.append(Paragraph(title_with_number, styles['InfoTitleLargeLeft'])) - - # delegation.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - # delegation.append(Paragraph('is due to expire on {}'.format(expiry_date), styles['Left'])) - - delegation.append(Paragraph('This is a reminder that your Commercial Operations licence {} expires on {}. '.format(approval.lodgement_number, expiry_date), styles['BoldLeft'])) - - delegation.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - delegation.append(Paragraph('It is important you apply to renew your licence now so that we can process it before your current licence expires.' - 'If you would like to continue operating within WA\'s national parks and other conservation reserves you need a licence under the Conservation and Land Management Regulations 2002.', styles['Left'])) - #delegation.append(Paragraph('If you would like to continue operating within WA\'s national parks and other conservation reserves you need a licence under the Conservation and Land Management Regulations 2002.' - # , styles['Left'])) - - delegation.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - delegation.append(Paragraph('As a reminder, the Commercial Operator Handbook (2019) outlines the conditions of your licence.' - 'The handbook is available online at the {} website:'.format(settings.DEP_NAME), styles['Left'])) - #delegation.append(Paragraph('The handbook is available online at the {} website: .'.format(settings.DEP_NAME), styles['Left'])) - delegation.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - delegation.append(Paragraph('{}'.format(settings.COLS_HANDBOOK_URL), styles['WebAddress'])) - delegation.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - delegation.append(Paragraph('Please make sure you have access to this handbook, either in hardcopy or online, when operating within WA\'s national parks and conservation reserves.', styles['Left'])) - #delegation.append(Paragraph('', styles['Left'])) - - delegation.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - delegation.append(Paragraph('If you have any questions about how to renew your licence please call Licencing Officer on {} or email licensing@dbca.wa.gov.au.'.format(settings.DEP_PHONE), styles['Left'])) - - delegation.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - delegation.append(Paragraph('Yours sincerely ', styles['Left'])) - delegation.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - delegation.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - delegation.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - #delegation.append(Paragraph('DIRECTOR GENERAL', styles['Left'])) - delegation.append(Paragraph('{}'.format(settings.DEP_NAME), styles['Left'])) - - elements.append(KeepTogether(delegation)) - - doc.build(elements) - - return renewal_buffer diff --git a/commercialoperator/components/approvals/serializers.py b/commercialoperator/components/approvals/serializers.py deleted file mode 100755 index 9daa782900..0000000000 --- a/commercialoperator/components/approvals/serializers.py +++ /dev/null @@ -1,306 +0,0 @@ -from django.conf import settings -from ledger.accounts.models import EmailUser,Address -from commercialoperator.components.proposals.serializers import ProposalSerializer, InternalProposalSerializer, ProposalParkSerializer -from commercialoperator.components.main.serializers import ApplicationTypeSerializer -from commercialoperator.components.approvals.models import ( - Approval, - ApprovalLogEntry, - ApprovalUserAction -) -from commercialoperator.components.organisations.models import ( - Organisation -) -from commercialoperator.components.main.serializers import CommunicationLogEntrySerializer -from commercialoperator.components.proposals.serializers import ProposalSerializer -from rest_framework import serializers - -class EmailUserSerializer(serializers.ModelSerializer): - class Meta: - model = EmailUser - fields = ('id','email','first_name','last_name','title','organisation') - -class ApprovalPaymentSerializer(serializers.ModelSerializer): - #proposal = serializers.SerializerMethodField(read_only=True) - org_applicant = serializers.SerializerMethodField(read_only=True) - bpay_allowed = serializers.SerializerMethodField(read_only=True) - monthly_invoicing_allowed = serializers.SerializerMethodField(read_only=True) - other_allowed = serializers.SerializerMethodField(read_only=True) - - class Meta: - model = Approval - fields = ( - 'lodgement_number', - 'current_proposal', - 'expiry_date', - 'org_applicant', - 'bpay_allowed', - 'monthly_invoicing_allowed', - 'other_allowed', - ) - read_only_fields = ( - 'lodgement_number', - 'current_proposal', - 'expiry_date', - 'org_applicant', - 'bpay_allowed', - 'monthly_invoicing_allowed', - 'other_allowed', - ) - - def get_org_applicant(self,obj): - return obj.org_applicant.name if obj.org_applicant else None - - def get_bpay_allowed(self,obj): - return obj.bpay_allowed - - def get_monthly_invoicing_allowed(self,obj): - return obj.monthly_invoicing_allowed - - def get_other_allowed(self,obj): - return settings.OTHER_PAYMENT_ALLOWED - - #def get_monthly_invoicing_period(self,obj): - # return obj.monthly_invoicing_period - - #def get_monthly_payment_due_period(self,obj): - # return obj.monthly_payment_due_period - - #def get_proposal_id(self,obj): - # return obj.current_proposal_id - - -class _ApprovalPaymentSerializer(serializers.ModelSerializer): - applicant = serializers.SerializerMethodField(read_only=True) - applicant_type = serializers.SerializerMethodField(read_only=True) - applicant_id = serializers.SerializerMethodField(read_only=True) - status = serializers.CharField(source='get_status_display') - title = serializers.CharField(source='current_proposal.title') - application_type = serializers.SerializerMethodField(read_only=True) - land_parks = serializers.SerializerMethodField(read_only=True) - - class Meta: - model = Approval - fields = ( - 'id', - 'lodgement_number', - 'current_proposal', - 'title', - 'issue_date', - 'start_date', - 'expiry_date', - 'applicant', - 'applicant_type', - 'applicant_id', - 'status', - 'cancellation_date', - 'application_type', - 'land_parks' - ) - - def get_application_type(self,obj): - if obj.current_proposal.application_type: - return obj.current_proposal.application_type.name - return None - - def get_applicant(self,obj): - return obj.applicant.name if isinstance(obj.applicant, Organisation) else obj.applicant - - def get_applicant_type(self,obj): - return obj.applicant_type - - def get_applicant_id(self,obj): - return obj.applicant_id - - def get_land_parks(self,obj): - return None #obj.current_proposal.land_parks - #return AuthorSerializer(obj.author).data - #if obj.current_proposal.land_parks: - # return ProposalParkSerializer(obj.current_proposal.land_parks).data - #return None - - -class ApprovalSerializer(serializers.ModelSerializer): - #applicant = serializers.CharField(source='applicant.name') - applicant = serializers.SerializerMethodField(read_only=True) - applicant_type = serializers.SerializerMethodField(read_only=True) - applicant_id = serializers.SerializerMethodField(read_only=True) - #applicant_id = serializers.ReadOnlyField(source='applicant.id') - licence_document = serializers.CharField(source='licence_document._file.url') - #renewal_document = serializers.CharField(source='renewal_document._file.url') - renewal_document = serializers.SerializerMethodField(read_only=True) - status = serializers.CharField(source='get_status_display') - allowed_assessors = EmailUserSerializer(many=True) - region = serializers.CharField(source='current_proposal.region.name') - district = serializers.CharField(source='current_proposal.district.name', allow_null=True) - #tenure = serializers.CharField(source='current_proposal.tenure.name') - activity = serializers.CharField(source='current_proposal.activity') - title = serializers.CharField(source='current_proposal.title') - #current_proposal = InternalProposalSerializer(many=False) - #application_type = ApplicationTypeSerializer(many=True) - application_type = serializers.SerializerMethodField(read_only=True) - linked_applications = serializers.SerializerMethodField(read_only=True) - can_renew = serializers.SerializerMethodField() - can_extend = serializers.SerializerMethodField() - is_assessor = serializers.SerializerMethodField() - is_approver = serializers.SerializerMethodField() - - class Meta: - model = Approval - fields = ( - 'id', - 'lodgement_number', - 'linked_applications', - 'licence_document', - 'replaced_by', - 'current_proposal', - 'activity', - 'region', - 'district', - 'tenure', - 'title', - 'renewal_document', - 'renewal_sent', - 'issue_date', - 'original_issue_date', - 'start_date', - 'expiry_date', - 'surrender_details', - 'suspension_details', - 'applicant', - 'applicant_type', - 'applicant_id', - 'extracted_fields', - 'status', - 'reference', - 'can_reissue', - 'allowed_assessors', - 'cancellation_date', - 'cancellation_details', - 'can_action', - 'set_to_cancel', - 'set_to_surrender', - 'set_to_suspend', - 'can_renew', - 'can_extend', - 'can_amend', - 'can_reinstate', - 'application_type', - 'migrated', - 'is_assessor', - 'is_approver' - ) - # the serverSide functionality of datatables is such that only columns that have field 'data' defined are requested from the serializer. We - # also require the following additional fields for some of the mRender functions - datatables_always_serialize = ( - 'id', - 'activity', - 'region', - 'title', - 'status', - 'reference', - 'lodgement_number', - 'linked_applications', - 'licence_document', - 'start_date', - 'expiry_date', - 'applicant', - 'can_reissue', - 'can_action', - 'can_reinstate', - 'can_amend', - 'can_renew', - 'can_extend', - 'set_to_cancel', - 'set_to_suspend', - 'set_to_surrender', - 'current_proposal', - 'renewal_document', - 'renewal_sent', - 'allowed_assessors', - 'application_type', - 'migrated', - 'is_assessor', - 'is_approver' - ) - - def get_linked_applications(self,obj): - return obj.linked_applications - - - def get_renewal_document(self,obj): - if obj.renewal_document and obj.renewal_document._file: - return obj.renewal_document._file.url - return None - - def get_application_type(self,obj): - if obj.current_proposal.application_type: - return obj.current_proposal.application_type.name - return None - - def get_applicant(self,obj): - try: - return obj.applicant.name if isinstance(obj.applicant, Organisation) else obj.applicant - except: - return None - - def get_applicant_type(self,obj): - try: - return obj.applicant_type - except: - return None - - def get_applicant_id(self,obj): - try: - return obj.applicant_id - except: - return None - - def get_can_renew(self,obj): - return obj.can_renew - - def get_can_extend(self,obj): - return obj.can_extend - - def get_is_assessor(self,obj): - request = self.context['request'] - user = request.user - return obj.is_assessor(user) - - def get_is_approver(self,obj): - request = self.context['request'] - user = request.user - return obj.is_approver(user) - -class ApprovalExtendSerializer(serializers.Serializer): - extend_details = serializers.CharField() - -class ApprovalCancellationSerializer(serializers.Serializer): - cancellation_date = serializers.DateField(input_formats=['%d/%m/%Y']) - cancellation_details = serializers.CharField() - -class ApprovalSuspensionSerializer(serializers.Serializer): - from_date = serializers.DateField(input_formats=['%d/%m/%Y']) - to_date = serializers.DateField(input_formats=['%d/%m/%Y'], required=False, allow_null=True) - suspension_details = serializers.CharField() - -class ApprovalSurrenderSerializer(serializers.Serializer): - surrender_date = serializers.DateField(input_formats=['%d/%m/%Y']) - surrender_details = serializers.CharField() - -class ApprovalUserActionSerializer(serializers.ModelSerializer): - who = serializers.CharField(source='who.get_full_name') - class Meta: - model = ApprovalUserAction - fields = '__all__' - -class ApprovalLogEntrySerializer(CommunicationLogEntrySerializer): - documents = serializers.SerializerMethodField() - class Meta: - model = ApprovalLogEntry - fields = '__all__' - read_only_fields = ( - 'customer', - ) - - def get_documents(self,obj): - return [[d.name,d._file.url] for d in obj.documents.all()] diff --git a/commercialoperator/components/approvals/signals.py b/commercialoperator/components/approvals/signals.py deleted file mode 100755 index e69de29bb2..0000000000 diff --git a/commercialoperator/components/approvals/templates/commercialoperator/emails/approval_cancel_notification.html b/commercialoperator/components/approvals/templates/commercialoperator/emails/approval_cancel_notification.html deleted file mode 100755 index f599100e11..0000000000 --- a/commercialoperator/components/approvals/templates/commercialoperator/emails/approval_cancel_notification.html +++ /dev/null @@ -1,10 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} -

Your licence to conduct commercial operations on Conservation and Land Management Act 1984 (CALM Act) land has been cancelled.

-

Licence : {{ approval.lodgement_number}}

-

Cancellation Details : {{ approval.cancellation_details}}

-

Cancellation Date : {{ approval.cancellation_date}}

-

If you have any enquiries or need assistance with the online system please contact a licensing officer on {{settings.DEP_PHONE}}, or email {{settings.SUPPORT_EMAIL}}

- -{% endblock %} diff --git a/commercialoperator/components/approvals/templates/commercialoperator/emails/approval_cancel_notification.txt b/commercialoperator/components/approvals/templates/commercialoperator/emails/approval_cancel_notification.txt deleted file mode 100755 index 0d35e3d464..0000000000 --- a/commercialoperator/components/approvals/templates/commercialoperator/emails/approval_cancel_notification.txt +++ /dev/null @@ -1,14 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.txt' %} - -{% block content %} - Your licence to conduct commercial operations on Conservation and Land Management Act 1984 (CALM Act) land has been cancelled. - - Licence : {{ approval.lodgement_number}} - - Cancellation Details : {{ approval.cancellation_details}} - - Cancellation Date : {{ approval.cancellation_date}} - - If you have any enquiries or need assistance with the online system please contact a licensing officer on {{settings.DEP_PHONE}}, or email {{settings.SUPPORT_EMAIL}} - -{% endblock %} diff --git a/commercialoperator/components/approvals/templates/commercialoperator/emails/approval_expire_notification.html b/commercialoperator/components/approvals/templates/commercialoperator/emails/approval_expire_notification.html deleted file mode 100755 index 98e6545ce6..0000000000 --- a/commercialoperator/components/approvals/templates/commercialoperator/emails/approval_expire_notification.html +++ /dev/null @@ -1,13 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} - - -

Please be aware that your commercial operations licence {{ approval.lodgement_number }} on {{ approval.expiry_date}}

-

To apply for a new Commercial Operations Licence please click here

-

If you would like to continue operating withing WA's national parks and other conservation reserves you need a licence under the Conservation and Land Management Regulations 2002.

-

If you have any questions about how to apply for a new licence please contact a licensing office on {{settings.DEP_PHONE}} or email {{settings.SUPPORT_EMAIL}}

- -{% endblock %} diff --git a/commercialoperator/components/approvals/templates/commercialoperator/emails/approval_expire_notification.txt b/commercialoperator/components/approvals/templates/commercialoperator/emails/approval_expire_notification.txt deleted file mode 100755 index fe4d2e5dd5..0000000000 --- a/commercialoperator/components/approvals/templates/commercialoperator/emails/approval_expire_notification.txt +++ /dev/null @@ -1,13 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.txt' %} - -{% block content %} - Please be aware that your commercial operations licence {{ approval.lodgement_number }} on {{ approval.expiry_date}} - - To apply for a new Commercial Operations Licence please click here - - If you would like to continue operating withing WA's national parks and other conservation reserves you need a licence under the Conservation and Land Management Regulations 2002. - - If you have any questions about how to apply for a new licence please contact a licensing office on {{settings.DEP_PHONE}} or email {{settings.SUPPORT_EMAIL}} - - -{% endblock %} diff --git a/commercialoperator/components/approvals/templates/commercialoperator/emails/approval_reinstate_notification.html b/commercialoperator/components/approvals/templates/commercialoperator/emails/approval_reinstate_notification.html deleted file mode 100755 index e14503d18c..0000000000 --- a/commercialoperator/components/approvals/templates/commercialoperator/emails/approval_reinstate_notification.html +++ /dev/null @@ -1,8 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} -

Your licence to conduct commercial operations on Conservation and Land Management Act 1984 (CALM Act) land has been reinstated. Please login to your account to view the licence.

-

Licence : {{ approval.lodgement_number}}

- -

If you have any enquiries or need assistance with the online system please contact a licensing officer on {{settings.DEP_PHONE}}, or email {{settings.SUPPORT_EMAIL}}

-{% endblock %} diff --git a/commercialoperator/components/approvals/templates/commercialoperator/emails/approval_reinstate_notification.txt b/commercialoperator/components/approvals/templates/commercialoperator/emails/approval_reinstate_notification.txt deleted file mode 100755 index 2ed965ee8f..0000000000 --- a/commercialoperator/components/approvals/templates/commercialoperator/emails/approval_reinstate_notification.txt +++ /dev/null @@ -1,10 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.txt' %} - -{% block content %} - Your licence to conduct commercial operations on Conservation and Land Management Act 1984 (CALM Act) land has been reinstated. Please login to your account to view the licence. - - Licence : {{ approval.lodgement_number}} - - If you have any enquiries or need assistance with the online system please contact a licensing officer on {{settings.DEP_PHONE}}, or email {{settings.SUPPORT_EMAIL}} - -{% endblock %} diff --git a/commercialoperator/components/approvals/templates/commercialoperator/emails/approval_renewal_notification.html b/commercialoperator/components/approvals/templates/commercialoperator/emails/approval_renewal_notification.html deleted file mode 100755 index 6609151e84..0000000000 --- a/commercialoperator/components/approvals/templates/commercialoperator/emails/approval_renewal_notification.html +++ /dev/null @@ -1,23 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} -

This is a reminder that your commercial operations licence - {{ approval.lodgement_number}} expires on {{approval.expiry_date}}.

- -

To renew your commercial operations licence please click here.

-

It is important you apply to renew your licence now so that we can process it before your current licence expires. If you would like to continue operating within WA’s national parks and other conservation reserves you need a licence under the Conservation and Land Management Regulations 2002.

- -

As a reminder, the Commercial Operator Handbook (2019) outlines the conditions of your licence. The handbook is available online at the Department of Biodiversity, Conservation and Attractions website:

- - - -

Please make sure you have access to this handbook, either in hardcopy or online, when operating within WA’s national parks and conservation reserves.

- -

If you have any questions about how to renew your licence please call Licencing Officer on {{settings.DEP_PHONE}} or email {{settings.SUPPORT_EMAIL}}.

- - - - - -{% endblock %} diff --git a/commercialoperator/components/approvals/templates/commercialoperator/emails/approval_renewal_notification.txt b/commercialoperator/components/approvals/templates/commercialoperator/emails/approval_renewal_notification.txt deleted file mode 100755 index d38b1b4408..0000000000 --- a/commercialoperator/components/approvals/templates/commercialoperator/emails/approval_renewal_notification.txt +++ /dev/null @@ -1,18 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.txt' %} - -{% block content %} - This is a reminder that your commercial operations licence - {{ approval.lodgement_number}} expires on {{approval.expiry_date}}. - - To renew your commercial operations licence please click
here. - It is important you apply to renew your licence now so that we can process it before your current licence expires. If you would like to continue operating within WA’s national parks and other conservation reserves you need a licence under the Conservation and Land Management Regulations 2002. - - As a reminder, the Commercial Operator Handbook (2019) outlines the conditions of your licence. The handbook is available online at the Department of Biodiversity, Conservation and Attractions website. - - Please make sure you have access to this handbook, either in hardcopy or online, when operating within WA’s national parks and conservation reserves. - - If you have any questions about how to renew your licence please contact a licensing office on {{settings.DEP_PHONE}} or email {{settings.SUPPORT_EMAIL}} - - - -{% endblock %} diff --git a/commercialoperator/components/approvals/templates/commercialoperator/emails/approval_surrender_notification.html b/commercialoperator/components/approvals/templates/commercialoperator/emails/approval_surrender_notification.html deleted file mode 100755 index d796e048c3..0000000000 --- a/commercialoperator/components/approvals/templates/commercialoperator/emails/approval_surrender_notification.html +++ /dev/null @@ -1,14 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} - -

Your licence to conduct commercial operations on Conservation and Land Management Act 1984 (CALM Act) land has been surrendered.

-

Licence : {{ approval.lodgement_number}}

-

Surrender Details : {{details}}

-

Surrender Date : {{surrender_date}}

-

If you have any enquiries or need assistance with the online system please contact a licensing officer on {{settings.DEP_PHONE}}, or email {{settings.SUPPORT_EMAIL}}

- -{% endblock %} diff --git a/commercialoperator/components/approvals/templates/commercialoperator/emails/approval_surrender_notification.txt b/commercialoperator/components/approvals/templates/commercialoperator/emails/approval_surrender_notification.txt deleted file mode 100755 index 775d55d0bc..0000000000 --- a/commercialoperator/components/approvals/templates/commercialoperator/emails/approval_surrender_notification.txt +++ /dev/null @@ -1,15 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.txt' %} - -{% block content %} - - Your licence to conduct commercial operations on Conservation and Land Management Act 1984 (CALM Act) land has been surrendered. - - Licence : {{ approval.lodgement_number}} - - Surrender Details : {{details}} - - Surrender Date : {{ surrender_date}} - - If you have any enquiries or need assistance with the online system please contact a licensing officer on {{settings.DEP_PHONE}}, or email {{settings.SUPPORT_EMAIL}} - -{% endblock %} diff --git a/commercialoperator/components/approvals/templates/commercialoperator/emails/approval_suspend_notification.html b/commercialoperator/components/approvals/templates/commercialoperator/emails/approval_suspend_notification.html deleted file mode 100755 index 1e71853dbc..0000000000 --- a/commercialoperator/components/approvals/templates/commercialoperator/emails/approval_suspend_notification.html +++ /dev/null @@ -1,18 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} - - -

Your licence to conduct commercial operations on Conservation and Land Management Act 1984 (CALM Act) land has been suspended.

- -

Licence : {{ approval.lodgement_number}}

-

Suspension Details : {{details}}

-

From Date : {{from_date}}

-

To Date : {{to_date}}

- -

If you have any enquiries or need assistance with the online system please contact a licensing officer on {{settings.DEP_PHONE}}, or email {{settings.SUPPORT_EMAIL}}

-{% endblock %} diff --git a/commercialoperator/components/approvals/templates/commercialoperator/emails/approval_suspend_notification.txt b/commercialoperator/components/approvals/templates/commercialoperator/emails/approval_suspend_notification.txt deleted file mode 100755 index 9bc5da5469..0000000000 --- a/commercialoperator/components/approvals/templates/commercialoperator/emails/approval_suspend_notification.txt +++ /dev/null @@ -1,16 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.txt' %} - -{% block content %} - Your licence to conduct commercial operations on Conservation and Land Management Act 1984 (CALM Act) land has been suspended. - - Licence : {{ approval.lodgement_number}} - - Suspension Details : {{details}} - - From Date : {{from_date}} - - To Date : {{to_date}} - - If you have any enquiries or need assistance with the online system please contact a licensing officer on {{settings.DEP_PHONE}}, or email {{settings.SUPPORT_EMAIL}} - -{% endblock %} diff --git a/commercialoperator/components/approvals/utils.py b/commercialoperator/components/approvals/utils.py deleted file mode 100755 index e69de29bb2..0000000000 diff --git a/commercialoperator/components/bookings/__init__.py b/commercialoperator/components/bookings/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/commercialoperator/components/bookings/api.py b/commercialoperator/components/bookings/api.py deleted file mode 100755 index f6adbe761b..0000000000 --- a/commercialoperator/components/bookings/api.py +++ /dev/null @@ -1,110 +0,0 @@ -import traceback -import os -import datetime -import base64 -import geojson -from six.moves.urllib.parse import urlparse -from wsgiref.util import FileWrapper -from django.db.models import Q, Min -from django.db import transaction -from django.http import HttpResponse -from django.core.files.base import ContentFile -from django.core.exceptions import ValidationError -from django.conf import settings -from django.contrib import messages -from django.views.decorators.http import require_http_methods -from django.views.decorators.csrf import csrf_exempt -from django.utils import timezone -from rest_framework import viewsets, serializers, status, generics, views -from rest_framework.decorators import detail_route, list_route, renderer_classes -from rest_framework.response import Response -from rest_framework.renderers import JSONRenderer -from rest_framework.permissions import IsAuthenticated, AllowAny, IsAdminUser, BasePermission -from rest_framework.pagination import PageNumberPagination -from datetime import datetime, timedelta -from collections import OrderedDict -from django.core.cache import cache -from ledger.accounts.models import EmailUser, Address -from ledger.address.models import Country -from datetime import datetime, timedelta, date -from django.urls import reverse -from django.shortcuts import render, redirect, get_object_or_404 -from commercialoperator.components.proposals.models import Proposal, ApplicationType -from commercialoperator.components.bookings.models import ( - Booking, - ParkBooking, - BookingInvoice, -) -from commercialoperator.components.bookings.serializers import ( - BookingSerializer, - ParkBookingSerializer, -# BookingSerializer2, -# ParkBookingSerializer2, -) -from commercialoperator.helpers import is_customer, is_internal -from rest_framework_datatables.pagination import DatatablesPageNumberPagination -from commercialoperator.components.proposals.api import ProposalFilterBackend, ProposalRenderer - - -class BookingPaginatedViewSet(viewsets.ModelViewSet): - filter_backends = (ProposalFilterBackend,) - pagination_class = DatatablesPageNumberPagination - renderer_classes = (ProposalRenderer,) - page_size = 10 - queryset = Booking.objects.none() - serializer_class = BookingSerializer - - def get_queryset(self): - user = self.request.user - if is_internal(self.request): - return Booking.objects.all().exclude(booking_type=Booking.BOOKING_TYPE_TEMPORARY) - elif is_customer(self.request): - user_orgs = [org.id for org in user.commercialoperator_organisations.all()] - return Booking.objects.filter( Q(proposal__org_applicant_id__in = user_orgs) | Q(proposal__submitter = user) ).exclude(booking_type=Booking.BOOKING_TYPE_TEMPORARY) - return Booking.objects.none() - - @list_route(methods=['GET',]) - def bookings_external(self, request, *args, **kwargs): - """ - Paginated serializer for datatables - used by the internal and external dashboard (filtered by the get_queryset method) - - To test: - http://localhost:8000/api/booking_paginated/bookings_external/?format=datatables&draw=1&length=2 - """ - - qs = self.get_queryset() - qs = self.filter_queryset(qs) - - self.paginator.page_size = qs.count() - result_page = self.paginator.paginate_queryset(qs, request) - serializer = BookingSerializer(result_page, context={'request':request}, many=True) - return self.paginator.get_paginated_response(serializer.data) - - -class BookingViewSet(viewsets.ModelViewSet): - queryset = Booking.objects.none() - serializer_class = BookingSerializer - - def get_queryset(self): - user = self.request.user - if is_internal(self.request): - return Booking.objects.all().exclude(booking_type=Booking.BOOKING_TYPE_TEMPORARY) - elif is_customer(self.request): - user_orgs = [org.id for org in user.commercialoperator_organisations.all()] - return Booking.objects.filter( Q(proposal__org_applicant_id__in = user_orgs) | Q(proposal__submitter = user) ).exclude(booking_type=Booking.BOOKING_TYPE_TEMPORARY) - return Booking.objects.none() - - -class ParkBookingViewSet(viewsets.ModelViewSet): - queryset = ParkBooking.objects.none() - serializer_class = ParkBookingSerializer - - def get_queryset(self): - user = self.request.user - if is_internal(self.request): - return ParkBooking.objects.all() - elif is_customer(self.request): - user_orgs = [org.id for org in user.commercialoperator_organisations.all()] - return ParkBooking.objects.filter( Q(booking__proposal__org_applicant_id__in = user_orgs) | Q(booking__proposal__submitter = user) ) - return ParkBooking.objects.none() - diff --git a/commercialoperator/components/bookings/confirmation_pdf.py b/commercialoperator/components/bookings/confirmation_pdf.py deleted file mode 100644 index 2f45503672..0000000000 --- a/commercialoperator/components/bookings/confirmation_pdf.py +++ /dev/null @@ -1,342 +0,0 @@ -import os - -from decimal import Decimal as D -from io import BytesIO -from oscar.templatetags.currency_filters import currency -from reportlab.lib import enums -from reportlab.lib.pagesizes import A4 -from reportlab.platypus import BaseDocTemplate, PageTemplate, Frame, Paragraph, Spacer, Table, TableStyle, ListFlowable, \ - KeepTogether, PageBreak, Flowable, NextPageTemplate, FrameBreak -from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle -from reportlab.lib.utils import ImageReader -from reportlab.pdfgen.canvas import Canvas -from reportlab.pdfbase import pdfmetrics -from reportlab.lib.units import inch -from reportlab.lib import colors - -from django.core.files import File -from django.conf import settings - -from ledger.accounts.models import Document -from ledger.checkout.utils import calculate_excl_gst - -DPAW_HEADER_LOGO = os.path.join(settings.BASE_DIR, 'ledger', 'payments','static', 'payments', 'img','dbca_logo.jpg') -DPAW_HEADER_LOGO_SM = os.path.join(settings.BASE_DIR, 'ledger', 'payments','static', 'payments', 'img','dbca_logo_small.png') -BPAY_LOGO = os.path.join(settings.BASE_DIR, 'ledger', 'payments','static', 'payments', 'img', 'BPAY_2012_PORT_BLUE.png') - -HEADER_MARGIN = 10 -HEADER_SMALL_BUFFER = 3 - -PAGE_MARGIN = 20 -PAGE_TOP_MARGIN = 200 - -PAGE_WIDTH, PAGE_HEIGHT = A4 - -DEFAULT_FONTNAME = 'Helvetica' -BOLD_FONTNAME = 'Helvetica-Bold' - -VERY_LARGE_FONTSIZE = 14 -LARGE_FONTSIZE = 12 -MEDIUM_FONTSIZE = 10 -SMALL_FONTSIZE = 8 - -PARAGRAPH_BOTTOM_MARGIN = 5 - -SECTION_BUFFER_HEIGHT = 10 - -DATE_FORMAT = '%d/%m/%Y' - -styles = getSampleStyleSheet() -styles.add(ParagraphStyle(name='InfoTitleLargeCenter', fontName=BOLD_FONTNAME, fontSize=LARGE_FONTSIZE, - spaceAfter=PARAGRAPH_BOTTOM_MARGIN, alignment=enums.TA_CENTER)) -styles.add(ParagraphStyle(name='InfoTitleVeryLargeCenter', fontName=BOLD_FONTNAME, fontSize=VERY_LARGE_FONTSIZE, - spaceAfter=PARAGRAPH_BOTTOM_MARGIN * 2, alignment=enums.TA_CENTER)) -styles.add(ParagraphStyle(name='InfoTitleLargeLeft', fontName=BOLD_FONTNAME, fontSize=LARGE_FONTSIZE, - spaceAfter=PARAGRAPH_BOTTOM_MARGIN, alignment=enums.TA_LEFT, - leftIndent=PAGE_WIDTH / 10, rightIndent=PAGE_WIDTH / 10)) -styles.add(ParagraphStyle(name='InfoTitleLargeRight', fontName=BOLD_FONTNAME, fontSize=LARGE_FONTSIZE, - spaceAfter=PARAGRAPH_BOTTOM_MARGIN, alignment=enums.TA_RIGHT, - rightIndent=PAGE_WIDTH / 10)) -styles.add(ParagraphStyle(name='BoldLeft', fontName=BOLD_FONTNAME, fontSize=MEDIUM_FONTSIZE, alignment=enums.TA_LEFT)) -styles.add(ParagraphStyle(name='BoldRight', fontName=BOLD_FONTNAME, fontSize=MEDIUM_FONTSIZE, alignment=enums.TA_RIGHT)) -styles.add(ParagraphStyle(name='Center', alignment=enums.TA_CENTER)) -styles.add(ParagraphStyle(name='Left', alignment=enums.TA_LEFT)) -styles.add(ParagraphStyle(name='Right', alignment=enums.TA_RIGHT)) -styles.add(ParagraphStyle(name='LongString', alignment=enums.TA_LEFT,wordWrap='CJK')) - -class BrokenLine(Flowable): - - def __init__(self, width,height=0): - Flowable.__init__(self) - self.width = width - self.height = height - - def __repr__(self): - return 'Line {}'.format(self.width) - - def draw(self): - self.canv.setDash(3,3) - self.canv.line(0, self.height,self.width,self.height) - -class Remittance(Flowable): - def __init__(self,current_x,current_y,invoice): - Flowable.__init__(self) - self.current_x = current_x - self.current_y = current_y - self.invoice = invoice - - def __repr__(self): - return 'remittance' - - def __logo_line(self): - canvas = self.canv - current_y, current_x = self.current_y, self.current_x - canvas.setFont(DEFAULT_FONTNAME, MEDIUM_FONTSIZE) - dpaw_header_logo = ImageReader(DPAW_HEADER_LOGO_SM) - - dpaw_header_logo_size = dpaw_header_logo.getSize() - canvas.drawImage(dpaw_header_logo, HEADER_MARGIN, current_y - (dpaw_header_logo_size[1]/1.8),height=dpaw_header_logo_size[1]/1.8, mask='auto', width=dpaw_header_logo_size[0]/1.8) - - current_y = -20 - canvas.setFont(BOLD_FONTNAME, MEDIUM_FONTSIZE) - canvas.drawRightString(current_x * 45,current_y,'Remittance Advice') - - current_y -= 20 - canvas.setFont(DEFAULT_FONTNAME, MEDIUM_FONTSIZE) - canvas.drawString(current_x * 27,current_y,'PLEASE DETACH AND RETURN WITH YOUR PAYMENT') - - current_y -= 20 - canvas.setFont(DEFAULT_FONTNAME, MEDIUM_FONTSIZE) - canvas.drawString(current_x, current_y, 'ABN: 38 052 249 024') - self.current_y = current_y - - def __payment_line(self): - canvas = self.canv - current_y, current_x = self.current_y, self.current_x - bpay_logo = ImageReader(BPAY_LOGO) - #current_y -= 40 - # Pay By Cheque - cheque_x = current_x + 4 * inch - cheque_y = current_y -30 - canvas.setFont(BOLD_FONTNAME, MEDIUM_FONTSIZE) - canvas.drawString(cheque_x, cheque_y, 'Pay By Cheque:') - canvas.setFont(DEFAULT_FONTNAME, 9) - cheque_y -= 15 - canvas.drawString(cheque_x, cheque_y, 'Make cheque payable to: Department of Parks and Wildlife') - cheque_y -= 15 - canvas.drawString(cheque_x, cheque_y, 'Mail to: Department of Parks and Wildlife') - cheque_y -= 15 - canvas.drawString(cheque_x + 32, cheque_y, 'Locked Bag 30') - cheque_y -= 15 - canvas.drawString(cheque_x + 32, cheque_y, 'Bentley Delivery Centre WA 6983') - if settings.BPAY_ALLOWED: - # Outer BPAY Box - canvas.rect(current_x,current_y - 25,2.3*inch,-1.2*inch) - canvas.setFillColorCMYK(0.8829,0.6126,0.0000,0.5647) - # Move into bpay box - current_y += 5 - box_pos = current_x + 0.1 * inch - bpay_logo_size = bpay_logo.getSize() - canvas.drawImage(bpay_logo, box_pos, current_y - (bpay_logo_size[1]/12 * 1.7), height= bpay_logo_size[1]/12,width=bpay_logo_size[0]/12, mask='auto') - # Create biller information box - biller_x = box_pos + bpay_logo_size[0]/12 + 1 - canvas.rect(biller_x,(current_y - (bpay_logo_size[1]/12 * 1.7)) + 3,1.65*inch,(bpay_logo_size[1]/12)-5) - # Bpay info - canvas.setFont(BOLD_FONTNAME, MEDIUM_FONTSIZE) - info_y = ((current_y - (bpay_logo_size[1]/12 * 1.7)) + 3) + (0.35 * inch) - canvas.drawString(biller_x + 5, info_y, 'Biller Code: {}'.format(self.invoice.biller_code)) - canvas.drawString(biller_x + 5, info_y - 20, 'Ref: {}'.format(self.invoice.reference)) - # Bpay Info string - canvas.setFont(BOLD_FONTNAME,SMALL_FONTSIZE) - canvas.drawString(box_pos, info_y - 0.55 * inch, 'Telephone & Internet Banking - BPAY') - canvas.setFont(DEFAULT_FONTNAME,6.5) - canvas.drawString(box_pos, info_y - 0.65 * inch, 'Contact your bank or financial institution to make') - canvas.drawString(box_pos, info_y - 0.75 * inch, 'this payment from your cheque, savings, debit or') - canvas.drawString(box_pos, info_y - 0.85 * inch, 'transaction account. More info: www.bpay.com.au') - - self.current_y = current_y - - def __footer_line(self): - canvas = self.canv - current_y, current_x = self.current_y, self.current_x - current_y -= 2 * inch - canvas.setFont(DEFAULT_FONTNAME, LARGE_FONTSIZE) - canvas.setFillColor(colors.black) - canvas.drawString(current_x, current_y, 'Invoice Number') - canvas.drawString(PAGE_WIDTH/4, current_y, 'Invoice Date') - canvas.drawString((PAGE_WIDTH/4) * 2, current_y, 'GST included') - canvas.drawString((PAGE_WIDTH/4) * 3, current_y, 'Invoice Total') - current_y -= 20 - canvas.setFont(DEFAULT_FONTNAME, MEDIUM_FONTSIZE) - canvas.drawString(current_x, current_y, self.invoice.reference) - canvas.drawString(PAGE_WIDTH/4, current_y, self.invoice.created.strftime(DATE_FORMAT)) - canvas.drawString((PAGE_WIDTH/4) * 2, current_y, currency(self.invoice.amount - calculate_excl_gst(self.invoice.amount))) - canvas.drawString((PAGE_WIDTH/4) * 3, current_y, currency(self.invoice.amount)) - - def draw(self): - if settings.BPAY_ALLOWED: - self.__logo_line() - self.__payment_line() - self.__footer_line() - - -def _create_header(canvas, doc, draw_page_number=True): - canvas.saveState() - canvas.setTitle('Confirmation') - canvas.setFont(BOLD_FONTNAME, LARGE_FONTSIZE) - - current_y = PAGE_HEIGHT - HEADER_MARGIN - - dpaw_header_logo = ImageReader(DPAW_HEADER_LOGO) - dpaw_header_logo_size = dpaw_header_logo.getSize() - canvas.drawImage(dpaw_header_logo, PAGE_WIDTH / 3, current_y - (dpaw_header_logo_size[1]/2),width=dpaw_header_logo_size[0]/2, height=dpaw_header_logo_size[1]/2, mask='auto') - - current_y -= 70 - invoice = doc.invoice - booking = doc.booking - licence_number = booking.proposal.approval.lodgement_number if booking.proposal.approval else None - - if hasattr(booking, 'payment_type'): - PAGE_TITLE = 'APPLICATION & LICENCE FEE CONFIRMATION' - else: - PAGE_TITLE = 'BOOKING CONFIRMATION' - canvas.drawCentredString(PAGE_WIDTH / 2, current_y - LARGE_FONTSIZE, PAGE_TITLE) - - # Invoice address details - invoice_details_offset = 37 - current_y -= 25 - canvas.setFont(BOLD_FONTNAME, SMALL_FONTSIZE) - current_x = PAGE_MARGIN + 5 - if booking.proposal.org_applicant: - canvas.drawString(current_x, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER), booking.proposal.applicant) - canvas.drawString(current_x, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER) * 2,invoice.owner.get_full_name()) - canvas.drawString(current_x, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER) * 3,invoice.owner.email) - current_x += 452 - - #write Invoice details - canvas.drawString(current_x, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER),'Date') - canvas.drawString(current_x + invoice_details_offset, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER),invoice.created.strftime(DATE_FORMAT)) - canvas.drawString(current_x, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER) * 2, 'Page') - canvas.drawString(current_x + invoice_details_offset, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER) * 2, str(canvas.getPageNumber())) - canvas.drawRightString(current_x + 20, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER) * 3, 'Licence Number') - canvas.drawString(current_x + invoice_details_offset, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER) * 3, licence_number) - canvas.drawRightString(current_x + 20, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER) * 4, 'Invoice Number') - canvas.drawString(current_x + invoice_details_offset, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER) * 4, invoice.reference) - canvas.drawRightString(current_x + 20, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER) * 5, 'Paid (AUD)') - canvas.drawString(current_x + invoice_details_offset, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER) * 5, currency(invoice.payment_amount)) - if hasattr(booking, 'booking_type'): - canvas.drawRightString(current_x + 20, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER) * 6, 'Booking No.') - canvas.drawString(current_x + invoice_details_offset, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER) * 6, booking.booking_number) - - if booking.deferred_payment_date and invoice.payment_method in [invoice.PAYMENT_METHOD_MONTHLY_INVOICING, invoice.PAYMENT_METHOD_BPAY]: - canvas.drawRightString(current_x + 20, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER) * 7, 'Payment Due Date') - canvas.drawString(current_x + invoice_details_offset, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER) * 7, booking.deferred_payment_date.strftime(DATE_FORMAT)) - - canvas.restoreState() - - -def _create_confirmation(confirmation_buffer, invoice, booking): - - global DPAW_HEADER_LOGO -# if cols_var["TEMPLATE_GROUP"] == 'rottnest': -# DPAW_HEADER_LOGO = os.path.join(settings.BASE_DIR, 'mooring', 'static', 'mooring', 'img','logo-rottnest-island-sm.png') -# else: -# DPAW_HEADER_LOGO = os.path.join(settings.BASE_DIR, 'ledger', 'payments','static', 'payments', 'img','dbca_logo.jpg') - DPAW_HEADER_LOGO = os.path.join(settings.BASE_DIR, 'ledger', 'payments','static', 'payments', 'img','dbca_logo.jpg') - - every_page_frame = Frame(PAGE_MARGIN, PAGE_MARGIN + 250, PAGE_WIDTH - 2 * PAGE_MARGIN, - PAGE_HEIGHT -450 , id='EveryPagesFrame',showBoundary=0) - remit_frame = Frame(PAGE_MARGIN, PAGE_MARGIN, PAGE_WIDTH - 2 * PAGE_MARGIN, - PAGE_HEIGHT - 600, id='RemitFrame',showBoundary=0) - every_page_template = PageTemplate(id='EveryPages', frames=[every_page_frame,remit_frame], onPage=_create_header) - - doc = BaseDocTemplate(confirmation_buffer, pageTemplates=[every_page_template], pagesize=A4) - - # this is the only way to get data into the onPage callback function - doc.invoice = invoice - doc.booking = booking - owner = invoice.owner - - elements = [] - #elements.append(Spacer(1, SECTION_BUFFER_HEIGHT * 5)) - - # Draw Products Table - invoice_table_style = TableStyle([ - ('VALIGN', (0, 0), (-1, -1), 'TOP'), - ('GRID',(0, 0), (-1, -1),1, colors.black), - ('ALIGN', (0, 0), (-1, -1), 'LEFT') - ]) - items = invoice.order.lines.all() - discounts = invoice.order.basket_discounts - #if invoice.text: - # elements.append(Paragraph(invoice.text, styles['Left'])) - # elements.append(Spacer(1, SECTION_BUFFER_HEIGHT * 2)) - elements.append(Spacer(1, SECTION_BUFFER_HEIGHT * 2)) - - data = [ - #['Item','Product', 'Quantity','Unit Price', 'Total'] - ['Item','Product', 'Quantity','Fees'] - ] - val = 1 - s = styles["BodyText"] - s.wordWrap = 'CJK' - - for item in items: - data.append( - [ - val, - Paragraph(item.description, s), - item.quantity, - invoice.payment_status.capitalize() - ] - ) - val += 1 - # Discounts - data.append( - [ - '', - '', - '' - ] - ) - t= Table( - data, - style=invoice_table_style, - hAlign='LEFT', - colWidths=( - 0.7 * inch, - None, - 0.7 * inch, - 1.0 * inch, - ) - ) - elements.append(t) - elements.append(Spacer(1, SECTION_BUFFER_HEIGHT * 2)) - # /Products Table - if invoice.payment_status != 'paid' and invoice.payment_status != 'over_paid': - elements.append(Paragraph(settings.INVOICE_UNPAID_WARNING, styles['Left'])) - - elements.append(Spacer(1, SECTION_BUFFER_HEIGHT * 6)) - - # Remitttance Frame -# elements.append(FrameBreak()) -# boundary = BrokenLine(PAGE_WIDTH - 2 * (PAGE_MARGIN *1.1)) -# elements.append(boundary) -# elements.append(Spacer(1, SECTION_BUFFER_HEIGHT)) -# -# remittance = Remittance(HEADER_MARGIN,HEADER_MARGIN - 10,invoice) -# elements.append(remittance) - doc.build(elements) - - return confirmation_buffer - -def create_confirmation_pdf_bytes(filename, invoice, booking): - confirmation_buffer = BytesIO() - _create_confirmation(confirmation_buffer, invoice, booking) - - # Get the value of the BytesIO buffer - value = confirmation_buffer.getvalue() - confirmation_buffer.close() - - return value - diff --git a/commercialoperator/components/bookings/context_processors.py b/commercialoperator/components/bookings/context_processors.py deleted file mode 100644 index a6720bc168..0000000000 --- a/commercialoperator/components/bookings/context_processors.py +++ /dev/null @@ -1,43 +0,0 @@ -from django.conf import settings -from commercialoperator import helpers - -def commercialoperator_url(request): - web_url = request.META['HTTP_HOST'] - template_group = 'commercialoperator' - TERMS = "/know/online-commercialoperator-booking-terms-and-conditions" - - is_officer = False - is_admin = False - is_customer = False - - if request.user.is_authenticated: - #is_officer = helpers.is_officer(request) - is_admin = helpers.is_commercialoperator_admin(request) - is_customer = helpers.is_customer(request) - - return { - 'EXPLORE_PARKS_SEARCH': '/external/payment', - 'EXPLORE_PARKS_CONTACT': '/contact-us', - #'EXPLORE_PARKS_CONSERVE': '/know/conserving-our-moorings', - #'EXPLORE_PARKS_PEAK_PERIODS': '/know/when-visit', - 'EXPLORE_PARKS_ENTRY_FEES': '/know/entry-fees', - 'EXPLORE_PARKS_TERMS': TERMS, - 'DEV_STATIC': settings.DEV_STATIC, - 'DEV_STATIC_URL': settings.DEV_STATIC_URL, - 'TEMPLATE_GROUP' : template_group, - 'SYSTEM_NAME' : settings.SYSTEM_NAME, - 'IS_OFFICER' : is_officer, - 'IS_ADMIN' : is_admin, - 'IS_CUSTOMER' : is_customer, - 'PUBLIC_URL' : settings.PUBLIC_URL - } - - -def template_context(request): - """Pass extra context variables to every template. - """ - context = commercialoperator_url(request) - return context - - - diff --git a/commercialoperator/components/bookings/email.py b/commercialoperator/components/bookings/email.py deleted file mode 100755 index 6eb87c2f4b..0000000000 --- a/commercialoperator/components/bookings/email.py +++ /dev/null @@ -1,401 +0,0 @@ -import logging - -from django.core.mail import EmailMultiAlternatives, EmailMessage -from django.utils.encoding import smart_text -from django.core.urlresolvers import reverse -from django.conf import settings - -from commercialoperator.components.emails.emails import TemplateEmailBase -from commercialoperator.components.bookings.invoice_pdf import create_invoice_pdf_bytes -from commercialoperator.components.bookings.confirmation_pdf import create_confirmation_pdf_bytes -from commercialoperator.components.bookings.models import Booking - -logger = logging.getLogger(__name__) - -SYSTEM_NAME = settings.SYSTEM_NAME_SHORT + ' Automated Message' - -class ApplicationFeeInvoiceTClassSendNotificationEmail(TemplateEmailBase): - subject = 'Your application fee invoice.' - html_template = 'commercialoperator/emails/bookings/tclass/send_application_fee_notification.html' - txt_template = 'commercialoperator/emails/bookings/tclass/send_application_fee_notification.txt' - -class ApplicationFeeConfirmationTClassSendNotificationEmail(TemplateEmailBase): - subject = 'Your application fee confirmation.' - html_template = 'commercialoperator/emails/bookings/tclass/send_application_fee_confirmation_notification.html' - txt_template = 'commercialoperator/emails/bookings/tclass/send_application_fee_confirmation_notification.txt' - - -class InvoiceTClassSendNotificationEmail(TemplateEmailBase): - subject = 'Your booking invoice.' - html_template = 'commercialoperator/emails/bookings/tclass/send_invoice_notification.html' - txt_template = 'commercialoperator/emails/bookings/tclass/send_invoice_notification.txt' - -class ConfirmationTClassSendNotificationEmail(TemplateEmailBase): - subject = 'Your booking confirmation.' - html_template = 'commercialoperator/emails/bookings/tclass/send_confirmation_notification.html' - txt_template = 'commercialoperator/emails/bookings/tclass/send_confirmation_notification.txt' - -class MonthlyInvoicesFailedTClassEmail(TemplateEmailBase): - subject = 'Failed: COLS Monthly Invoices.' - html_template = 'commercialoperator/emails/bookings/tclass/send_monthly_invoices_failed_notification.html' - txt_template = 'commercialoperator/emails/bookings/tclass/send_monthly_invoices_failed_notification.txt' - -class SendPaymentDueNotificationTClassEmail(TemplateEmailBase): - subject = 'COLS Monthly/BPAY Bookings Invoices Overdue.' - html_template = 'commercialoperator/emails/bookings/tclass/send_payment_due_notification.html' - txt_template = 'commercialoperator/emails/bookings/tclass/send_payment_due_notification.txt' - -class SendExternalPaymentDueNotificationTClassEmail(TemplateEmailBase): - subject = 'Your booking invoice is overdue.' - html_template = 'commercialoperator/emails/bookings/tclass/send_external_payment_due_notification.html' - txt_template = 'commercialoperator/emails/bookings/tclass/send_external_payment_due_notification.txt' - -class PaymentDueNotificationFailedTClassEmail(TemplateEmailBase): - subject = 'Failed: COLS Payment Due Notifications' - html_template = 'commercialoperator/emails/bookings/tclass/send_external_payment_due_notification_failed.html' - txt_template = 'commercialoperator/emails/bookings/tclass/send_external_payment_due_notification_failed.txt' - -def send_application_fee_invoice_tclass_email_notification(request, proposal, invoice, recipients, is_test=False): - email = ApplicationFeeInvoiceTClassSendNotificationEmail() - #url = request.build_absolute_uri(reverse('external-proposal-detail',kwargs={'proposal_pk': proposal.id})) - - context = { - 'lodgement_number': proposal.lodgement_number, - #'url': url, - } - - filename = 'invoice.pdf' - doc = create_invoice_pdf_bytes(filename, invoice, proposal) - attachment = (filename, doc, 'application/pdf') - - msg = email.send(recipients, attachments=[attachment], context=context) - if is_test: - return - - sender = request.user if request else settings.DEFAULT_FROM_EMAIL - _log_proposal_email(msg, proposal, sender=sender) -# try: -# _log_org_email(msg, proposal.applicant, proposal.submitter, sender=sender) -# except: -# _log_org_email(msg, proposal.submitter, proposal.submitter, sender=sender) - if proposal.org_applicant: - _log_org_email(msg, proposal.org_applicant, proposal.submitter, sender=sender) - else: - _log_user_email(msg, proposal.submitter, proposal.submitter, sender=sender) - - -def send_application_fee_confirmation_tclass_email_notification(request, application_fee, invoice, recipients, is_test=False): - email = ApplicationFeeConfirmationTClassSendNotificationEmail() - #url = request.build_absolute_uri(reverse('external-proposal-detail',kwargs={'proposal_pk': proposal.id})) - - proposal = application_fee.proposal - context = { - 'lodgement_number': proposal.lodgement_number, - #'url': url, - } - - filename = 'confirmation.pdf' - doc = create_confirmation_pdf_bytes(filename, invoice, application_fee) - #doc = create_invoice_pdf_bytes(filename, invoice, proposal) - attachment = (filename, doc, 'application/pdf') - - msg = email.send(recipients, attachments=[attachment], context=context) - if is_test: - return - - sender = request.user if request else settings.DEFAULT_FROM_EMAIL - _log_proposal_email(msg, proposal, sender=sender) - if proposal.org_applicant: - _log_org_email(msg, proposal.org_applicant, proposal.submitter, sender=sender) - else: - _log_user_email(msg, proposal.submitter, proposal.submitter, sender=sender) - -def send_invoice_tclass_email_notification(request, booking, invoice, recipients, is_test=False): - email = InvoiceTClassSendNotificationEmail() - #url = request.build_absolute_uri(reverse('external-proposal-detail',kwargs={'proposal_pk': proposal.id})) - - context = { - 'booking_number': booking.booking_number, - #'url': url, - } - - filename = 'invoice.pdf' - doc = create_invoice_pdf_bytes(filename, invoice, booking.proposal) - attachment = (filename, doc, 'application/pdf') - - msg = email.send(recipients, attachments=[attachment], context=context) - if is_test: - return - - sender = request.user if request else settings.DEFAULT_FROM_EMAIL - _log_proposal_email(msg, booking.proposal, sender=sender) - #_log_org_email(msg, booking.proposal.applicant, booking.proposal.submitter, sender=sender) - if booking.proposal.org_applicant: - _log_org_email(msg, booking.proposal.org_applicant, booking.proposal.submitter, sender=sender) - else: - _log_user_email(msg, booking.proposal.submitter, booking.proposal.submitter, sender=sender) - -def send_confirmation_tclass_email_notification(request, booking, invoice, recipients, is_test=False): - email = ConfirmationTClassSendNotificationEmail() - #url = request.build_absolute_uri(reverse('external-proposal-detail',kwargs={'proposal_pk': proposal.id})) - - context = { - 'booking_number': booking.booking_number, - #'url': url, - } - - filename = 'confirmation.pdf' - doc = create_confirmation_pdf_bytes(filename, invoice, booking) - attachment = (filename, doc, 'application/pdf') - - msg = email.send(recipients, attachments=[attachment], context=context) - if is_test: - return - - sender = request.user if request else settings.DEFAULT_FROM_EMAIL - _log_proposal_email(msg, booking.proposal, sender=sender) - #_log_org_email(msg, booking.proposal.applicant, booking.proposal.submitter, sender=sender) - if booking.proposal.org_applicant: - _log_org_email(msg, booking.proposal.org_applicant, booking.proposal.submitter, sender=sender) - else: - _log_user_email(msg, booking.proposal.submitter, booking.proposal.submitter, sender=sender) - -def send_proposal_approval_email_notification(proposal,request): - email = ProposalApprovalSendNotificationEmail() - - context = { - 'proposal': proposal, - - } - cc_list = proposal.proposed_issuance_approval['cc_email'] - all_ccs = [] - if cc_list: - all_ccs = cc_list.split(',') - - licence_document= proposal.approval.licence_document._file - if licence_document is not None: - file_name = proposal.approval.licence_document.name - attachment = (file_name, licence_document.file.read(), 'application/pdf') - attachment = [attachment] - else: - attachment = [] - - msg = email.send(proposal.submitter.email, bcc= all_ccs, attachments=attachment, context=context) - sender = request.user if request else settings.DEFAULT_FROM_EMAIL - _log_proposal_email(msg, proposal, sender=sender) - #_log_org_email(msg, proposal.applicant, proposal.submitter, sender=sender) - if proposal.org_applicant: - _log_org_email(msg, proposal.org_applicant, proposal.submitter, sender=sender) - else: - _log_user_email(msg, proposal.submitter, proposal.submitter, sender=sender) - -def send_monthly_invoice_tclass_email_notification(sender, booking, invoice, recipients, is_test=False): - email = MonthlyInvoiceTClassSendNotificationEmail() - - context = { - 'booking_number': booking.booking_number, - } - - filename = 'monthly_invoice.pdf' - doc = create_invoice_pdf_bytes(filename, invoice, booking.proposal) - attachment = (filename, doc, 'application/pdf') - - msg = email.send(recipients, attachments=[attachment], context=context) - if is_test: - return - - _log_proposal_email(msg, booking.proposal, sender=sender) - if booking.proposal.org_applicant: - _log_org_email(msg, booking.proposal.org_applicant, booking.proposal.submitter, sender=sender) - else: - _log_user_email(msg, booking.proposal.submitter, booking.proposal.submitter, sender=sender) - -def send_monthly_invoices_failed_tclass(booking_ids): - """ Internal failed notification email for Monthly Invoicing script """ - email = MonthlyInvoicesFailedTClassEmail() - - context = { - 'bookings': Booking.objects.filter(id__in=booking_ids).values_list('id', 'admission_number', 'proposal__lodgement_number', 'proposal__org_applicant__organisation__name'), - } - msg = email.send(settings.NOTIFICATION_EMAIL, context=context) - -def send_payment_due_notification_failed_tclass(bookings): - """ Internal failed notification email for Payment Due Notification script """ - email = PaymentDueNotificationFailedTClassEmail() - - context = { - 'bookings': bookings - } - msg = email.send(settings.NOTIFICATION_EMAIL, context=context) - -def send_invoice_payment_due_tclass_email_notification(sender, bookings, recipients, is_test=False): - email = SendPaymentDueNotificationTClassEmail() - - context = { - 'bookings': bookings, - } - - msg = email.send(booking.proposal.submitter.email, context=context) - #sender = sender if sender else settings.DEFAULT_FROM_EMAIL - #_log_proposal_email(msg, booking.proposal, sender=sender) - #if booking.proposal.org_applicant: - # _log_org_email(msg, booking.proposal.org_applicant, booking.proposal.submitter, sender=sender) - #else: - # _log_user_email(msg, booking.proposal.submitter, booking.proposal.submitter, sender=sender) - -def send_invoice_payment_due_tclass_external_email_notification(sender, booking, recipients, is_test=False): - email = SendExternalPaymentDueNotificationTClassEmail() - - context = { - 'booking': booking, - } - - msg = email.send(booking.proposal.submitter.email, context=context) - sender = sender if sender else settings.DEFAULT_FROM_EMAIL - _log_proposal_email(msg, booking.proposal, sender=sender) - if booking.proposal.org_applicant: - _log_org_email(msg, booking.proposal.org_applicant, booking.proposal.submitter, sender=sender) - else: - _log_user_email(msg, booking.proposal.submitter, booking.proposal.submitter, sender=sender) - - - - -def _log_proposal_email(email_message, proposal, sender=None): - from commercialoperator.components.proposals.models import ProposalLogEntry - if isinstance(email_message, (EmailMultiAlternatives, EmailMessage,)): - # TODO this will log the plain text body, should we log the html instead - text = email_message.body - subject = email_message.subject - fromm = smart_text(sender) if sender else smart_text(email_message.from_email) - # the to email is normally a list - if isinstance(email_message.to, list): - to = ','.join(email_message.to) - else: - to = smart_text(email_message.to) - # we log the cc and bcc in the same cc field of the log entry as a ',' comma separated string - all_ccs = [] - if email_message.cc: - all_ccs += list(email_message.cc) - if email_message.bcc: - all_ccs += list(email_message.bcc) - all_ccs = ','.join(all_ccs) - - else: - text = smart_text(email_message) - subject = '' - to = proposal.submitter.email - fromm = smart_text(sender) if sender else SYSTEM_NAME - all_ccs = '' - - customer = proposal.submitter - - staff = sender - - kwargs = { - 'subject': subject, - 'text': text, - 'proposal': proposal, - 'customer': customer, - 'staff': staff, - 'to': to, - 'fromm': fromm, - 'cc': all_ccs - } - - email_entry = ProposalLogEntry.objects.create(**kwargs) - - return email_entry - - -def _log_org_email(email_message, organisation, customer ,sender=None): - from commercialoperator.components.organisations.models import OrganisationLogEntry - if isinstance(email_message, (EmailMultiAlternatives, EmailMessage,)): - # TODO this will log the plain text body, should we log the html instead - text = email_message.body - subject = email_message.subject - fromm = smart_text(sender) if sender else smart_text(email_message.from_email) - # the to email is normally a list - if isinstance(email_message.to, list): - to = ','.join(email_message.to) - else: - to = smart_text(email_message.to) - # we log the cc and bcc in the same cc field of the log entry as a ',' comma separated string - all_ccs = [] - if email_message.cc: - all_ccs += list(email_message.cc) - if email_message.bcc: - all_ccs += list(email_message.bcc) - all_ccs = ','.join(all_ccs) - - else: - text = smart_text(email_message) - subject = '' - to = customer - fromm = smart_text(sender) if sender else SYSTEM_NAME - all_ccs = '' - - customer = customer - - staff = sender - - kwargs = { - 'subject': subject, - 'text': text, - 'organisation': organisation, - 'customer': customer, - 'staff': staff, - 'to': to, - 'fromm': fromm, - 'cc': all_ccs - } - - email_entry = OrganisationLogEntry.objects.create(**kwargs) - - return email_entry - -def _log_user_email(email_message, emailuser, customer ,sender=None): - from ledger.accounts.models import EmailUserLogEntry - if isinstance(email_message, (EmailMultiAlternatives, EmailMessage,)): - # TODO this will log the plain text body, should we log the html instead - text = email_message.body - subject = email_message.subject - fromm = smart_text(sender) if sender else smart_text(email_message.from_email) - # the to email is normally a list - if isinstance(email_message.to, list): - to = ','.join(email_message.to) - else: - to = smart_text(email_message.to) - # we log the cc and bcc in the same cc field of the log entry as a ',' comma separated string - all_ccs = [] - if email_message.cc: - all_ccs += list(email_message.cc) - if email_message.bcc: - all_ccs += list(email_message.bcc) - all_ccs = ','.join(all_ccs) - - else: - text = smart_text(email_message) - subject = '' - to = customer - fromm = smart_text(sender) if sender else SYSTEM_NAME - all_ccs = '' - - customer = customer - - staff = sender - - kwargs = { - 'subject': subject, - 'text': text, - 'emailuser': emailuser, - 'customer': customer, - 'staff': staff, - 'to': to, - 'fromm': fromm, - 'cc': all_ccs - } - - email_entry = EmailUserLogEntry.objects.create(**kwargs) - - return email_entry diff --git a/commercialoperator/components/bookings/invoice_pdf.py b/commercialoperator/components/bookings/invoice_pdf.py deleted file mode 100644 index 8888a914c2..0000000000 --- a/commercialoperator/components/bookings/invoice_pdf.py +++ /dev/null @@ -1,375 +0,0 @@ -import os - -from decimal import Decimal as D -from io import BytesIO -from oscar.templatetags.currency_filters import currency -from reportlab.lib import enums -from reportlab.lib.pagesizes import A4 -from reportlab.platypus import BaseDocTemplate, PageTemplate, Frame, Paragraph, Spacer, Table, TableStyle, ListFlowable, \ - KeepTogether, PageBreak, Flowable, NextPageTemplate, FrameBreak -from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle -from reportlab.lib.utils import ImageReader -from reportlab.pdfgen.canvas import Canvas -from reportlab.pdfbase import pdfmetrics -from reportlab.lib.units import inch -from reportlab.lib import colors - -from django.core.files import File -from django.conf import settings - -from ledger.accounts.models import Document -from ledger.checkout.utils import calculate_excl_gst - -DPAW_HEADER_LOGO = os.path.join(settings.BASE_DIR, 'ledger', 'payments','static', 'payments', 'img','dbca_logo.jpg') -DPAW_HEADER_LOGO_SM = os.path.join(settings.BASE_DIR, 'ledger', 'payments','static', 'payments', 'img','dbca_logo_small.png') -BPAY_LOGO = os.path.join(settings.BASE_DIR, 'ledger', 'payments','static', 'payments', 'img', 'BPAY_2012_PORT_BLUE.png') - -HEADER_MARGIN = 10 -HEADER_SMALL_BUFFER = 3 - -PAGE_MARGIN = 20 -PAGE_TOP_MARGIN = 200 - -PAGE_WIDTH, PAGE_HEIGHT = A4 - -DEFAULT_FONTNAME = 'Helvetica' -BOLD_FONTNAME = 'Helvetica-Bold' - -VERY_LARGE_FONTSIZE = 14 -LARGE_FONTSIZE = 12 -MEDIUM_FONTSIZE = 10 -SMALL_FONTSIZE = 8 - -PARAGRAPH_BOTTOM_MARGIN = 5 - -SECTION_BUFFER_HEIGHT = 10 - -DATE_FORMAT = '%d/%m/%Y' - -styles = getSampleStyleSheet() -styles.add(ParagraphStyle(name='InfoTitleLargeCenter', fontName=BOLD_FONTNAME, fontSize=LARGE_FONTSIZE, - spaceAfter=PARAGRAPH_BOTTOM_MARGIN, alignment=enums.TA_CENTER)) -styles.add(ParagraphStyle(name='InfoTitleVeryLargeCenter', fontName=BOLD_FONTNAME, fontSize=VERY_LARGE_FONTSIZE, - spaceAfter=PARAGRAPH_BOTTOM_MARGIN * 2, alignment=enums.TA_CENTER)) -styles.add(ParagraphStyle(name='InfoTitleLargeLeft', fontName=BOLD_FONTNAME, fontSize=LARGE_FONTSIZE, - spaceAfter=PARAGRAPH_BOTTOM_MARGIN, alignment=enums.TA_LEFT, - leftIndent=PAGE_WIDTH / 10, rightIndent=PAGE_WIDTH / 10)) -styles.add(ParagraphStyle(name='InfoTitleLargeRight', fontName=BOLD_FONTNAME, fontSize=LARGE_FONTSIZE, - spaceAfter=PARAGRAPH_BOTTOM_MARGIN, alignment=enums.TA_RIGHT, - rightIndent=PAGE_WIDTH / 10)) -styles.add(ParagraphStyle(name='BoldLeft', fontName=BOLD_FONTNAME, fontSize=MEDIUM_FONTSIZE, alignment=enums.TA_LEFT)) -styles.add(ParagraphStyle(name='BoldRight', fontName=BOLD_FONTNAME, fontSize=MEDIUM_FONTSIZE, alignment=enums.TA_RIGHT)) -styles.add(ParagraphStyle(name='Center', alignment=enums.TA_CENTER)) -styles.add(ParagraphStyle(name='Left', alignment=enums.TA_LEFT)) -styles.add(ParagraphStyle(name='Right', alignment=enums.TA_RIGHT)) -styles.add(ParagraphStyle(name='LongString', alignment=enums.TA_LEFT,wordWrap='CJK')) - -class BrokenLine(Flowable): - - def __init__(self, width,height=0): - Flowable.__init__(self) - self.width = width - self.height = height - - def __repr__(self): - return 'Line {}'.format(self.width) - - def draw(self): - self.canv.setDash(3,3) - self.canv.line(0, self.height,self.width,self.height) - -class Remittance(Flowable): - def __init__(self, current_x, current_y, proposal, invoice): - Flowable.__init__(self) - self.current_x = current_x - self.current_y = current_y - self.proposal = proposal - self.invoice = invoice - - def __repr__(self): - return 'remittance' - - def __logo_line(self): - canvas = self.canv - current_y, current_x = self.current_y, self.current_x - canvas.setFont(DEFAULT_FONTNAME, MEDIUM_FONTSIZE) - dpaw_header_logo = ImageReader(DPAW_HEADER_LOGO_SM) - - dpaw_header_logo_size = dpaw_header_logo.getSize() - canvas.drawImage(dpaw_header_logo, HEADER_MARGIN, current_y - (dpaw_header_logo_size[1]/1.8),height=dpaw_header_logo_size[1]/1.8, mask='auto', width=dpaw_header_logo_size[0]/1.8) - - current_y = -20 - canvas.setFont(BOLD_FONTNAME, MEDIUM_FONTSIZE) - canvas.drawRightString(current_x * 45,current_y,'Remittance Advice') - - #current_y -= 20 - #canvas.setFont(DEFAULT_FONTNAME, MEDIUM_FONTSIZE) - #canvas.drawString(current_x * 27,current_y,'PLEASE DETACH AND RETURN WITH YOUR PAYMENT') - - current_y -= 50 - canvas.setFont(DEFAULT_FONTNAME, MEDIUM_FONTSIZE) - canvas.drawString(current_x, current_y, 'ABN: 38 052 249 024') - self.current_y = current_y - - def __payment_line(self): - canvas = self.canv - current_y, current_x = self.current_y, self.current_x - bpay_logo = ImageReader(BPAY_LOGO) - #current_y -= 40 - # Pay By Cheque - cheque_x = current_x + 4 * inch - cheque_y = current_y - 10 - #canvas.setFont(BOLD_FONTNAME, MEDIUM_FONTSIZE) - #canvas.drawString(cheque_x, cheque_y, 'Pay By Cheque:') - #canvas.setFont(DEFAULT_FONTNAME, 9) - #cheque_y -= 15 - #canvas.drawString(cheque_x, cheque_y, 'Make cheque payable to: Department of Parks and Wildlife') - #cheque_y -= 15 - #canvas.drawString(cheque_x, cheque_y, 'Mail to: Department of Parks and Wildlife') - #cheque_y -= 15 - #canvas.drawString(cheque_x + 32, cheque_y, 'Locked Bag 30') - #cheque_y -= 15 - #canvas.drawString(cheque_x + 32, cheque_y, 'Bentley Delivery Centre WA 6983') - if self.invoice.payment_method in [self.invoice.PAYMENT_METHOD_MONTHLY_INVOICING, self.invoice.PAYMENT_METHOD_BPAY]: - # Outer BPAY Box - canvas.rect(current_x,current_y - 25,2.3*inch,-1.2*inch) - canvas.setFillColorCMYK(0.8829,0.6126,0.0000,0.5647) - # Move into bpay box - current_y += 5 - box_pos = current_x + 0.1 * inch - bpay_logo_size = bpay_logo.getSize() - canvas.drawImage(bpay_logo, box_pos, current_y - (bpay_logo_size[1]/12 * 1.7), height= bpay_logo_size[1]/12,width=bpay_logo_size[0]/12, mask='auto') - # Create biller information box - biller_x = box_pos + bpay_logo_size[0]/12 + 1 - canvas.rect(biller_x,(current_y - (bpay_logo_size[1]/12 * 1.7)) + 3,1.65*inch,(bpay_logo_size[1]/12)-5) - # Bpay info - canvas.setFont(BOLD_FONTNAME, MEDIUM_FONTSIZE) - info_y = ((current_y - (bpay_logo_size[1]/12 * 1.7)) + 3) + (0.35 * inch) - canvas.drawString(biller_x + 5, info_y, 'Biller Code: {}'.format(self.invoice.biller_code)) - canvas.drawString(biller_x + 5, info_y - 20, 'Ref: {}'.format(self.invoice.reference)) - # Bpay Info string - canvas.setFont(BOLD_FONTNAME,SMALL_FONTSIZE) - canvas.drawString(box_pos, info_y - 0.55 * inch, 'Telephone & Internet Banking - BPAY') - canvas.setFont(DEFAULT_FONTNAME,6.5) - canvas.drawString(box_pos, info_y - 0.65 * inch, 'Contact your bank or financial institution to make') - canvas.drawString(box_pos, info_y - 0.75 * inch, 'this payment from your cheque, savings, debit or') - canvas.drawString(box_pos, info_y - 0.85 * inch, 'transaction account. More info: www.bpay.com.au') - - self.current_y = current_y - - def __footer_line(self): - canvas = self.canv - current_y, current_x = self.current_y, self.current_x - current_y -= 2 * inch - canvas.setFont(DEFAULT_FONTNAME, LARGE_FONTSIZE) - canvas.setFillColor(colors.black) - canvas.drawString(current_x, current_y, 'Invoice Number') - canvas.drawString(PAGE_WIDTH/4, current_y, 'Invoice Date') - canvas.drawString((PAGE_WIDTH/4) * 2, current_y, 'GST included') - canvas.drawString((PAGE_WIDTH/4) * 3, current_y, 'Invoice Total') - current_y -= 20 - canvas.setFont(DEFAULT_FONTNAME, MEDIUM_FONTSIZE) - canvas.drawString(current_x, current_y, self.invoice.reference) - canvas.drawString(PAGE_WIDTH/4, current_y, self.invoice.created.strftime(DATE_FORMAT)) - canvas.drawString((PAGE_WIDTH/4) * 2, current_y, currency(self.invoice.amount - calculate_excl_gst(self.invoice.amount) if not _is_gst_exempt(self.proposal, self.invoice) else 0.0)) - canvas.drawString((PAGE_WIDTH/4) * 3, current_y, currency(self.invoice.amount)) - - def draw(self): - #if settings.BPAY_ALLOWED: - if self.invoice.payment_method in [self.invoice.PAYMENT_METHOD_MONTHLY_INVOICING, self.invoice.PAYMENT_METHOD_BPAY]: - self.__logo_line() - self.__payment_line() - self.__footer_line() - -#def _set_template_group(mooring_var): - - -#def get_template_group(mooring_var): - - - -def _create_header(canvas, doc, draw_page_number=True): - canvas.saveState() - canvas.setTitle('Invoice') - canvas.setFont(BOLD_FONTNAME, LARGE_FONTSIZE) - - current_y = PAGE_HEIGHT - HEADER_MARGIN - - dpaw_header_logo = ImageReader(DPAW_HEADER_LOGO) - dpaw_header_logo_size = dpaw_header_logo.getSize() - canvas.drawImage(dpaw_header_logo, PAGE_WIDTH / 3, current_y - (dpaw_header_logo_size[1]/2),width=dpaw_header_logo_size[0]/2, height=dpaw_header_logo_size[1]/2, mask='auto') - - current_y -= 70 - canvas.drawCentredString(PAGE_WIDTH / 2, current_y - LARGE_FONTSIZE, 'TAX INVOICE') - - current_y -= 20 - canvas.drawCentredString(PAGE_WIDTH / 2, current_y - LARGE_FONTSIZE, 'ABN: 38 052 249 024') - - # Invoice address details - invoice_details_offset = 37 - current_y -= 10 - - invoice = doc.invoice - proposal = doc.proposal - bi = proposal.bookings.filter(invoices__invoice_reference=invoice.reference) - licence_number = proposal.approval.lodgement_number if proposal.approval else None - - # TODO need to fix, since individual parks can be exempt, Below calculation assumes NO PARK IS exempt - #is_gst_exempt = proposal.application_type.is_gst_exempt if proposal.fee_invoice_reference == invoice.reference else False - - canvas.setFont(BOLD_FONTNAME, SMALL_FONTSIZE) - current_x = PAGE_MARGIN + 5 - if proposal.org_applicant: - canvas.drawString(current_x, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER), proposal.applicant) - canvas.drawString(current_x, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER) * 2,invoice.owner.get_full_name()) - canvas.drawString(current_x, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER) * 3,invoice.owner.email) - current_x += 452 - - #write Invoice details - canvas.drawString(current_x, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER),'Date') - canvas.drawString(current_x + invoice_details_offset, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER),invoice.created.strftime(DATE_FORMAT)) - canvas.drawString(current_x, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER) * 2, 'Page') - canvas.drawString(current_x + invoice_details_offset, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER) * 2, str(canvas.getPageNumber())) - canvas.drawRightString(current_x + 20, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER) * 3, 'Licence Number') - canvas.drawString(current_x + invoice_details_offset, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER) * 3, licence_number) - canvas.drawRightString(current_x + 20, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER) * 4, 'Invoice Number') - canvas.drawString(current_x + invoice_details_offset, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER) * 4, invoice.reference) - canvas.drawRightString(current_x + 20, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER) * 5, 'Total (AUD)') - canvas.drawString(current_x + invoice_details_offset, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER) * 5, currency(invoice.amount)) - canvas.drawRightString(current_x + 20, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER) * 6, 'GST included (AUD)') - canvas.drawString(current_x + invoice_details_offset, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER) * 6, currency(invoice.amount - calculate_excl_gst(invoice.amount) if not _is_gst_exempt(proposal, invoice) else 0.0)) - canvas.drawRightString(current_x + 20, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER) * 7, 'Paid (AUD)') - canvas.drawString(current_x + invoice_details_offset, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER) * 7, currency(invoice.payment_amount)) - canvas.drawRightString(current_x + 20, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER) * 8, 'Outstanding (AUD)') - canvas.drawString(current_x + invoice_details_offset, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER) * 8, currency(invoice.balance)) - - if bi and bi[0].deferred_payment_date and invoice.payment_method in [invoice.PAYMENT_METHOD_MONTHLY_INVOICING, invoice.PAYMENT_METHOD_BPAY]: - canvas.drawRightString(current_x + 20, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER) * 9, 'Payment Due Date') - canvas.drawString(current_x + invoice_details_offset, current_y - (SMALL_FONTSIZE + HEADER_SMALL_BUFFER) * 9, bi[0].deferred_payment_date.strftime(DATE_FORMAT)) - - canvas.restoreState() - -def _is_gst_exempt(proposal, invoice): - # TODO need to fix, since individual parks can be exempt, Below calculation assumes NO PARK IS exempt - return proposal.application_type.is_gst_exempt if proposal.fee_invoice_reference == invoice.reference else False - -def _create_invoice(invoice_buffer, invoice, proposal): - - global DPAW_HEADER_LOGO -# if cols_var["TEMPLATE_GROUP"] == 'rottnest': -# DPAW_HEADER_LOGO = os.path.join(settings.BASE_DIR, 'mooring', 'static', 'mooring', 'img','logo-rottnest-island-sm.png') -# else: -# DPAW_HEADER_LOGO = os.path.join(settings.BASE_DIR, 'ledger', 'payments','static', 'payments', 'img','dbca_logo.jpg') - DPAW_HEADER_LOGO = os.path.join(settings.BASE_DIR, 'ledger', 'payments','static', 'payments', 'img','dbca_logo.jpg') - - every_page_frame = Frame(PAGE_MARGIN, PAGE_MARGIN + 250, PAGE_WIDTH - 2 * PAGE_MARGIN, - PAGE_HEIGHT -450 , id='EveryPagesFrame',showBoundary=0) - remit_frame = Frame(PAGE_MARGIN, PAGE_MARGIN, PAGE_WIDTH - 2 * PAGE_MARGIN, - PAGE_HEIGHT - 600, id='RemitFrame',showBoundary=0) - every_page_template = PageTemplate(id='EveryPages', frames=[every_page_frame,remit_frame], onPage=_create_header) - - - doc = BaseDocTemplate(invoice_buffer, pageTemplates=[every_page_template], pagesize=A4) - - - # this is the only way to get data into the onPage callback function - doc.invoice = invoice - doc.proposal = proposal - owner = invoice.owner - - elements = [] - #elements.append(Spacer(1, SECTION_BUFFER_HEIGHT * 5)) - - # Draw Products Table - invoice_table_style = TableStyle([ - ('VALIGN', (0, 0), (-1, -1), 'TOP'), - ('GRID',(0, 0), (-1, -1),1, colors.black), - ('ALIGN', (0, 0), (-1, -1), 'LEFT') - ]) - items = invoice.order.lines.all() - discounts = invoice.order.basket_discounts - if invoice.text: - elements.append(Paragraph(invoice.text, styles['Left'])) - elements.append(Spacer(1, SECTION_BUFFER_HEIGHT * 2)) - data = [ - ['Item','Product', 'Quantity','Unit Price', 'Total'] - ] - val = 1 - s = styles["BodyText"] - s.wordWrap = 'CJK' - - for item in items: - data.append( - [ - val, - Paragraph(item.description, s), - item.quantity, - currency(item.unit_price_incl_tax), - currency(item.line_price_before_discounts_incl_tax) - ] - ) - val += 1 - # Discounts - data.append( - [ - '', - '', - '', - '' - ] - ) - for discount in discounts: - data.append( - [ - '', - discount.offer, - '', - '', - '-${}'.format(discount.amount) - ] - ) - val += 1 - t= Table( - data, - style=invoice_table_style, - hAlign='LEFT', - colWidths=( - 0.7 * inch, - None, - 0.7 * inch, - 1.0 * inch, - 1.0 * inch, - ) - ) - elements.append(t) - elements.append(Spacer(1, SECTION_BUFFER_HEIGHT * 2)) - # /Products Table - if invoice.payment_status != 'paid' and invoice.payment_status != 'over_paid': - elements.append(Paragraph(settings.INVOICE_UNPAID_WARNING, styles['Left'])) - - elements.append(Spacer(1, SECTION_BUFFER_HEIGHT * 6)) - - # Remitttance Frame - elements.append(FrameBreak()) - boundary = BrokenLine(PAGE_WIDTH - 2 * (PAGE_MARGIN *1.1)) - elements.append(boundary) - elements.append(Spacer(1, SECTION_BUFFER_HEIGHT)) - - remittance = Remittance(HEADER_MARGIN,HEADER_MARGIN - 10, proposal, invoice) - elements.append(remittance) - #_create_remittance(invoice_buffer,doc) - doc.build(elements) - - return invoice_buffer - -def create_invoice_pdf_bytes(filename, invoice, proposal): - invoice_buffer = BytesIO() - _create_invoice(invoice_buffer, invoice, proposal) - - # Get the value of the BytesIO buffer - value = invoice_buffer.getvalue() - invoice_buffer.close() - - return value - - diff --git a/commercialoperator/components/bookings/models.py b/commercialoperator/components/bookings/models.py deleted file mode 100644 index 3b6a364ddc..0000000000 --- a/commercialoperator/components/bookings/models.py +++ /dev/null @@ -1,355 +0,0 @@ -from __future__ import unicode_literals - -from datetime import datetime, timedelta -from django.db import models, transaction -from django.utils.encoding import python_2_unicode_compatible -from django.utils import timezone -from ledger.accounts.models import EmailUser, RevisionedMixin -from ledger.payments.models import Invoice -from commercialoperator.components.proposals.models import Proposal -from commercialoperator.components.main.models import Park -from decimal import Decimal as D -from ledger.checkout.utils import calculate_excl_gst - -import logging -logger = logging.getLogger(__name__) - -class Payment(RevisionedMixin): - - send_invoice = models.BooleanField(default=False) - confirmation_sent = models.BooleanField(default=False) - created = models.DateTimeField(default=timezone.now()) - expiry_time = models.DateTimeField(default=timezone.now() + timedelta(minutes=30), blank=True, null=True) - - class Meta: - app_label = 'commercialoperator' - abstract = True - - @property - def paid(self): - payment_status = self.__check_payment_status() - if payment_status == 'paid' or payment_status == 'over_paid': - return True - return False - - @property - def unpaid(self): - payment_status = self.__check_payment_status() - if payment_status == 'unpaid': - return True - return False - - @property - def amount_paid(self): - return self.__check_payment_amount() - - def __check_payment_amount(self): - amount = D('0.0') - if self.active_invoice: - return self.active_invoice.payment_amount - return amount - - - def __check_invoice_payment_status(self): - invoices = [] - payment_amount = D('0.0') - invoice_amount = D('0.0') - references = self.invoices.all().values('invoice_reference') - for r in references: - try: - invoices.append(Invoice.objects.get(reference=r.get("invoice_reference"))) - except Invoice.DoesNotExist: - pass - for i in invoices: - if not i.voided: - payment_amount += i.payment_amount - invoice_amount += i.amount - - if invoice_amount == payment_amount: - return 'paid' - if payment_amount > invoice_amount: - return 'over_paid' - return "unpaid" - - def __check_payment_status(self): - invoices = [] - amount = D('0.0') - references = self.invoices.all().values('invoice_reference') - for r in references: - try: - invoices.append(Invoice.objects.get(reference=r.get("invoice_reference"))) - except Invoice.DoesNotExist: - pass - for i in invoices: - if not i.voided: - amount += i.payment_amount - - if amount == 0: - return 'unpaid' - elif self.cost_total < amount: - return 'over_paid' - elif self.cost_total > amount: - return 'partially_paid' - return "paid" - - -class Booking(Payment): - BOOKING_TYPE_INTERNET = 0 - BOOKING_TYPE_RECEPTION = 1 - BOOKING_TYPE_BLACK = 2 - BOOKING_TYPE_TEMPORARY = 3 - BOOKING_TYPE_MONTHLY_INVOICING = 4 - BOOKING_TYPE_CHOICES = ( - (BOOKING_TYPE_INTERNET, 'Internet booking'), - (BOOKING_TYPE_RECEPTION, 'Reception booking'), - (BOOKING_TYPE_BLACK, 'Black booking'), - (BOOKING_TYPE_TEMPORARY, 'Temporary reservation'), - (BOOKING_TYPE_MONTHLY_INVOICING, 'Monthly invoicing'), -# (4, 'Cancelled Booking'), -# (5, 'Changed Booking') - ) - - proposal = models.ForeignKey(Proposal, on_delete=models.PROTECT, blank=True, null=True, related_name='bookings') - booking_type = models.SmallIntegerField(choices=BOOKING_TYPE_CHOICES, default=0) - admission_number = models.CharField(max_length=9, blank=True, default='') - created_by = models.ForeignKey(EmailUser,on_delete=models.PROTECT, blank=True, null=True,related_name='created_by_booking') - - def __str__(self): - return 'Application {} : Invoice {}'.format(self.proposal, self.invoices.last()) - - class Meta: - app_label = 'commercialoperator' - - @property - def next_id(self): - ids = map(int,[i.split('AD')[1] for i in Booking.objects.all().values_list('admission_number', flat=True) if i]) - return max(ids) + 1 if ids else 1 - -# def set_admission_number(self): -# """ Need to set admission_number after Credit Card Payment is successfully completed i.e. after BookingSuccessView.get() is executed. -# Prior to this, the Booking object is temporary. -# """ -# if self.admission_number == '': -# self.admission_number = 'AD{0:06d}'.format(self.next_id) -# self.save() - - def save(self, *args, **kwargs): - super(Booking, self).save(*args,**kwargs) - if self.admission_number == '': - self.admission_number = 'AD{0:06d}'.format(self.next_id) - self.save() - - @property - def booking_number(self): - return 'COLS-{0:06d}'.format(self.id) - - @property - def num_visitors(self): - if self.park_bookings: - for park_booking in park_bookings: - num_visitors += park_booking.num_visitors - return num_visitors - return 0 - - @property - def visitors(self): - if self.park_bookings: - for park_booking in park_bookings: - no_adults += park_booking.no_adults - no_children += park_booking.no_children - no_free_of_charge += park_booking.no_free_of_charge - return { - "adults" : no_adults, - "children" : no_children, - "free_of_charge" : no_free_of_charge - } - return { - "adults" : 0, - "children" : 0, - "free_of_charge" : 0 - } - - @property - def park_id_list(self): - #return list(set([x['campsite'] for x in self.campsites.all().values('campsite')])) - return self.park_bookings.all().values('park_id') - - @property - def park_name_list(self): - #return list(set(self.campsites.values_list('campsite__name', flat=True))) - return self.park_bookings.all().values('park__name') - - @property - def as_line_items(self): - """ returns a dict line item equiv of the Booking Object for ledger checkout """ - - lines = [] - for park_booking in self.park_bookings.all(): - lines += park_booking.as_line_items - return lines - - @property - def invoice(self): - return self.invoices.last().invoice - - @property - def deferred_payment_date(self): - return self.invoices.last().deferred_payment_date - -class ParkBooking(RevisionedMixin): - created = models.DateTimeField(default=timezone.now()) - booking = models.ForeignKey(Booking, on_delete=models.PROTECT, blank=True, null=True, related_name='park_bookings') - park = models.ForeignKey(Park, related_name='bookings') - arrival = models.DateField() - no_adults = models.SmallIntegerField(default=0) - no_children = models.SmallIntegerField(default=0) - no_free_of_charge = models.SmallIntegerField(default=0) - cost = models.DecimalField(max_digits=8, decimal_places=2, default='0.00') - - def __str__(self): - return 'Park {} : Arrival {} (Adults {}, Children {}, Free {})'.format(self.park.name, self.arrival, self.no_adults, self.no_children, self.no_free_of_charge) - - class Meta: - app_label = 'commercialoperator' - - @property - def num_visitors(self): - return self.no_adults + self.no_children + self.no_free_of_charge - - @property - def visitors(self): - return { - "adults" : self.no_adults, - "children" : self.no_children, - "free_of_charge" : self.no_free_of_charge - } - - @property - def as_line_items(self): - """ returns a dict line item equiv of the ParkBooking Object for ledger checkout (aggregated via Booking object)""" - def add_line_item(age_group, price, no_persons): - if no_persons > 0: - return { - 'ledger_description': 'Booking Date {}: {} - {} - {}'.format(self.created.date(), self.park.name, self.arrival, age_group), - 'oracle_code': self.park.oracle_code, - 'price_incl_tax': D(price), - 'price_excl_tax': D(price) if self.park.is_gst_exempt else calculate_excl_gst(D(price)), - 'quantity': no_persons, - } - return None - - lines = [] - if self.no_adults > 0: - lines.append(add_line_item('Adult', price=self.park.adult_price, no_persons=self.no_adults)) - - if self.no_children > 0: - lines.append(add_line_item('Child', price=self.park.child_price, no_persons=self.no_children)) - - if self.no_free_of_charge > 0: - lines.append(add_line_item('Free', price=0.0, no_persons=self.no_free_of_charge)) - - return lines - - -class BookingInvoice(RevisionedMixin): - PAYMENT_METHOD_CC = 0 - PAYMENT_METHOD_BPAY = 1 - PAYMENT_METHOD_MONTHLY_INVOICING = 2 - PAYMENT_METHOD_OTHER = 3 - PAYMENT_METHOD_CHOICES = ( - (PAYMENT_METHOD_CC, 'Credit Card'), - (PAYMENT_METHOD_BPAY, 'BPAY'), - (PAYMENT_METHOD_MONTHLY_INVOICING, 'Monthly Invoicing'), - (PAYMENT_METHOD_OTHER, 'Other (Cash/Cheque)'), - ) - - booking = models.ForeignKey(Booking, related_name='invoices') - invoice_reference = models.CharField(max_length=50, null=True, blank=True, default='') - payment_method = models.SmallIntegerField(choices=PAYMENT_METHOD_CHOICES, default=0) # duplicating from ledger Invoice model to allow easier filtering on payment dashboard - deferred_payment_date = models.DateField(blank=True, null=True) - payment_due_notification_sent = models.BooleanField(default=False) - - def __str__(self): - return 'Booking {} : Invoice #{}'.format(self.id,self.invoice_reference) - - class Meta: - app_label = 'commercialoperator' - - @property - def active(self): - try: - invoice = Invoice.objects.get(reference=self.invoice_reference) - return False if invoice.voided else True - except Invoice.DoesNotExist: - pass - return False - - @property - def invoice(self): - try: - invoice = Invoice.objects.get(reference=self.invoice_reference) - return invoice - except Invoice.DoesNotExist: - pass - return False - - @property - def overdue(self): - if self.invoice and self.invoice.settlement_date and (self.invoice.payment_status == 'unpaid' or self.invoice.payment_status == 'partially_paid') and self.invoice.settlement_datePlease find attached the confirmation for the application fee, for Application {{ booking_number }}, for your own records.

- -{% endblock %} diff --git a/commercialoperator/components/bookings/templates/commercialoperator/emails/bookings/tclass/send_application_fee_confirmation_notification.txt b/commercialoperator/components/bookings/templates/commercialoperator/emails/bookings/tclass/send_application_fee_confirmation_notification.txt deleted file mode 100755 index 600d4579c4..0000000000 --- a/commercialoperator/components/bookings/templates/commercialoperator/emails/bookings/tclass/send_application_fee_confirmation_notification.txt +++ /dev/null @@ -1,5 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.txt' %} - -{% block content %} - Please find attached the confirmation for the application fee, for Application {{ booking_number }}, for your own records. -{% endblock %} diff --git a/commercialoperator/components/bookings/templates/commercialoperator/emails/bookings/tclass/send_application_fee_notification.html b/commercialoperator/components/bookings/templates/commercialoperator/emails/bookings/tclass/send_application_fee_notification.html deleted file mode 100755 index e7d5b2a0b7..0000000000 --- a/commercialoperator/components/bookings/templates/commercialoperator/emails/bookings/tclass/send_application_fee_notification.html +++ /dev/null @@ -1,7 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} - -

Please find attached the invoice for the application fee, for Application {{ lodgement_number }}, for your own records.

- -{% endblock %} diff --git a/commercialoperator/components/bookings/templates/commercialoperator/emails/bookings/tclass/send_application_fee_notification.txt b/commercialoperator/components/bookings/templates/commercialoperator/emails/bookings/tclass/send_application_fee_notification.txt deleted file mode 100755 index 8e02223d25..0000000000 --- a/commercialoperator/components/bookings/templates/commercialoperator/emails/bookings/tclass/send_application_fee_notification.txt +++ /dev/null @@ -1,5 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.txt' %} - -{% block content %} - Please find attached the invoice for the application fee, for Application {{ lodgement_number }}, for your own records. -{% endblock %} diff --git a/commercialoperator/components/bookings/templates/commercialoperator/emails/bookings/tclass/send_confirmation_notification.html b/commercialoperator/components/bookings/templates/commercialoperator/emails/bookings/tclass/send_confirmation_notification.html deleted file mode 100755 index 2148f51748..0000000000 --- a/commercialoperator/components/bookings/templates/commercialoperator/emails/bookings/tclass/send_confirmation_notification.html +++ /dev/null @@ -1,9 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} - -

Please find attached the confirmation for your booking, {{ booking_number }}.

-
-

Print or save the attached confirmation for presentation on arrival and at any time during your visit.

- -{% endblock %} diff --git a/commercialoperator/components/bookings/templates/commercialoperator/emails/bookings/tclass/send_confirmation_notification.txt b/commercialoperator/components/bookings/templates/commercialoperator/emails/bookings/tclass/send_confirmation_notification.txt deleted file mode 100755 index 70551ce971..0000000000 --- a/commercialoperator/components/bookings/templates/commercialoperator/emails/bookings/tclass/send_confirmation_notification.txt +++ /dev/null @@ -1,7 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.txt' %} - -{% block content %} - Please find attached the confirmation for your booking, {{ booking_number }}. - - Print or save the attached confirmation for presentation on arrival and at any time during your visit. -{% endblock %} diff --git a/commercialoperator/components/bookings/templates/commercialoperator/emails/bookings/tclass/send_external_payment_due_notification.html b/commercialoperator/components/bookings/templates/commercialoperator/emails/bookings/tclass/send_external_payment_due_notification.html deleted file mode 100755 index 014bd2b8a3..0000000000 --- a/commercialoperator/components/bookings/templates/commercialoperator/emails/bookings/tclass/send_external_payment_due_notification.html +++ /dev/null @@ -1,9 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} - -

Your invoice for the following booking is overdue:

-
- Booking: {{booking.1}}, Proposal: {{booking.2}}, Invoice reference: {{booking.4}}, Payment due date: {{booking.5}}
- -{% endblock %} diff --git a/commercialoperator/components/bookings/templates/commercialoperator/emails/bookings/tclass/send_external_payment_due_notification.txt b/commercialoperator/components/bookings/templates/commercialoperator/emails/bookings/tclass/send_external_payment_due_notification.txt deleted file mode 100755 index da51db62c6..0000000000 --- a/commercialoperator/components/bookings/templates/commercialoperator/emails/bookings/tclass/send_external_payment_due_notification.txt +++ /dev/null @@ -1,9 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} - - Your invoice for the following booking is overdue: - - Booking: {{booking.1}}, Proposal: {{booking.2}}, Invoice reference: {{booking.4}}, Payment due date: {{booking.5}} - -{% endblock %} diff --git a/commercialoperator/components/bookings/templates/commercialoperator/emails/bookings/tclass/send_invoice_notification.html b/commercialoperator/components/bookings/templates/commercialoperator/emails/bookings/tclass/send_invoice_notification.html deleted file mode 100755 index b73bad8cee..0000000000 --- a/commercialoperator/components/bookings/templates/commercialoperator/emails/bookings/tclass/send_invoice_notification.html +++ /dev/null @@ -1,10 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} - - - -

Please find attached the invoice for park entry {{ booking_number }}

-

A copy of all invoices is saved in the online system, to view them please login to your account.

- -{% endblock %} diff --git a/commercialoperator/components/bookings/templates/commercialoperator/emails/bookings/tclass/send_invoice_notification.txt b/commercialoperator/components/bookings/templates/commercialoperator/emails/bookings/tclass/send_invoice_notification.txt deleted file mode 100755 index f9c46c7759..0000000000 --- a/commercialoperator/components/bookings/templates/commercialoperator/emails/bookings/tclass/send_invoice_notification.txt +++ /dev/null @@ -1,6 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.txt' %} - -{% block content %} - Please find attached the invoice for park entry {{ booking_number }} - A copy of all invoices is saved in the online system, to view them please login to your account. -{% endblock %} diff --git a/commercialoperator/components/bookings/templates/commercialoperator/emails/bookings/tclass/send_monthly_invoices_failed_notification.html b/commercialoperator/components/bookings/templates/commercialoperator/emails/bookings/tclass/send_monthly_invoices_failed_notification.html deleted file mode 100755 index c0ee596c18..0000000000 --- a/commercialoperator/components/bookings/templates/commercialoperator/emails/bookings/tclass/send_monthly_invoices_failed_notification.html +++ /dev/null @@ -1,13 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} - -

The following monthly invoices failed:

-
- {% for booking in bookings %} - Booking: {{booking.1}}, Proposal: {{booking.2}}, Organisation: {{booking.3}}
- {% endfor %} -
-

Please investigate and resend invoices.

- -{% endblock %} diff --git a/commercialoperator/components/bookings/templates/commercialoperator/emails/bookings/tclass/send_monthly_invoices_failed_notification.txt b/commercialoperator/components/bookings/templates/commercialoperator/emails/bookings/tclass/send_monthly_invoices_failed_notification.txt deleted file mode 100755 index 5e6484b603..0000000000 --- a/commercialoperator/components/bookings/templates/commercialoperator/emails/bookings/tclass/send_monthly_invoices_failed_notification.txt +++ /dev/null @@ -1,13 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} - - The following monthly invoices failed: - - {% for booking in bookings %} - Booking: {{booking.1}}, Proposal: {{booking.2}}, Organisation: {{booking.3}} - {% endfor %} - - Please investigate and resend invoices. - -{% endblock %} diff --git a/commercialoperator/components/bookings/templates/commercialoperator/emails/bookings/tclass/send_payment_due_failed_notification.html b/commercialoperator/components/bookings/templates/commercialoperator/emails/bookings/tclass/send_payment_due_failed_notification.html deleted file mode 100755 index c240b07f42..0000000000 --- a/commercialoperator/components/bookings/templates/commercialoperator/emails/bookings/tclass/send_payment_due_failed_notification.html +++ /dev/null @@ -1,13 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} - -

The following Payment Due Notifications failed:

-
- {% for booking in bookings %} - Booking: {{booking.admission_number}}, Proposal: {{booking.proposal.lodgement_number}}, Organisation: {{booking.proposal.applicant}}, Invoice: {{booking.invoice.reference}}, Payment Due: {{booking.invoice.settlement_date}}
- {% endfor %} -
-

Please investigate/resend notifications

- -{% endblock %} diff --git a/commercialoperator/components/bookings/templates/commercialoperator/emails/bookings/tclass/send_payment_due_failed_notification.txt b/commercialoperator/components/bookings/templates/commercialoperator/emails/bookings/tclass/send_payment_due_failed_notification.txt deleted file mode 100755 index c0ee596c18..0000000000 --- a/commercialoperator/components/bookings/templates/commercialoperator/emails/bookings/tclass/send_payment_due_failed_notification.txt +++ /dev/null @@ -1,13 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} - -

The following monthly invoices failed:

-
- {% for booking in bookings %} - Booking: {{booking.1}}, Proposal: {{booking.2}}, Organisation: {{booking.3}}
- {% endfor %} -
-

Please investigate and resend invoices.

- -{% endblock %} diff --git a/commercialoperator/components/bookings/templates/commercialoperator/emails/bookings/tclass/send_payment_due_notification.html b/commercialoperator/components/bookings/templates/commercialoperator/emails/bookings/tclass/send_payment_due_notification.html deleted file mode 100755 index 3a66e5359a..0000000000 --- a/commercialoperator/components/bookings/templates/commercialoperator/emails/bookings/tclass/send_payment_due_notification.html +++ /dev/null @@ -1,12 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} - -

Invoices for the following monthly/BPAY bookings are overdue:

-
- {% for booking in bookings %} - Booking: {{booking.admission_number}}, Proposal: {{booking.proposal.lodgement_number}}, Organisation: {{booking.proposal.applicant}}, Invoice: {{booking.invoice.reference}}, Payment due date: {{booking.invoice.settlement_date}}
- {% endfor %} -
- -{% endblock %} diff --git a/commercialoperator/components/bookings/templates/commercialoperator/emails/bookings/tclass/send_payment_due_notification.txt b/commercialoperator/components/bookings/templates/commercialoperator/emails/bookings/tclass/send_payment_due_notification.txt deleted file mode 100755 index 3ad2c8aad2..0000000000 --- a/commercialoperator/components/bookings/templates/commercialoperator/emails/bookings/tclass/send_payment_due_notification.txt +++ /dev/null @@ -1,11 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} - - Invoices for the following monthly/BPAY bookings are overdue: - - {% for booking in bookings %} - Booking: {{booking.1}}, Proposal: {{booking.2}}, Organisation: {{booking.3}}, Invoice reference: {{booking.4}}, Payment due date: {{booking.5}} - {% endfor %} - -{% endblock %} diff --git a/commercialoperator/components/bookings/utils.py b/commercialoperator/components/bookings/utils.py deleted file mode 100644 index 2fce921516..0000000000 --- a/commercialoperator/components/bookings/utils.py +++ /dev/null @@ -1,473 +0,0 @@ -from django.http import HttpResponseRedirect -from django.core.urlresolvers import reverse -from django.conf import settings -from django.core.exceptions import ValidationError -from django.db import transaction - -from datetime import datetime, timedelta, date -from django.utils import timezone -from dateutil.relativedelta import relativedelta -from commercialoperator.components.main.models import Park -from commercialoperator.components.proposals.models import Proposal -from commercialoperator.components.organisations.models import Organisation -from commercialoperator.components.bookings.models import Booking, ParkBooking, BookingInvoice, ApplicationFee -from commercialoperator.components.bookings.email import send_monthly_invoice_tclass_email_notification -from ledger.checkout.utils import create_basket_session, create_checkout_session, calculate_excl_gst -from ledger.payments.models import Invoice -from ledger.payments.utils import oracle_parser -import json -import ast -from decimal import Decimal - -import logging -logger = logging.getLogger('payment_checkout') - - -def create_booking(request, proposal, booking_type=Booking.BOOKING_TYPE_TEMPORARY): - """ Create the ledger lines - line items for invoice sent to payment system """ - - if booking_type == Booking.BOOKING_TYPE_MONTHLY_INVOICING and proposal.org_applicant and proposal.org_applicant.monthly_invoicing_allowed: - booking, created = Booking.objects.get_or_create( - invoices__isnull=True, - proposal_id=proposal.id, - booking_type=booking_type, - created__month=timezone.now().month, - defaults={ - 'created_by': request.user, - 'created': timezone.now(), - } - ) - lines = ast.literal_eval(request.POST['line_details'])['tbody'] - - elif (booking_type == Booking.BOOKING_TYPE_INTERNET and proposal.org_applicant and proposal.org_applicant.bpay_allowed) or \ - (booking_type == Booking.BOOKING_TYPE_RECEPTION): - #(booking_type == Booking.BOOKING_TYPE_RECEPTION and proposal.org_applicant.other_allowed): - booking = Booking.objects.create(proposal_id=proposal.id, created_by=request.user, booking_type=booking_type) - lines = ast.literal_eval(request.POST['line_details'])['tbody'] - - else: - booking = Booking.objects.create(proposal_id=proposal.id, created_by=request.user, booking_type=booking_type) - lines = json.loads(request.POST['payment'])['tbody'] - - #Booking.objects.filter(invoices__isnull=True, booking_type=4, proposal_id=478, proposal__org_applicant=org) - - #tbody = json.loads(request.POST['payment'])['tbody'] - #lines = ast.literal_eval(request.POST['line_details'])['tbody'] - for row in lines: - park_id = row[0]['value'] - arrival = row[1] - no_adults = int(row[2]) if row[2] else 0 - no_children = int(row[3]) if row[3] else 0 - no_free_of_charge = int(row[4]) if row[4] else 0 - park = Park.objects.get(id=park_id) - - if any([no_adults, no_children, no_free_of_charge]) > 0: - park_booking = ParkBooking.objects.create( - booking = booking, - park_id = park_id, - arrival = datetime.strptime(arrival, '%Y-%m-%d').date(), - no_adults = no_adults, - no_children = no_children, - no_free_of_charge = no_free_of_charge, - cost = no_adults*park.adult_price + no_children*park.child_price - ) - if not park_booking: - raise ValidationError('Must have at least one person visiting the park') - - return booking - -""" -TEST 1: -1. create 1 Organisation: - a. monthly_invoicing_allowed = True - b. monthly_invoicing_period = 5 (create invoice 0 days from 1st of the month) - c. monthly_payment_due = 20 (set settlement_date to 20 days after invoice created) -2. For Org, create 2 or 3 bookings, add parks --> pre-date booking to last month -3. run monthly invoice script: - a. confirm monthly_script SKIPS invoice creation, if executed before the invoicing date (1st of the month + monthly_invoicing_period(5) --> before 6th day of the month) - b. confirm monthly_script creates invoice, if executed after the invoicing date (1st of the month + monthly_invoicing_period(5) --> on or after 6th of the month) - b. confirm the created invoice has the correct payment date printed on the PDF (invoice_created + monthly_invoicing_period(20) --> 26th of the month) -4. confirm cannot re-create invoice again for this booking - -TEST 2: -1. create 2 Organisations (with different invoicing periods): - ORG_1: - a. monthly_invoicing_allowed = True - b. monthly_invoicing_period = 3 (create invoice 3 days from 1st of the month) - c. monthly_payment_due = 20 (set settlement_date to 20 days after invoice created) - ORG_2: - a. monthly_invoicing_allowed = True - b. monthly_invoicing_period = 5 (create invoice 5 days from 1st of the month) - c. monthly_payment_due = 20 (set settlement_date to 20 days after invoice created) -2. For Org_1, create 2 or 3 bookings, add parks --> pre-date booking to last month -3. For Org_3, create 2 or 3 bookings, add parks --> pre-date booking to last month -4. run monthly invoice script: - a. confirm monthly_script SKIPS invoice creation (for both Orgs), if executed before the invoicing date (1st of the month + monthly_invoicing_period(3) --> before 4th day of the month) - b. confirm monthly_script creates invoice for Org_1 only, if executed after the Org_1 invoicing date (1st of the month + monthly_invoicing_period(3) --> on or after 4th of the month) - c. confirm monthly_script creates invoice for Org_2 only, if executed after the Org_2 invoicing date (1st of the month + monthly_invoicing_period(5) --> on or after 6th of the month) - d. confirm the Org_1 invoice has the correct payment date printed on the PDF (invoice_created_date + monthly_invoicing_period(20) --> 24h of the month) - e. confirm the Org_2 invoice has the correct payment date printed on the PDF (invoice_created_date + monthly_invoicing_period(20) --> 26 of the month) -4. confirm cannot re-create invoices again for these booking - - - -""" -def create_monthly_invoice(user, offset_months=-1): - bookings = Booking.objects.filter( - invoices__isnull=True, - booking_type=Booking.BOOKING_TYPE_MONTHLY_INVOICING, - created__month=(timezone.now() + relativedelta(months=offset_months)).month - ) - - failed_bookings = [] - for booking in bookings: - with transaction.atomic(): - if is_invoicing_period(booking) and is_monthly_invoicing_allowed(booking): - try: - logger.info('Creating monthly invoice for booking {}'.format(booking.admission_number)) - order = create_invoice(booking, payment_method='monthly_invoicing') - invoice = Invoice.objects.get(order_number=order.number) - #invoice.settlement_date = calc_payment_due_date(booking, invoice.created + relativedelta(months=1)) - #invoice.save() - - deferred_payment_date = calc_payment_due_date(booking, invoice.created + relativedelta(months=1)) - book_inv = BookingInvoice.objects.create(booking=booking, invoice_reference=invoice.reference, payment_method=invoice.payment_method, deferred_payment_date=deferred_payment_date) - - #send_monthly_invoice_tclass_email_notification(user, booking, invoice, recipients=[booking.proposal.applicant_email]) - #ProposalUserAction.log_action(booking.proposal,ProposalUserAction.ACTION_SEND_MONTHLY_INVOICE.format(booking.proposal.id),booking.proposal.applicant_email) - except Exception, e: - logger.error('Failed to create monthly invoice for booking_id {}'.format(booking.id)) - logger.error('{}'.format(e)) - failed_bookings.append(booking.id) - - return failed_bookings - -def create_bpay_invoice(user, booking): - - failed_bookings = [] - with transaction.atomic(): - if booking.booking_type == Booking.BOOKING_TYPE_INTERNET and booking.proposal.org_applicant and booking.proposal.org_applicant.bpay_allowed: - try: - now = timezone.now().date() - dt = date(now.year, now.month, 1) + relativedelta(months=1) - logger.info('Creating BPAY invoice for booking {}'.format(booking.admission_number)) - order = create_invoice(booking, payment_method='bpay') - invoice = Invoice.objects.get(order_number=order.number) - #invoice.settlement_date = calc_payment_due_date(booking, dt) - relativedelta(days=1) - #invoice.save() - - deferred_payment_date = calc_payment_due_date(booking, dt) - relativedelta(days=1) - book_inv = BookingInvoice.objects.create(booking=booking, invoice_reference=invoice.reference, payment_method=invoice.payment_method, deferred_payment_date=deferred_payment_date) - - #send_monthly_invoice_tclass_email_notification(user, booking, invoice, recipients=[booking.proposal.applicant_email]) - #ProposalUserAction.log_action(booking.proposal,ProposalUserAction.ACTION_SEND_MONTHLY_INVOICE.format(booking.proposal.id),booking.proposal.applicant_email) - except Exception, e: - logger.error('Failed to create monthly invoice for booking_id {}'.format(booking.id)) - logger.error('{}'.format(e)) - failed_bookings.append(booking.id) - - return failed_bookings - -def create_other_invoice(user, booking): - - failed_bookings = [] - with transaction.atomic(): - #if booking.booking_type == Booking.BOOKING_TYPE_RECEPTION and booking.proposal.org_applicant.other_allowed: - if booking.booking_type == Booking.BOOKING_TYPE_RECEPTION: - try: - now = timezone.now().date() - dt = date(now.year, now.month, 1) + relativedelta(months=1) - logger.info('Creating OTHER (CASH/CHEQUE) invoice for booking {}'.format(booking.admission_number)) - order = create_invoice(booking, payment_method='other') - invoice = Invoice.objects.get(order_number=order.number) - - deferred_payment_date = calc_payment_due_date(booking, dt) - relativedelta(days=1) - book_inv = BookingInvoice.objects.create(booking=booking, invoice_reference=invoice.reference, payment_method=invoice.payment_method, deferred_payment_date=deferred_payment_date) - - #send_monthly_invoice_tclass_email_notification(user, booking, invoice, recipients=[booking.proposal.applicant_email]) - #ProposalUserAction.log_action(booking.proposal,ProposalUserAction.ACTION_SEND_MONTHLY_INVOICE.format(booking.proposal.id),booking.proposal.applicant_email) - except Exception, e: - logger.error('Failed to create OTHER invoice for booking_id {}'.format(booking.id)) - logger.error('{}'.format(e)) - failed_bookings.append(booking.id) - - return failed_bookings - -def calc_payment_due_date(booking, _date): - org_applicant = booking.proposal.org_applicant - if isinstance(org_applicant, Organisation): - return calc_monthly_invoicing_date(_date, org_applicant.monthly_invoicing_period) + relativedelta(days=org_applicant.monthly_payment_due_period) - return None - -def calc_monthly_invoicing_date(_date, offset_days): - return _date + relativedelta(days=offset_days) - -def is_invoicing_period(booking): - org_applicant = booking.proposal.org_applicant - if isinstance(org_applicant, Organisation): - return timezone.now().day >= org_applicant.monthly_invoicing_period - return False - -def is_monthly_invoicing_allowed(booking): - org_applicant = booking.proposal.org_applicant - if isinstance(org_applicant, Organisation): - return booking.booking_type == Booking.BOOKING_TYPE_MONTHLY_INVOICING and org_applicant and org_applicant.monthly_invoicing_allowed - return False - - -def get_session_booking(session): - if 'cols_booking' in session: - booking_id = session['cols_booking'] - else: - raise Exception('Booking not in Session') - - try: - return Booking.objects.get(id=booking_id) - except Booking.DoesNotExist: - raise Exception('Booking not found for booking_id {}'.format(booking_id)) - - -def set_session_booking(session, booking): - session['cols_booking'] = booking.id - session.modified = True - -def delete_session_booking(session): - if 'cols_booking' in session: - del session['cols_booking'] - session.modified = True - -def get_session_application_invoice(session): - """ Application Fee session ID """ - if 'cols_app_invoice' in session: - application_fee_id = session['cols_app_invoice'] - else: - raise Exception('Application not in Session') - - try: - #return Invoice.objects.get(id=application_invoice_id) - #return Proposal.objects.get(id=proposal_id) - return ApplicationFee.objects.get(id=application_fee_id) - except Invoice.DoesNotExist: - raise Exception('Application not found for application {}'.format(application_fee_id)) - -def set_session_application_invoice(session, application_fee): - """ Application Fee session ID """ - session['cols_app_invoice'] = application_fee.id - session.modified = True - -def delete_session_application_invoice(session): - """ Application Fee session ID """ - if 'cols_app_invoice' in session: - del session['cols_app_invoice'] - session.modified = True - -def create_fee_lines(proposal, invoice_text=None, vouchers=[], internal=False): - """ Create the ledger lines - line item for application fee sent to payment system """ - - now = datetime.now().strftime('%Y-%m-%d %H:%M') - application_price = proposal.application_type.application_fee - licence_price = proposal.licence_fee_amount - line_items = [ - { 'ledger_description': 'Application Fee - {} - {}'.format(now, proposal.lodgement_number), - 'oracle_code': proposal.application_type.oracle_code_application, - 'price_incl_tax': application_price, - 'price_excl_tax': application_price if proposal.application_type.is_gst_exempt else calculate_excl_gst(application_price), - 'quantity': 1, - }, - { 'ledger_description': 'Licence Charge {} - {} - {}'.format(proposal.other_details.get_preferred_licence_period_display(), now, proposal.lodgement_number), - 'oracle_code': proposal.application_type.oracle_code_licence, - 'price_incl_tax': licence_price, - 'price_excl_tax': licence_price if proposal.application_type.is_gst_exempt else calculate_excl_gst(licence_price), - 'quantity': 1, - } - ] - logger.info('{}'.format(line_items)) - return line_items - -def create_lines(request, invoice_text=None, vouchers=[], internal=False): - """ Create the ledger lines - line items for invoice sent to payment system """ - - def add_line_item(park, arrival, age_group, price, no_persons): - #price = Decimal(price) - price = round(float(price), 2) - if no_persons > 0: - return { - 'ledger_description': '{} - {} - {}'.format(park.name, arrival, age_group), - 'oracle_code': park.oracle_code.encode('utf-8'), - 'price_incl_tax': price, - 'price_excl_tax': price if park.is_gst_exempt else round(float(calculate_excl_gst(price)), 2), - 'quantity': no_persons, - } - return None - - lines = [] - tbody = json.loads(request.POST['payment'])['tbody'] - for row in tbody: - park_id = row[0]['value'] - arrival = row[1] - no_adults = int(row[2]) if row[2] else 0 - no_children = int(row[3]) if row[3] else 0 - no_free_of_charge = int(row[4]) if row[4] else 0 - park= Park.objects.get(id=park_id) - - if no_adults > 0: - lines.append(add_line_item(park, arrival, 'Adult', price=park.adult_price, no_persons=no_adults)) - - if no_children > 0: - lines.append(add_line_item(park, arrival, 'Child', price=park.child_price, no_persons=no_children)) - - if no_free_of_charge > 0: - lines.append(add_line_item(park, arrival, 'Free', price=0.0, no_persons=no_free_of_charge)) - - return lines - -def checkout(request, proposal, lines, return_url_ns='public_booking_success', return_preload_url_ns='public_booking_success', invoice_text=None, vouchers=[], proxy=False): - basket_params = { - 'products': lines, - 'vouchers': vouchers, - 'system': settings.PAYMENT_SYSTEM_ID, - 'custom_basket': True, - } - - basket, basket_hash = create_basket_session(request, basket_params) - #fallback_url = request.build_absolute_uri('/') - checkout_params = { - 'system': settings.PAYMENT_SYSTEM_ID, - 'fallback_url': request.build_absolute_uri('/'), # 'http://mooring-ria-jm.dbca.wa.gov.au/' - 'return_url': request.build_absolute_uri(reverse(return_url_ns)), # 'http://mooring-ria-jm.dbca.wa.gov.au/success/' - 'return_preload_url': request.build_absolute_uri(reverse(return_url_ns)), # 'http://mooring-ria-jm.dbca.wa.gov.au/success/' - #'fallback_url': fallback_url, - #'return_url': fallback_url, - #'return_preload_url': fallback_url, - 'force_redirect': True, - #'proxy': proxy, - 'invoice_text': invoice_text, # 'Reservation for Jawaid Mushtaq from 2019-05-17 to 2019-05-19 at RIA 005' - } -# if not internal: -# checkout_params['check_url'] = request.build_absolute_uri('/api/booking/{}/booking_checkout_status.json'.format(booking.id)) - #if internal or request.user.is_anonymous(): - if proxy or request.user.is_anonymous(): - #checkout_params['basket_owner'] = booking.customer.id - checkout_params['basket_owner'] = proposal.submitter_id - - - create_checkout_session(request, checkout_params) - -# if internal: -# response = place_order_submission(request) -# else: - response = HttpResponseRedirect(reverse('checkout:index')) - # inject the current basket into the redirect response cookies - # or else, anonymous users will be directionless - response.set_cookie( - settings.OSCAR_BASKET_COOKIE_OPEN, basket_hash, - max_age=settings.OSCAR_BASKET_COOKIE_LIFETIME, - secure=settings.OSCAR_BASKET_COOKIE_SECURE, httponly=True - ) - -# if booking.cost_total < 0: -# response = HttpResponseRedirect('/refund-payment') -# response.set_cookie( -# settings.OSCAR_BASKET_COOKIE_OPEN, basket_hash, -# max_age=settings.OSCAR_BASKET_COOKIE_LIFETIME, -# secure=settings.OSCAR_BASKET_COOKIE_SECURE, httponly=True -# ) -# -# # Zero booking costs -# if booking.cost_total < 1 and booking.cost_total > -1: -# response = HttpResponseRedirect('/no-payment') -# response.set_cookie( -# settings.OSCAR_BASKET_COOKIE_OPEN, basket_hash, -# max_age=settings.OSCAR_BASKET_COOKIE_LIFETIME, -# secure=settings.OSCAR_BASKET_COOKIE_SECURE, httponly=True -# ) - - return response - - -def oracle_integration(date,override): - system = '0557' - oracle_codes = oracle_parser(date, system, 'Commercial Operator Licensing', override=override) - - -def test_create_invoice(payment_method='bpay'): - """ - This will create and invoice and order from a basket bypassing the session - and payment bpoint code constraints. - - To test: - from ledger.payments.invoice.utils import test_create_invoice - - - from ledger.checkout.utils import createCustomBasket - from ledger.payments.invoice.utils import CreateInvoiceBasket - from decimal import Decimal - - products = [{u'oracle_code': u'ABC123 GST', u'price_incl_tax': Decimal('10.00'), u'price_excl_tax': Decimal('9.090909090909'), u'ledger_description': u'Booking Date 2019-09-24: Neale Junction Nature Reserve - 2019-09-24 - Adult', u'quantity': 1}] - or - products = Booking.objects.last().as_line_items - - user = EmailUser.objects.get(email__icontains='walter.genuit@dbca') - payment_method = 'bpay' (or 'monthly_invoicing') - - basket = createCustomBasket(products, user, 'S557', bpay_allowed=True, monthly_invoicing_allowed=True) - order = CreateInvoiceBasket(payment_method='bpay', system='0557').create_invoice_and_order(basket, 0, None, None, user=user, invoice_text='CIB7') - - Invoice.objects.get(order_number=order.number) - - - To view: - http://localhost:8499/ledger/payments/invoice/05572188633 - - """ - from ledger.checkout.utils import createCustomBasket - from ledger.payments.invoice.utils import CreateInvoiceBasket - from ledger.accounts.models import EmailUser - from decimal import Decimal - - products = [{ - 'oracle_code': 'ABC123 GST', - 'price_incl_tax': Decimal('10.00'), - 'price_excl_tax': Decimal('9.090909090909'), - 'ledger_description': 'Booking Date 2019-09-24: Neale Junction Nature Reserve - 2019-09-24 - Adult', - 'quantity': 1 - }] - #products = Booking.objects.last().as_line_items - - user = EmailUser.objects.get(email='jawaid.mushtaq@dbca.wa.gov.au') - #payment_method = 'bpay' - payment_method = 'monthly_invoicing' - - basket = createCustomBasket(products, user, 'S557') - order = CreateInvoiceBasket(payment_method=payment_method, system='0557').create_invoice_and_order(basket, 0, None, None, user=user, invoice_text='CIB7') - print 'Created Order: {}'.format(order.number) - print 'Created Invoice: {}'.format(Invoice.objects.get(order_number=order.number)) - - return order - -def create_invoice(booking, payment_method='bpay'): - """ - This will create and invoice and order from a basket bypassing the session - and payment bpoint code constraints. - """ - from ledger.checkout.utils import createCustomBasket - from ledger.payments.invoice.utils import CreateInvoiceBasket - from ledger.accounts.models import EmailUser - from decimal import Decimal - - products = Booking.objects.last().as_line_items - user = EmailUser.objects.get(email=booking.proposal.applicant_email) - - if payment_method=='monthly_invoicing': - invoice_text = 'Monthly Payment Invoice' - elif payment_method=='bpay': - invoice_text = 'BPAY Payment Invoice' - else: - invoice_text = 'Payment Invoice' - - basket = createCustomBasket(products, user, settings.PAYMENT_SYSTEM_ID) - order = CreateInvoiceBasket(payment_method=payment_method, system=settings.PAYMENT_SYSTEM_PREFIX).create_invoice_and_order(basket, 0, None, None, user=user, invoice_text=invoice_text) - - return order - - diff --git a/commercialoperator/components/bookings/views.py b/commercialoperator/components/bookings/views.py deleted file mode 100644 index 68bf5307fc..0000000000 --- a/commercialoperator/components/bookings/views.py +++ /dev/null @@ -1,483 +0,0 @@ -from django.http import Http404, HttpResponse, HttpResponseRedirect, JsonResponse -from django.core.urlresolvers import reverse -from django.contrib.auth.decorators import login_required -from django.shortcuts import render, get_object_or_404, redirect -from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView, FormView -from django.views.generic.base import View, TemplateView -from django.conf import settings -from django.contrib.auth.mixins import UserPassesTestMixin, LoginRequiredMixin -from django.views.decorators.csrf import csrf_protect -from django.core.exceptions import ValidationError -from django.db import transaction - -from datetime import datetime, timedelta, date -from django.utils import timezone -from dateutil.relativedelta import relativedelta - -from commercialoperator.components.proposals.models import Proposal -from commercialoperator.components.compliances.models import Compliance -from commercialoperator.components.main.models import Park -from commercialoperator.components.organisations.models import Organisation -from commercialoperator.components.bookings.context_processors import commercialoperator_url, template_context -from commercialoperator.components.bookings.invoice_pdf import create_invoice_pdf_bytes -from commercialoperator.components.bookings.confirmation_pdf import create_confirmation_pdf_bytes -from commercialoperator.components.bookings.monthly_confirmation_pdf import create_monthly_confirmation_pdf_bytes -from commercialoperator.components.bookings.email import ( - send_invoice_tclass_email_notification, - send_confirmation_tclass_email_notification, - send_application_fee_invoice_tclass_email_notification, - send_application_fee_confirmation_tclass_email_notification, -) -from commercialoperator.components.bookings.utils import ( - create_booking, - get_session_booking, - set_session_booking, - delete_session_booking, - create_lines, - checkout, - create_fee_lines, - get_session_application_invoice, - set_session_application_invoice, - delete_session_application_invoice, - calc_payment_due_date, - create_bpay_invoice, - create_other_invoice, -) - -from commercialoperator.components.proposals.serializers import ProposalSerializer - -from ledger.checkout.utils import create_basket_session, create_checkout_session, place_order_submission, get_cookie_basket -from ledger.payments.utils import oracle_parser_on_invoice,update_payments -import json -from decimal import Decimal - -from commercialoperator.components.bookings.models import Booking, ParkBooking, BookingInvoice, ApplicationFee, ApplicationFeeInvoice -from ledger.payments.models import Invoice -from ledger.basket.models import Basket -from ledger.payments.mixins import InvoiceOwnerMixin -from oscar.apps.order.models import Order - -import logging -logger = logging.getLogger('payment_checkout') - - -class ApplicationFeeView(TemplateView): - template_name = 'commercialoperator/booking/success.html' - - def get_object(self): - return get_object_or_404(Proposal, id=self.kwargs['proposal_pk']) - - def post(self, request, *args, **kwargs): - - #proposal_id = int(kwargs['proposal_pk']) - #proposal = Proposal.objects.get(id=proposal_id) - - proposal = self.get_object() - application_fee = ApplicationFee.objects.create(proposal=proposal, created_by=request.user, payment_type=ApplicationFee.PAYMENT_TYPE_TEMPORARY) - - try: - with transaction.atomic(): - set_session_application_invoice(request.session, application_fee) - lines = create_fee_lines(proposal) - checkout_response = checkout( - request, - proposal, - lines, - return_url_ns='fee_success', - return_preload_url_ns='fee_success', - invoice_text='Application Fee' - ) - - logger.info('{} built payment line item {} for Application Fee and handing over to payment gateway'.format('User {} with id {}'.format(proposal.submitter.get_full_name(),proposal.submitter.id), proposal.id)) - return checkout_response - - except Exception, e: - logger.error('Error Creating Application Fee: {}'.format(e)) - if application_fee: - application_fee.delete() - raise - - -class DeferredInvoicingPreviewView(TemplateView): - template_name = 'commercialoperator/booking/preview.html' - - def post(self, request, *args, **kwargs): - - payment_method = self.request.GET.get('method') - context = template_context(self.request) - proposal_id = int(kwargs['proposal_pk']) - proposal = Proposal.objects.get(id=proposal_id) - try: - recipient = proposal.applicant.email - submitter = proposal.applicant - except: - recipient = proposal.submitter.email - submitter = proposal.submitter - - #if isinstance(proposal.org_applicant, Organisation) and (proposal.org_applicant.monthly_invoicing_allowed or proposal.org_applicant.bpay_allowed or proposal.org_applicant.other_allowed): - if isinstance(proposal.org_applicant, Organisation) and (proposal.org_applicant.monthly_invoicing_allowed or proposal.org_applicant.bpay_allowed): - try: - lines = create_lines(request) - logger.info('{} Show Park Bookings Preview for BPAY/Other/monthly invoicing'.format('User {} with id {}'.format(proposal.submitter.get_full_name(),proposal.submitter.id), proposal.id)) - context.update({ - 'lines': lines, - 'line_details': request.POST['payment'], - 'proposal_id': proposal_id, - 'submitter': submitter, - 'payment_method': payment_method, - }) - return render(request, self.template_name, context) - - - except Exception, e: - logger.error('Error creating booking preview: {}'.format(e)) - else: - logger.error('Error creating booking preview: {}'.format(e)) - raise - - -class DeferredInvoicingView(TemplateView): - #template_name = 'mooring/booking/make_booking.html' - template_name = 'commercialoperator/booking/success.html' - #template_name = 'commercialoperator/booking/preview.html' - - def post(self, request, *args, **kwargs): - - payment_method = self.request.POST.get('method') - context = template_context(self.request) - proposal_id = int(kwargs['proposal_pk']) - proposal = Proposal.objects.get(id=proposal_id) - try: - recipient = proposal.applicant.email - submitter = proposal.applicant - except: - recipient = proposal.submitter.email - submitter = proposal.submitter - - if isinstance(proposal.org_applicant, Organisation): - try: - if proposal.org_applicant.bpay_allowed and payment_method=='bpay': - booking_type = Booking.BOOKING_TYPE_INTERNET - elif proposal.org_applicant.monthly_invoicing_allowed and payment_method=='monthly_invoicing': - booking_type = Booking.BOOKING_TYPE_MONTHLY_INVOICING - #elif proposal.org_applicant.other_allowed and payment_method=='other': - else: - booking_type = Booking.BOOKING_TYPE_RECEPTION - - booking = create_booking(request, proposal, booking_type=booking_type) - invoice_reference = None - if booking and payment_method=='bpay': - # BPAY/OTHER invoice are created immediately. Monthly invoices are created later by Cron - ret = create_bpay_invoice(submitter, booking) - invoice_reference = booking.invoice.reference - - if booking and payment_method=='other': - # BPAY/Other invoice are created immediately. Monthly invoices are created later by Cron - ret = create_other_invoice(submitter, booking) - invoice_reference = booking.invoice.reference - - logger.info('{} Created Park Bookings with payment method {} for Proposal ID {}'.format('User {} with id {}'.format(proposal.submitter.get_full_name(),proposal.submitter.id), payment_method, proposal.id)) - #send_monthly_invoicing_confirmation_tclass_email_notification(request, booking, invoice, recipients=[recipient]) - context.update({ - 'booking': booking, - 'booking_id': booking.id, - 'submitter': submitter, - 'monthly_invoicing': True if payment_method=='monthly_invoicing' else False, - 'invoice_reference': invoice_reference - }) - if payment_method=='other': - return HttpResponseRedirect(reverse('payments:invoice-payment') + '?invoice={}'.format(invoice_reference)) - else: - return render(request, self.template_name, context) - - - except Exception, e: - logger.error('Error Creating booking: {}'.format(e)) - if booking: - booking.delete() - raise - else: - logger.error('Error Creating booking: {}'.format(e)) - raise - - -class MakePaymentView(TemplateView): - #template_name = 'mooring/booking/make_booking.html' - template_name = 'commercialoperator/booking/success.html' - - def post(self, request, *args, **kwargs): - - proposal_id = int(kwargs['proposal_pk']) - proposal = Proposal.objects.get(id=proposal_id) - - try: - booking = create_booking(request, proposal, booking_type=Booking.BOOKING_TYPE_TEMPORARY) - with transaction.atomic(): - set_session_booking(request.session,booking) - #lines = create_lines(request) - checkout_response = checkout( - request, - proposal, - #lines, - booking.as_line_items, - return_url_ns='public_booking_success', - return_preload_url_ns='public_booking_success', - invoice_text='Payment Invoice', - ) - - logger.info('{} built payment line items {} for Park Bookings and handing over to payment gateway'.format('User {} with id {}'.format(proposal.submitter.get_full_name(),proposal.submitter.id), proposal.id)) - return checkout_response - - except Exception, e: - logger.error('Error Creating booking: {}'.format(e)) - if booking: - booking.delete() - raise - - -from commercialoperator.components.proposals.utils import proposal_submit -class ApplicationFeeSuccessView(TemplateView): - template_name = 'commercialoperator/booking/success_fee.html' - - def get(self, request, *args, **kwargs): - print (" APPLICATION FEE SUCCESS ") -# for ss in request.session.keys(): -# print (ss) -# print (request.session[ss]) - - proposal = None - submitter = None - invoice = None - try: - context = template_context(self.request) - basket = None - application_fee = get_session_application_invoice(request.session) - proposal = application_fee.proposal - - try: - recipient = proposal.applicant.email - submitter = proposal.applicant - except: - recipient = proposal.submitter.email - submitter = proposal.submitter - - if self.request.user.is_authenticated(): - basket = Basket.objects.filter(status='Submitted', owner=request.user).order_by('-id')[:1] - else: - basket = Basket.objects.filter(status='Submitted', owner=booking.proposal.submitter).order_by('-id')[:1] - - order = Order.objects.get(basket=basket[0]) - invoice = Invoice.objects.get(order_number=order.number) - invoice_ref = invoice.reference - fee_inv, created = ApplicationFeeInvoice.objects.get_or_create(application_fee=application_fee, invoice_reference=invoice_ref) - - if application_fee.payment_type == ApplicationFee.PAYMENT_TYPE_TEMPORARY: - try: - inv = Invoice.objects.get(reference=invoice_ref) - order = Order.objects.get(number=inv.order_number) - order.user = submitter - order.save() - except Invoice.DoesNotExist: - logger.error('{} tried paying an application fee with an incorrect invoice'.format('User {} with id {}'.format(proposal.submitter.get_full_name(), proposal.submitter.id) if proposal.submitter else 'An anonymous user')) - return redirect('external-proposal-detail', args=(proposal.id,)) - if inv.system not in ['0557']: - logger.error('{} tried paying an application fee with an invoice from another system with reference number {}'.format('User {} with id {}'.format(proposal.submitter.get_full_name(), proposal.submitter.id) if proposal.submitter else 'An anonymous user',inv.reference)) - return redirect('external-proposal-detail', args=(proposal.id,)) - - if fee_inv: - #application_fee.payment_type = 1 # internet booking - application_fee.payment_type = ApplicationFee.PAYMENT_TYPE_INTERNET - application_fee.expiry_time = None - update_payments(invoice_ref) - - proposal = proposal_submit(proposal, request) - if proposal and (invoice.payment_status == 'paid' or invoice.payment_status == 'over_paid'): - proposal.fee_invoice_reference = invoice_ref - proposal.save() - else: - logger.error('Invoice payment status is {}'.format(invoice.payment_status)) - raise - - application_fee.save() - request.session['cols_last_app_invoice'] = application_fee.id - delete_session_application_invoice(request.session) - - send_application_fee_invoice_tclass_email_notification(request, proposal, invoice, recipients=[recipient]) - send_application_fee_confirmation_tclass_email_notification(request, application_fee, invoice, recipients=[recipient]) - - context = { - 'proposal': proposal, - 'submitter': submitter, - 'fee_invoice': invoice - } - return render(request, self.template_name, context) - - except Exception as e: - if ('cols_last_app_invoice' in request.session) and ApplicationFee.objects.filter(id=request.session['cols_last_app_invoice']).exists(): - application_fee = ApplicationFee.objects.get(id=request.session['cols_last_app_invoice']) - proposal = application_fee.proposal - - try: - recipient = proposal.applicant.email - submitter = proposal.applicant - except: - recipient = proposal.submitter.email - submitter = proposal.submitter - - if ApplicationFeeInvoice.objects.filter(application_fee=application_fee).count() > 0: - afi = ApplicationFeeInvoice.objects.filter(application_fee=application_fee) - invoice = afi[0] - else: - return redirect('home') - - context = { - 'proposal': proposal, - 'submitter': submitter, - 'fee_invoice': invoice - } - return render(request, self.template_name, context) - -class BookingSuccessView(TemplateView): - template_name = 'commercialoperator/booking/success.html' - - def get(self, request, *args, **kwargs): - print (" BOOKING SUCCESS ") - - booking = None - submitter = None - invoice = None - try: - context = template_context(self.request) - basket = None - booking = get_session_booking(request.session) - proposal = booking.proposal - - try: - recipient = proposal.applicant.email - submitter = proposal.applicant - except: - recipient = proposal.submitter.email - submitter = proposal.submitter - - if self.request.user.is_authenticated(): - basket = Basket.objects.filter(status='Submitted', owner=request.user).order_by('-id')[:1] - else: - basket = Basket.objects.filter(status='Submitted', owner=booking.proposal.submitter).order_by('-id')[:1] - - order = Order.objects.get(basket=basket[0]) - invoice = Invoice.objects.get(order_number=order.number) - invoice_ref = invoice.reference - book_inv, created = BookingInvoice.objects.get_or_create(booking=booking, invoice_reference=invoice_ref, payment_method=invoice.payment_method) - - if booking.booking_type == Booking.BOOKING_TYPE_TEMPORARY: - try: - inv = Invoice.objects.get(reference=invoice_ref) - #if (inv.payment_method == Invoice.PAYMENT_METHOD_BPAY): - # # will return 1st of the next month + monthly_payment_due_period (days) e.g 20th of next month - # now = timezone.now().date() - # dt = date(now.year, now.month, 1) + relativedelta(months=1) - # inv.settlement_date = calc_payment_due_date(booking, dt) - relativedelta(days=1) - # inv.save() - - order = Order.objects.get(number=inv.order_number) - order.user = submitter - order.save() - except Invoice.DoesNotExist: - logger.error('{} tried paying an admission fee with an incorrect invoice'.format('User {} with id {}'.format(proposal.submitter.get_full_name(), proposal.submitter.id) if proposal.submitter else 'An anonymous user')) - return redirect('external-proposal-detail', args=(proposal.id,)) - if inv.system not in ['0557']: - logger.error('{} tried paying an admission fee with an invoice from another system with reference number {}'.format('User {} with id {}'.format(proposal.submitter.get_full_name(), proposal.submitter.id) if proposal.submitter else 'An anonymous user',inv.reference)) - return redirect('external-proposal-detail', args=(proposal.id,)) - - if book_inv: - booking.booking_type = Booking.BOOKING_TYPE_INTERNET - booking.expiry_time = None - #booking.set_admission_number() - update_payments(invoice_ref) - - if not (invoice.payment_status == 'paid' or invoice.payment_status == 'over_paid') and invoice.payment_method == Invoice.PAYMENT_METHOD_CC: - logger.error('Payment Method={} - Admission Fee Invoice payment status is {}'.format(invoice.get_payment_method_display(), invoice.payment_status)) - raise - - booking.save() - request.session['cols_last_booking'] = booking.id - delete_session_booking(request.session) - - send_invoice_tclass_email_notification(request, booking, invoice, recipients=[recipient]) - send_confirmation_tclass_email_notification(request, booking, invoice, recipients=[recipient]) - - context.update({ - 'booking_id': booking.id, - 'submitter': submitter, - 'invoice_reference': invoice.reference - }) - return render(request, self.template_name, context) - - except Exception as e: - #logger.error('{}'.format(e)) - if ('cols_last_booking' in request.session) and Booking.objects.filter(id=request.session['cols_last_booking']).exists(): - booking = Booking.objects.get(id=request.session['cols_last_booking']) - proposal = booking.proposal - - try: - recipient = proposal.applicant.email - submitter = proposal.applicant - except: - recipient = proposal.submitter.email - submitter = proposal.submitter - - if BookingInvoice.objects.filter(booking=booking).count() > 0: - bi = BookingInvoice.objects.filter(booking=booking) - invoice = bi[0] - else: - return redirect('home') - - context.update({ - 'booking_id': booking.id, - 'submitter': submitter, - 'invoice_reference': invoice.invoice_reference - }) - return render(request, self.template_name, context) - - -class InvoicePDFView(InvoiceOwnerMixin,View): - def get(self, request, *args, **kwargs): - invoice = get_object_or_404(Invoice, reference=self.kwargs['reference']) - bi=BookingInvoice.objects.filter(invoice_reference=invoice.reference).last() - if bi: - proposal = bi.booking.proposal - else: - proposal = Proposal.objects.get(fee_invoice_reference=invoice.reference) - - response = HttpResponse(content_type='application/pdf') - response.write(create_invoice_pdf_bytes('invoice.pdf', invoice, proposal)) - return response - - def get_object(self): - invoice = get_object_or_404(Invoice, reference=self.kwargs['reference']) - return invoice - - -class ConfirmationPDFView(InvoiceOwnerMixin,View): - def get(self, request, *args, **kwargs): - invoice = get_object_or_404(Invoice, reference=self.kwargs['reference']) - bi=BookingInvoice.objects.filter(invoice_reference=invoice.reference).last() - - # GST ignored here because GST amount is not included on the confirmation PDF - response = HttpResponse(content_type='application/pdf') - response.write(create_confirmation_pdf_bytes('confirmation.pdf',invoice, bi.booking)) - return response - - def get_object(self): - invoice = get_object_or_404(Invoice, reference=self.kwargs['reference']) - return invoice - - -class MonthlyConfirmationPDFView(View): - def get(self, request, *args, **kwargs): - booking = get_object_or_404(Booking, id=self.kwargs['id']) - - response = HttpResponse(content_type='application/pdf') - response.write(create_monthly_confirmation_pdf_bytes('monthly_confirmation.pdf', booking)) - return response - diff --git a/commercialoperator/components/compliances/__init__.py b/commercialoperator/components/compliances/__init__.py deleted file mode 100755 index e69de29bb2..0000000000 diff --git a/commercialoperator/components/compliances/admin.py b/commercialoperator/components/compliances/admin.py deleted file mode 100755 index add230a530..0000000000 --- a/commercialoperator/components/compliances/admin.py +++ /dev/null @@ -1,16 +0,0 @@ -from django.contrib import admin -from commercialoperator.components.compliances import models -# Register your models here. - -#@admin.register(models.ComplianceAmendmentInfo) -#class ComplianceAmendmentInfoAdmin(admin.ModelAdmin): -# list_display = ['status'] - -#@admin.register(models.ComplianceAmendmentStatus) -#class ComplianceAmendmentStatusAdmin(admin.ModelAdmin): -# list_display = ['status'] - -@admin.register(models.ComplianceAmendmentReason) -class ComplianceAmendmentReasonAdmin(admin.ModelAdmin): - list_display = ['reason'] - diff --git a/commercialoperator/components/compliances/api.py b/commercialoperator/components/compliances/api.py deleted file mode 100755 index 7757a60ca6..0000000000 --- a/commercialoperator/components/compliances/api.py +++ /dev/null @@ -1,434 +0,0 @@ - -import traceback -import os -import datetime -import base64 -import geojson -from six.moves.urllib.parse import urlparse -from wsgiref.util import FileWrapper -from django.db.models import Q, Min -from django.db import transaction -from django.http import HttpResponse -from django.core.files.base import ContentFile -from django.core.exceptions import ValidationError -from django.conf import settings -from django.contrib import messages -from django.views.decorators.http import require_http_methods -from django.views.decorators.csrf import csrf_exempt -from django.utils import timezone -from rest_framework import viewsets, serializers, status, generics, views -from rest_framework.decorators import detail_route, list_route, renderer_classes -from rest_framework.response import Response -from rest_framework.renderers import JSONRenderer -from rest_framework.permissions import IsAuthenticated, AllowAny, IsAdminUser, BasePermission -from rest_framework.pagination import PageNumberPagination -from datetime import datetime, timedelta -from collections import OrderedDict -from django.core.cache import cache -from ledger.accounts.models import EmailUser, Address -from ledger.address.models import Country -from datetime import datetime, timedelta, date -from django.urls import reverse -from django.shortcuts import render, redirect, get_object_or_404 -from commercialoperator.components.compliances.models import ( - Compliance, - ComplianceAmendmentRequest, - ComplianceAmendmentReason -) -from commercialoperator.components.compliances.serializers import ( - ComplianceSerializer, - InternalComplianceSerializer, - SaveComplianceSerializer, - ComplianceActionSerializer, - ComplianceCommsSerializer, - ComplianceAmendmentRequestSerializer, - CompAmendmentRequestDisplaySerializer -) -from commercialoperator.helpers import is_customer, is_internal -from rest_framework_datatables.pagination import DatatablesPageNumberPagination -from commercialoperator.components.proposals.api import ProposalFilterBackend, ProposalRenderer - -class CompliancePaginatedViewSet(viewsets.ModelViewSet): - filter_backends = (ProposalFilterBackend,) - pagination_class = DatatablesPageNumberPagination - renderer_classes = (ProposalRenderer,) - page_size = 10 - queryset = Compliance.objects.none() - serializer_class = ComplianceSerializer - - def get_queryset(self): - if is_internal(self.request): - #return Compliance.objects.all() - return Compliance.objects.all().exclude(processing_status='discarded') - elif is_customer(self.request): - user_orgs = [org.id for org in self.request.user.commercialoperator_organisations.all()] - queryset = Compliance.objects.filter( Q(proposal__org_applicant_id__in = user_orgs) | Q(proposal__submitter = self.request.user) ).exclude(processing_status='discarded') - return queryset - return Compliance.objects.none() - -# def list(self, request, *args, **kwargs): -# response = super(ProposalPaginatedViewSet, self).list(request, args, kwargs) -# -# # Add extra data to response.data -# #response.data['regions'] = self.get_queryset().filter(region__isnull=False).values_list('region__name', flat=True).distinct() -# return response - - @list_route(methods=['GET',]) - def compliances_external(self, request, *args, **kwargs): - """ - Paginated serializer for datatables - used by the external dashboard - - To test: - http://localhost:8000/api/compliance_paginated/compliances_external/?format=datatables&draw=1&length=2 - """ - - qs = self.get_queryset().exclude(processing_status='future') - #qs = ProposalFilterBackend().filter_queryset(self.request, qs, self) - qs = self.filter_queryset(qs) - #qs = qs.order_by('lodgement_number', '-issue_date').distinct('lodgement_number') - - # on the internal organisations dashboard, filter the Proposal/Approval/Compliance datatables by applicant/organisation - applicant_id = request.GET.get('org_id') - if applicant_id: - qs = qs.filter(proposal__org_applicant_id=applicant_id) - submitter_id = request.GET.get('submitter_id', None) - if submitter_id: - qs = qs.filter(proposal__submitter_id=submitter_id) - self.paginator.page_size = qs.count() - result_page = self.paginator.paginate_queryset(qs, request) - serializer = ComplianceSerializer(result_page, context={'request':request}, many=True) - return self.paginator.get_paginated_response(serializer.data) - - -class ComplianceViewSet(viewsets.ModelViewSet): - serializer_class = ComplianceSerializer - #queryset = Compliance.objects.all() - queryset = Compliance.objects.none() - - def get_queryset(self): - if is_internal(self.request): - return Compliance.objects.all().exclude(processing_status='discarded') - elif is_customer(self.request): - user_orgs = [org.id for org in self.request.user.commercialoperator_organisations.all()] - queryset = Compliance.objects.filter( Q(proposal__org_applicant_id__in = user_orgs) | Q(proposal__submitter = self.request.user) ).exclude(processing_status='discarded') - return queryset - return Compliance.objects.none() - - def list(self, request, *args, **kwargs): - queryset = self.get_queryset() - # Filter by org - org_id = request.GET.get('org_id',None) - if org_id: - queryset = queryset.filter(proposal__org_applicant_id=org_id) - submitter_id = request.GET.get('submitter_id', None) - if submitter_id: - qs = qs.filter(proposal__submitter_id=submitter_id) - serializer = self.get_serializer(queryset, many=True) - return Response(serializer.data) - - @list_route(methods=['GET',]) - def filter_list(self, request, *args, **kwargs): - """ Used by the external dashboard filters """ - region_qs = self.get_queryset().filter(proposal__region__isnull=False).values_list('proposal__region__name', flat=True).distinct() - activity_qs = self.get_queryset().filter(proposal__activity__isnull=False).values_list('proposal__activity', flat=True).distinct() - data = dict( - regions=region_qs, - activities=activity_qs, - ) - return Response(data) - - @detail_route(methods=['GET',]) - def internal_compliance(self, request, *args, **kwargs): - instance = self.get_object() - serializer = InternalComplianceSerializer(instance,context={'request':request}) - return Response(serializer.data) - - -# @list_route(methods=['GET',]) -# def compliances_paginated(self, request, *args, **kwargs): -# """ -# Used by the external dashboard -# -# http://localhost:8499/api/compliances/compliances_external/paginated/?format=datatables&draw=1&length=2 -# """ -# -# qs = self.get_queryset().exclude(processing_status='future') -# qs = ProposalFilterBackend().filter_queryset(request, qs, self) -# -# paginator = DatatablesPageNumberPagination() -# paginator.page_size = qs.count() -# result_page = paginator.paginate_queryset(qs, request) -# serializer = ComplianceSerializer(result_page, context={'request':request}, many=True) -# return paginator.get_paginated_response(serializer.data) - -# @list_route(methods=['GET',]) -# def user_list(self, request, *args, **kwargs): -# #Remove filter to include 'Apporved Proposals in external dashboard .exclude(processing_status=Proposal.PROCESSING_STATUS_CHOICES[13][0]) -# queryset = self.get_queryset().exclude(processing_status='future') -# serializer = ComplianceSerializer(queryset, many=True) -# return Response(serializer.data) -# -# @list_route(methods=['GET']) -# def user_list_paginated(self, request, *args, **kwargs): -# """ -# Placing Paginator class here (instead of settings.py) allows specific method for desired behaviour), -# otherwise all serializers will use the default pagination class -# -# https://stackoverflow.com/questions/29128225/django-rest-framework-3-1-breaks-pagination-paginationserializer -# """ -# queryset = self.get_queryset().exclude(processing_status='future') -# paginator = DatatablesPageNumberPagination() -# paginator.page_size = queryset.count() -# result_page = paginator.paginate_queryset(queryset, request) -# #serializer = ListProposalSerializer(result_page, context={'request':request}, many=True) -# serializer = self.get_serializer(result_page, context={'request':request}, many=True) -# return paginator.get_paginated_response(serializer.data) - - @detail_route(methods=['POST',]) - @renderer_classes((JSONRenderer,)) - def submit(self, request, *args, **kwargs): - try: - with transaction.atomic(): - instance = self.get_object() - data = { - 'text': request.data.get('detail') - } - serializer = SaveComplianceSerializer(instance, data=data) - serializer.is_valid(raise_exception=True) - instance = serializer.save() - instance.submit(request) - serializer = self.get_serializer(instance) - # Save the files - '''for f in request.FILES: - document = instance.documents.create() - document.name = str(request.FILES[f]) - document._file = request.FILES[f] - document.save() - # End Save Documents''' - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e[0].encode('utf-8'))) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['GET',]) - def assign_request_user(self, request, *args, **kwargs): - try: - instance = self.get_object() - instance.assign_to(request.user,request) - serializer = InternalComplianceSerializer(instance) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['POST',]) - def delete_document(self, request, *args, **kwargs): - try: - instance = self.get_object() - doc=request.data.get('document') - instance.delete_document(request, doc) - serializer = ComplianceSerializer(instance) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e[0].encode('utf-8'))) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['POST',]) - def assign_to(self, request, *args, **kwargs): - try: - instance = self.get_object() - user_id = request.data.get('user_id',None) - user = None - if not user_id: - raise serializers.ValiationError('A user id is required') - try: - user = EmailUser.objects.get(id=user_id) - except EmailUser.DoesNotExist: - raise serializers.ValidationError('A user with the id passed in does not exist') - instance.assign_to(user,request) - serializer = InternalComplianceSerializer(instance) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['GET',]) - def unassign(self, request, *args, **kwargs): - try: - instance = self.get_object() - instance.unassign(request) - serializer = InternalComplianceSerializer(instance) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['GET',]) - def accept(self, request, *args, **kwargs): - try: - instance = self.get_object() - instance.accept(request) - serializer = InternalComplianceSerializer(instance) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['GET',]) - def amendment_request(self, request, *args, **kwargs): - try: - instance = self.get_object() - qs = instance.amendment_requests - qs = qs.filter(status = 'requested') - serializer = CompAmendmentRequestDisplaySerializer(qs,many=True) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['GET',]) - def action_log(self, request, *args, **kwargs): - try: - instance = self.get_object() - qs = instance.action_logs.all() - serializer = ComplianceActionSerializer(qs,many=True) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['GET',]) - def comms_log(self, request, *args, **kwargs): - try: - instance = self.get_object() - qs = instance.comms_logs.all() - serializer = ComplianceCommsSerializer(qs,many=True) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['POST',]) - @renderer_classes((JSONRenderer,)) - def add_comms_log(self, request, *args, **kwargs): - try: - with transaction.atomic(): - instance = self.get_object() - request.data['compliance'] = u'{}'.format(instance.id) - request.data['staff'] = u'{}'.format(request.user.id) - serializer = ComplianceCommsSerializer(data=request.data) - serializer.is_valid(raise_exception=True) - comms = serializer.save() - # Save the files - for f in request.FILES: - document = comms.documents.create() - document.name = str(request.FILES[f]) - document._file = request.FILES[f] - document.save() - # End Save Documents - - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - -class ComplianceAmendmentRequestViewSet(viewsets.ModelViewSet): - queryset = ComplianceAmendmentRequest.objects.all() - serializer_class = ComplianceAmendmentRequestSerializer - - def create(self, request, *args, **kwargs): - try: - serializer = self.get_serializer(data= request.data) - serializer.is_valid(raise_exception = True) - instance = serializer.save() - instance.generate_amendment(request) - serializer = self.get_serializer(instance) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - if hasattr(e,'error_dict'): - raise serializers.ValidationError(repr(e.error_dict)) - else: - raise serializers.ValidationError(repr(e[0].encode('utf-8'))) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - - - -class ComplianceAmendmentReasonChoicesView(views.APIView): - - renderer_classes = [JSONRenderer,] - def get(self,request, format=None): - choices_list = [] - #choices = ComplianceAmendmentRequest.REASON_CHOICES - choices=ComplianceAmendmentReason.objects.all() - if choices: - for c in choices: - choices_list.append({'key': c.id,'value': c.reason}) - return Response(choices_list) - diff --git a/commercialoperator/components/compliances/email.py b/commercialoperator/components/compliances/email.py deleted file mode 100755 index 86cc793ee8..0000000000 --- a/commercialoperator/components/compliances/email.py +++ /dev/null @@ -1,402 +0,0 @@ -import logging - -from django.core.mail import EmailMultiAlternatives, EmailMessage -from django.utils.encoding import smart_text -from django.core.urlresolvers import reverse -from django.conf import settings - -from commercialoperator.components.emails.emails import TemplateEmailBase -from ledger.accounts.models import EmailUser - -logger = logging.getLogger(__name__) - -SYSTEM_NAME = settings.SYSTEM_NAME_SHORT + ' Automated Message' -class ComplianceExternalSubmitSendNotificationEmail(TemplateEmailBase): - subject = '{} - Commercial Operations licence requirement.'.format(settings.DEP_NAME) - html_template = 'commercialoperator/emails/send_external_submit_notification.html' - txt_template = 'commercialoperator/emails/send_external_submit_notification.txt' - -class ComplianceSubmitSendNotificationEmail(TemplateEmailBase): - subject = 'A new Compliance has been submitted.' - html_template = 'commercialoperator/emails/send_submit_notification.html' - txt_template = 'commercialoperator/emails/send_submit_notification.txt' - -class ComplianceAcceptNotificationEmail(TemplateEmailBase): - subject = '{} - Commercial Operations- Confirmation - Licence requirement completed.'.format(settings.DEP_NAME) - html_template = 'commercialoperator/emails/compliance_accept_notification.html' - txt_template = 'commercialoperator/emails/compliance_accept_notification.txt' - -class ComplianceAmendmentRequestSendNotificationEmail(TemplateEmailBase): - subject = '{} - Commercial Operations licence requirement.'.format(settings.DEP_NAME) - html_template = 'commercialoperator/emails/send_amendment_notification.html' - txt_template = 'commercialoperator/emails/send_amendment_notification.txt' - -class ComplianceReminderNotificationEmail(TemplateEmailBase): - subject = '{} - Commercial Operations Licence requirement overdue.'.format(settings.DEP_NAME) - html_template = 'commercialoperator/emails/send_reminder_notification.html' - txt_template = 'commercialoperator/emails/send_reminder_notification.txt' - -class ComplianceInternalReminderNotificationEmail(TemplateEmailBase): - subject = 'A Compliance with requirements has passed the due date.' - html_template = 'commercialoperator/emails/send_internal_reminder_notification.html' - txt_template = 'commercialoperator/emails/send_internal_reminder_notification.txt' - -class ComplianceDueNotificationEmail(TemplateEmailBase): - subject = '{} - Commercial Operations Licence requirement due.'.format(settings.DEP_NAME) - html_template = 'commercialoperator/emails/send_due_notification.html' - txt_template = 'commercialoperator/emails/send_due_notification.txt' - -class ComplianceInternalDueNotificationEmail(TemplateEmailBase): - subject = 'A Compliance with requirements is due for submission.' - html_template = 'commercialoperator/emails/send_internal_due_notification.html' - txt_template = 'commercialoperator/emails/send_internal_due_notification.txt' - -def send_amendment_email_notification(amendment_request, request, compliance, is_test=False): - email = ComplianceAmendmentRequestSendNotificationEmail() - #reason = amendment_request.get_reason_display() - reason = amendment_request.reason.reason - url = request.build_absolute_uri(reverse('external-compliance-detail',kwargs={'compliance_pk': compliance.id})) - url = ''.join(url.split('-internal')) - login_url = request.build_absolute_uri(reverse('external')) - login_url = ''.join(login_url.split('-internal')) - context = { - 'compliance': compliance, - 'reason': reason, - 'amendment_request_text': amendment_request.text, - 'url': url - } - - submitter = compliance.submitter.email if compliance.submitter and compliance.submitter.email else compliance.proposal.submitter.email - msg = email.send(submitter, context=context) - if is_test: - return - - sender = request.user if request else settings.DEFAULT_FROM_EMAIL - _log_compliance_email(msg, compliance, sender=sender) - if compliance.proposal.org_applicant: - _log_org_email(msg, compliance.proposal.org_applicant, compliance.submitter, sender=sender) - else: - _log_user_email(msg, compliance.proposal.submitter, compliance.submitter, sender=sender) - - -#send reminder emails if Compliance has not been lodged by due date. Used in Cron job so cannot use 'request' parameter -def send_reminder_email_notification(compliance, is_test=False): - """ Used by the management command, therefore have no request object - therefore explicitly defining base_url """ - email = ComplianceReminderNotificationEmail() - #url = request.build_absolute_uri(reverse('external-compliance-detail',kwargs={'compliance_pk': compliance.id})) - url=settings.SITE_URL if settings.SITE_URL else '' - url+=reverse('external-compliance-detail',kwargs={'compliance_pk': compliance.id}) - login_url=settings.SITE_URL if settings.SITE_URL else '' - login_url+=reverse('external') - context = { - 'compliance': compliance, - 'url': url, - 'login_url': login_url - } - - submitter = compliance.submitter.email if compliance.submitter and compliance.submitter.email else compliance.proposal.submitter.email - msg = email.send(submitter, context=context) - if is_test: - return - - sender = settings.DEFAULT_FROM_EMAIL - try: - sender_user = EmailUser.objects.get(email__icontains=sender) - except: - sender_user = EmailUser.objects.create(email=sender, password='', is_staff=True) - _log_compliance_email(msg, compliance, sender=sender_user) - if compliance.proposal.org_applicant: - _log_org_email(msg, compliance.proposal.org_applicant, compliance.submitter, sender=sender_user) - else: - _log_user_email(msg, compliance.proposal.submitter, compliance.submitter, sender=sender) - -def send_internal_reminder_email_notification(compliance, is_test=False): - email = ComplianceInternalReminderNotificationEmail() - #url = request.build_absolute_uri(reverse('external-compliance-detail',kwargs={'compliance_pk': compliance.id})) - url=settings.SITE_URL - url+=reverse('internal-compliance-detail',kwargs={'compliance_pk': compliance.id}) - if "-internal" not in url: - # add it. This email is for internal staff - url = '-internal.{}'.format(settings.SITE_DOMAIN).join(url.split('.' + settings.SITE_DOMAIN)) - - context = { - 'compliance': compliance, - 'url': url - } - - msg = email.send(compliance.proposal.assessor_recipients, context=context) - if is_test: - return - - sender = settings.DEFAULT_FROM_EMAIL - try: - sender_user = EmailUser.objects.get(email__icontains=sender) - except: - sender_user = EmailUser.objects.create(email=sender, password='') - _log_compliance_email(msg, compliance, sender=sender_user) - if compliance.proposal.org_applicant: - _log_org_email(msg, compliance.proposal.org_applicant, compliance.submitter, sender=sender_user) - else: - _log_user_email(msg, compliance.proposal.submitter, compliance.submitter, sender=sender) - - -def send_due_email_notification(compliance, is_test=False): - email = ComplianceDueNotificationEmail() - #url = request.build_absolute_uri(reverse('external-compliance-detail',kwargs={'compliance_pk': compliance.id})) - url=settings.SITE_URL - url+=reverse('external-compliance-detail',kwargs={'compliance_pk': compliance.id}) - context = { - 'compliance': compliance, - 'url': url - } - - submitter = compliance.submitter.email if compliance.submitter and compliance.submitter.email else compliance.proposal.submitter.email - msg = email.send(submitter, context=context) - if is_test: - return - - sender = settings.DEFAULT_FROM_EMAIL - try: - sender_user = EmailUser.objects.get(email__icontains=sender) - except: - sender_user = EmailUser.objects.create(email=sender, password='', is_staff=True) - _log_compliance_email(msg, compliance, sender=sender_user) - if compliance.proposal.org_applicant: - _log_org_email(msg, compliance.proposal.org_applicant, compliance.submitter, sender=sender_user) - else: - _log_user_email(msg, compliance.proposal.submitter, compliance.submitter, sender=sender) - - -def send_internal_due_email_notification(compliance, is_test=False): - email = ComplianceInternalDueNotificationEmail() - #url = request.build_absolute_uri(reverse('external-compliance-detail',kwargs={'compliance_pk': compliance.id})) - url=settings.SITE_URL - url+=reverse('internal-compliance-detail',kwargs={'compliance_pk': compliance.id}) - if "-internal" not in url: - # add it. This email is for internal staff - url = '-internal.{}'.format(settings.SITE_DOMAIN).join(url.split('.' + settings.SITE_DOMAIN)) - - context = { - 'compliance': compliance, - 'url': url - } - - msg = email.send(compliance.proposal.assessor_recipients, context=context) - if is_test: - return - - sender = settings.DEFAULT_FROM_EMAIL - try: - sender_user = EmailUser.objects.get(email__icontains=sender) - except: - sender_user = EmailUser.objects.create(email=sender, password='', is_staff=True) - _log_compliance_email(msg, compliance, sender=sender_user) - if compliance.proposal.org_applicant: - _log_org_email(msg, compliance.proposal.org_applicant, compliance.submitter, sender=sender_user) - else: - _log_user_email(msg, compliance.proposal.submitter, compliance.submitter, sender=sender) - - -def send_compliance_accept_email_notification(compliance,request, is_test=False): - email = ComplianceAcceptNotificationEmail() - - context = { - 'compliance': compliance - } - submitter = compliance.submitter.email if compliance.submitter and compliance.submitter.email else compliance.proposal.submitter.email - msg = email.send(submitter, context=context) - if is_test: - return - - sender = request.user if request else settings.DEFAULT_FROM_EMAIL - _log_compliance_email(msg, compliance, sender=sender) - if compliance.proposal.org_applicant: - _log_org_email(msg, compliance.proposal.org_applicant, compliance.submitter, sender=sender) - else: - _log_user_email(msg, compliance.proposal.submitter, compliance.submitter, sender=sender) - -def send_external_submit_email_notification(request, compliance, is_test=False): - email = ComplianceExternalSubmitSendNotificationEmail() - url = request.build_absolute_uri(reverse('external-compliance-detail',kwargs={'compliance_pk': compliance.id})) - url = ''.join(url.split('-internal')) - submitter = compliance.submitter if compliance.submitter and compliance.submitter.email else compliance.proposal.submitter - context = { - 'compliance': compliance, - 'submitter': submitter.get_full_name(), - 'url': url - } - - msg = email.send(submitter.email, context=context) - if is_test: - return - - sender = request.user if request else settings.DEFAULT_FROM_EMAIL - _log_compliance_email(msg, compliance, sender=sender) - if compliance.proposal.org_applicant: - _log_org_email(msg, compliance.proposal.org_applicant, compliance.submitter, sender=sender) - else: - _log_user_email(msg, compliance.proposal.submitter, compliance.submitter, sender=sender) - -def send_submit_email_notification(request, compliance, is_test=False): - email = ComplianceSubmitSendNotificationEmail() - url = request.build_absolute_uri(reverse('internal-compliance-detail',kwargs={'compliance_pk': compliance.id})) - if "-internal" not in url: - # add it. This email is for internal staff - url = '-internal.{}'.format(settings.SITE_DOMAIN).join(url.split('.' + settings.SITE_DOMAIN)) - - context = { - 'compliance': compliance, - 'url': url - } - - msg = email.send(compliance.proposal.assessor_recipients, context=context) - if is_test: - return - - sender = request.user if request else settings.DEFAULT_FROM_EMAIL - _log_compliance_email(msg, compliance, sender=sender) - if compliance.proposal.org_applicant: - _log_org_email(msg, compliance.proposal.org_applicant, compliance.submitter, sender=sender) - else: - _log_user_email(msg, compliance.proposal.submitter, compliance.submitter, sender=sender) - - -def _log_compliance_email(email_message, compliance, sender=None): - from commercialoperator.components.compliances.models import ComplianceLogEntry - if isinstance(email_message, (EmailMultiAlternatives, EmailMessage,)): - # TODO this will log the plain text body, should we log the html instead - text = email_message.body - subject = email_message.subject - fromm = smart_text(sender) if sender else smart_text(email_message.from_email) - # the to email is normally a list - if isinstance(email_message.to, list): - to = ','.join(email_message.to) - else: - to = smart_text(email_message.to) - # we log the cc and bcc in the same cc field of the log entry as a ',' comma separated string - all_ccs = [] - if email_message.cc: - all_ccs += list(email_message.cc) - if email_message.bcc: - all_ccs += list(email_message.bcc) - all_ccs = ','.join(all_ccs) - - else: - text = smart_text(email_message) - subject = '' - to = compliance.submitter.email - fromm = smart_text(sender) if sender else SYSTEM_NAME - all_ccs = '' - - customer = compliance.submitter - - staff = sender - - kwargs = { - 'subject': subject, - 'text': text, - 'compliance': compliance, - 'customer': customer, - 'staff': staff, - 'to': to, - 'fromm': fromm, - 'cc': all_ccs - } - - email_entry = ComplianceLogEntry.objects.create(**kwargs) - - return email_entry - - -def _log_org_email(email_message, organisation, customer ,sender=None): - from commercialoperator.components.organisations.models import OrganisationLogEntry - if isinstance(email_message, (EmailMultiAlternatives, EmailMessage,)): - # TODO this will log the plain text body, should we log the html instead - text = email_message.body - subject = email_message.subject - fromm = smart_text(sender) if sender else smart_text(email_message.from_email) - # the to email is normally a list - if isinstance(email_message.to, list): - to = ','.join(email_message.to) - else: - to = smart_text(email_message.to) - # we log the cc and bcc in the same cc field of the log entry as a ',' comma separated string - all_ccs = [] - if email_message.cc: - all_ccs += list(email_message.cc) - if email_message.bcc: - all_ccs += list(email_message.bcc) - all_ccs = ','.join(all_ccs) - - else: - text = smart_text(email_message) - subject = '' - to = customer.email - fromm = smart_text(sender) if sender else SYSTEM_NAME - all_ccs = '' - - customer = customer - - staff = sender - - kwargs = { - 'subject': subject, - 'text': text, - 'organisation': organisation, - 'customer': customer, - 'staff': staff, - 'to': to, - 'fromm': fromm, - 'cc': all_ccs - } - - email_entry = OrganisationLogEntry.objects.create(**kwargs) - - return email_entry - -def _log_user_email(email_message, emailuser, customer ,sender=None): - from ledger.accounts.models import EmailUserLogEntry - if isinstance(email_message, (EmailMultiAlternatives, EmailMessage,)): - # TODO this will log the plain text body, should we log the html instead - text = email_message.body - subject = email_message.subject - fromm = smart_text(sender) if sender else smart_text(email_message.from_email) - # the to email is normally a list - if isinstance(email_message.to, list): - to = ','.join(email_message.to) - else: - to = smart_text(email_message.to) - # we log the cc and bcc in the same cc field of the log entry as a ',' comma separated string - all_ccs = [] - if email_message.cc: - all_ccs += list(email_message.cc) - if email_message.bcc: - all_ccs += list(email_message.bcc) - all_ccs = ','.join(all_ccs) - - else: - text = smart_text(email_message) - subject = '' - to = customer - fromm = smart_text(sender) if sender else SYSTEM_NAME - all_ccs = '' - - customer = customer - - staff = sender - - kwargs = { - 'subject': subject, - 'text': text, - 'emailuser': emailuser, - 'customer': customer, - 'staff': staff, - 'to': to, - 'fromm': fromm, - 'cc': all_ccs - } - - email_entry = EmailUserLogEntry.objects.create(**kwargs) - - return email_entry - diff --git a/commercialoperator/components/compliances/models.py b/commercialoperator/components/compliances/models.py deleted file mode 100755 index adb287e0c0..0000000000 --- a/commercialoperator/components/compliances/models.py +++ /dev/null @@ -1,359 +0,0 @@ - -from __future__ import unicode_literals - -import json -import datetime -from django.db import models,transaction -from django.dispatch import receiver -from django.db.models.signals import pre_delete -from django.utils.encoding import python_2_unicode_compatible -from django.core.exceptions import ValidationError -from django.contrib.postgres.fields.jsonb import JSONField -from django.utils import timezone -from django.contrib.sites.models import Site -from django.conf import settings -from taggit.managers import TaggableManager -from taggit.models import TaggedItemBase -from ledger.accounts.models import Organisation as ledger_organisation -from ledger.accounts.models import EmailUser, RevisionedMixin -from ledger.licence.models import Licence -from commercialoperator import exceptions -from commercialoperator.components.organisations.models import Organisation -from commercialoperator.components.main.models import CommunicationsLogEntry, Region, UserAction, Document -from commercialoperator.components.proposals.models import ProposalRequirement, AmendmentReason -from commercialoperator.components.compliances.email import ( - send_compliance_accept_email_notification, - send_amendment_email_notification, - send_reminder_email_notification, - send_external_submit_email_notification, - send_submit_email_notification, - send_internal_reminder_email_notification, - send_due_email_notification, - send_internal_due_email_notification - ) - -import logging -logger = logging.getLogger(__name__) - - -#class Compliance(models.Model): -class Compliance(RevisionedMixin): - - PROCESSING_STATUS_CHOICES = (('due', 'Due'), - ('future', 'Future'), - ('with_assessor', 'With Assessor'), - ('approved', 'Approved'), - ('discarded', 'Discarded'), - ) - - CUSTOMER_STATUS_CHOICES = (('due', 'Due'), - ('future', 'Future'), - ('with_assessor', 'Under Review'), - ('approved', 'Approved'), - ('discarded', 'Discarded'), - ) - - - lodgement_number = models.CharField(max_length=9, blank=True, default='') - proposal = models.ForeignKey('commercialoperator.Proposal',related_name='compliances') - approval = models.ForeignKey('commercialoperator.Approval',related_name='compliances') - due_date = models.DateField() - text = models.TextField(blank=True) - processing_status = models.CharField(choices=PROCESSING_STATUS_CHOICES,max_length=20) - customer_status = models.CharField(choices=CUSTOMER_STATUS_CHOICES,max_length=20, default=CUSTOMER_STATUS_CHOICES[1][0]) - assigned_to = models.ForeignKey(EmailUser,related_name='commercialoperator_compliance_assignments',null=True,blank=True) - #requirement = models.TextField(null=True,blank=True) - requirement = models.ForeignKey(ProposalRequirement, blank=True, null=True, related_name='compliance_requirement', on_delete=models.SET_NULL) - lodgement_date = models.DateTimeField(blank=True, null=True) - submitter = models.ForeignKey(EmailUser, blank=True, null=True, related_name='commercialoperator_compliances') - reminder_sent = models.BooleanField(default=False) - post_reminder_sent = models.BooleanField(default=False) - - - class Meta: - app_label = 'commercialoperator' - - @property - def regions(self): - return self.proposal.regions_list - - @property - def activity(self): - return self.proposal.activity - - @property - def title(self): - return self.proposal.title - - @property - def holder(self): - return self.proposal.applicant - - @property - def reference(self): - #return 'C{0:06d}'.format(self.id) - return self.lodgement_number - - @property - def allowed_assessors(self): - return self.proposal.compliance_assessors - - @property - def can_user_view(self): - """ - :return: True if the compliance is not in the editable status for external user. - """ - return self.customer_status == 'with_assessor' or self.customer_status == 'approved' - - @property - def can_process(self): - """ - :return: True if the compliance is ready for assessment. - """ - return self.processing_status == 'with_assessor' - - - @property - def amendment_requests(self): - qs =ComplianceAmendmentRequest.objects.filter(compliance = self) - return qs - - def save(self, *args, **kwargs): - super(Compliance, self).save(*args,**kwargs) - if self.lodgement_number == '': - new_lodgment_id = 'C{0:06d}'.format(self.pk) - self.lodgement_number = new_lodgment_id - self.save() - - def submit(self,request): - with transaction.atomic(): - try: - if self.processing_status=='discarded': - raise ValidationError('You cannot submit this compliance with requirements as it has been discarded.') - if self.processing_status == 'future' or 'due': - self.processing_status = 'with_assessor' - self.customer_status = 'with_assessor' - self.submitter = request.user - - if request.FILES: - for f in request.FILES: - document = self.documents.create(name=str(request.FILES[f])) - document._file = request.FILES[f] - document.save() - if (self.amendment_requests): - qs = self.amendment_requests.filter(status = "requested") - if (qs): - for q in qs: - q.status = 'amended' - q.save() - - #self.lodgement_date = datetime.datetime.strptime(timezone.now().strftime('%Y-%m-%d'),'%Y-%m-%d').date() - self.lodgement_date = timezone.now() - self.save(version_comment='Compliance Submitted: {}'.format(self.id)) - self.proposal.save(version_comment='Compliance Submitted: {}'.format(self.id)) - self.log_user_action(ComplianceUserAction.ACTION_SUBMIT_REQUEST.format(self.id),request) - send_external_submit_email_notification(request,self) - send_submit_email_notification(request,self) - self.documents.all().update(can_delete=False) - except: - raise - - def delete_document(self, request, document): - with transaction.atomic(): - try: - if document: - doc = self.documents.get(id=document[2]) - doc.delete() - return self - except: - raise ValidationError('Document not found') - - - def assign_to(self, user,request): - with transaction.atomic(): - self.assigned_to = user - self.save() - self.log_user_action(ComplianceUserAction.ACTION_ASSIGN_TO.format(user.get_full_name()),request) - - def unassign(self,request): - with transaction.atomic(): - self.assigned_to = None - self.save() - self.log_user_action(ComplianceUserAction.ACTION_UNASSIGN,request) - - def accept(self, request): - with transaction.atomic(): - self.processing_status = 'approved' - self.customer_status = 'approved' - self.save() - self.log_user_action(ComplianceUserAction.ACTION_CONCLUDE_REQUEST.format(self.id),request) - send_compliance_accept_email_notification(self,request) - - - def send_reminder(self,user): - with transaction.atomic(): - today = timezone.localtime(timezone.now()).date() - try: - if self.processing_status =='due': - if self.due_date < today and self.lodgement_date==None and self.post_reminder_sent==False: - send_reminder_email_notification(self) - send_internal_reminder_email_notification(self) - self.post_reminder_sent=True - self.reminder_sent=True - self.save() - ComplianceUserAction.log_action(self,ComplianceUserAction.ACTION_REMINDER_SENT.format(self.id),user) - logger.info('Post due date reminder sent for Compliance {} '.format(self.lodgement_number)) - elif self.due_date >= today and today >= self.due_date - datetime.timedelta(days=14) and self.reminder_sent==False: - # second part: if today is with 14 days of due_date, and email reminder is not sent (deals with Compliances created with the reminder period) - send_due_email_notification(self) - send_internal_due_email_notification(self) - self.reminder_sent=True - self.save() - ComplianceUserAction.log_action(self,ComplianceUserAction.ACTION_REMINDER_SENT.format(self.id),user) - logger.info('Pre due date reminder sent for Compliance {} '.format(self.lodgement_number)) - - except Exception as e: - logger.info('Error sending Reminder Compliance {}\n{}'.format(self.lodgement_number, e)) - - def log_user_action(self, action, request): - return ComplianceUserAction.log_action(self, action, request.user) - - def __str__(self): - return self.lodgement_number - - -def update_proposal_complaince_filename(instance, filename): - return '{}/proposals/{}/compliance/{}'.format(settings.MEDIA_APP_DIR, instance.compliance.proposal.id,filename) - - -class ComplianceDocument(Document): - compliance = models.ForeignKey('Compliance',related_name='documents') - _file = models.FileField(upload_to=update_proposal_complaince_filename) - can_delete = models.BooleanField(default=True) # after initial submit prevent document from being deleted - - def delete(self): - if self.can_delete: - return super(ComplianceDocument, self).delete() - logger.info('Cannot delete existing document object after Compliance has been submitted (including document submitted before Compliance pushback to status Due): {}'.format(self.name)) - - class Meta: - app_label = 'commercialoperator' - -class ComplianceUserAction(UserAction): - ACTION_CREATE = "Create compliance {}" - ACTION_SUBMIT_REQUEST = "Submit compliance {}" - ACTION_ASSIGN_TO = "Assign to {}" - ACTION_UNASSIGN = "Unassign" - ACTION_DECLINE_REQUEST = "Decline request" - ACTION_ID_REQUEST_AMENDMENTS = "Request amendments" - ACTION_REMINDER_SENT = "Reminder sent for compliance {}" - ACTION_STATUS_CHANGE = "Change status to Due for compliance {}" - # Assessors - - - - ACTION_CONCLUDE_REQUEST = "Conclude request {}" - - @classmethod - def log_action(cls, compliance, action, user): - return cls.objects.create( - compliance=compliance, - who=user, - what=str(action) - ) - - compliance = models.ForeignKey(Compliance,related_name='action_logs') - - class Meta: - app_label = 'commercialoperator' - -class ComplianceLogEntry(CommunicationsLogEntry): - compliance = models.ForeignKey(Compliance, related_name='comms_logs') - - def save(self, **kwargs): - # save the request id if the reference not provided - if not self.reference: - self.reference = self.compliance.id - super(ComplianceLogEntry, self).save(**kwargs) - - class Meta: - app_label = 'commercialoperator' - -def update_compliance_comms_log_filename(instance, filename): - return '{}/proposals/{}/compliance/communications/{}'.format(settings.MEDIA_APP_DIR, instance.log_entry.compliance.proposal.id,filename) - - -class ComplianceLogDocument(Document): - log_entry = models.ForeignKey('ComplianceLogEntry',related_name='documents') - _file = models.FileField(upload_to=update_compliance_comms_log_filename) - - class Meta: - app_label = 'commercialoperator' - -class CompRequest(models.Model): - compliance = models.ForeignKey(Compliance) - subject = models.CharField(max_length=200, blank=True) - text = models.TextField(blank=True) - officer = models.ForeignKey(EmailUser, null=True) - - class Meta: - app_label = 'commercialoperator' - -class ComplianceAmendmentReason(models.Model): - reason = models.CharField('Reason', max_length=125) - - class Meta: - app_label = 'commercialoperator' - - def __str__(self): - return self.reason - - -class ComplianceAmendmentRequest(CompRequest): - STATUS_CHOICES = (('requested', 'Requested'), ('amended', 'Amended')) - # try: - # # model requires some choices if AmendmentReason does not yet exist or is empty - # REASON_CHOICES = list(AmendmentReason.objects.values_list('id', 'reason')) - # if not REASON_CHOICES: - # REASON_CHOICES = ((0, 'The information provided was insufficient'), - # (1, 'There was missing information'), - # (2, 'Other')) - # except: - # REASON_CHOICES = ((0, 'The information provided was insufficient'), - # (1, 'There was missing information'), - # (2, 'Other')) - - status = models.CharField('Status', max_length=30, choices=STATUS_CHOICES, default=STATUS_CHOICES[0][0]) - # reason = models.CharField('Reason', max_length=30, choices=REASON_CHOICES, default=REASON_CHOICES[0][0]) - reason = models.ForeignKey(ComplianceAmendmentReason, blank=True, null=True) - - class Meta: - app_label = 'commercialoperator' - - def generate_amendment(self,request): - with transaction.atomic(): - if self.status == 'requested': - compliance = self.compliance - if compliance.processing_status != 'due': - compliance.processing_status = 'due' - compliance.customer_status = 'due' - compliance.save() - # Create a log entry for the proposal - compliance.log_user_action(ComplianceUserAction.ACTION_ID_REQUEST_AMENDMENTS,request) - # Create a log entry for the organisation - applicant_field=getattr(compliance.proposal, compliance.proposal.applicant_field) - applicant_field.log_user_action(ComplianceUserAction.ACTION_ID_REQUEST_AMENDMENTS,request) - send_amendment_email_notification(self,request, compliance) - - -import reversion -reversion.register(Compliance, follow=['documents', 'action_logs', 'comms_logs', 'comprequest_set']) -reversion.register(ComplianceDocument) -reversion.register(ComplianceUserAction) -reversion.register(ComplianceLogEntry, follow=['documents']) -reversion.register(ComplianceLogDocument) -reversion.register(CompRequest) -reversion.register(ComplianceAmendmentReason, follow=['complianceamendmentrequest_set']) -reversion.register(ComplianceAmendmentRequest) - - diff --git a/commercialoperator/components/compliances/pdf.py b/commercialoperator/components/compliances/pdf.py deleted file mode 100755 index e69de29bb2..0000000000 diff --git a/commercialoperator/components/compliances/serializers.py b/commercialoperator/components/compliances/serializers.py deleted file mode 100755 index 86b224039c..0000000000 --- a/commercialoperator/components/compliances/serializers.py +++ /dev/null @@ -1,184 +0,0 @@ -from django.conf import settings -from ledger.accounts.models import EmailUser,Address -from commercialoperator.components.compliances.models import ( - Compliance, ComplianceUserAction, ComplianceLogEntry, ComplianceAmendmentRequest, ComplianceAmendmentReason -) -from rest_framework import serializers - - -class EmailUserSerializer(serializers.ModelSerializer): - class Meta: - model = EmailUser - fields = ('id','email','first_name','last_name','title','organisation') - -class ComplianceSerializer(serializers.ModelSerializer): - regions = serializers.CharField(source='proposal.region') - activity = serializers.CharField(source='proposal.activity') - title = serializers.CharField(source='proposal.title') - holder = serializers.CharField(source='proposal.applicant') - processing_status = serializers.CharField(source='get_processing_status_display') - customer_status = serializers.CharField(source='get_customer_status_display') - submitter = serializers.SerializerMethodField(read_only=True) - documents = serializers.SerializerMethodField() - #submitter = serializers.CharField(source='submitter.get_full_name') - submitter = serializers.SerializerMethodField(read_only=True) - allowed_assessors = EmailUserSerializer(many=True) - #assigned_to = serializers.CharField(source='assigned_to.get_full_name') - assigned_to = serializers.SerializerMethodField(read_only=True) - requirement = serializers.CharField(source='requirement.requirement', required=False, allow_null=True) - approval_lodgement_number = serializers.SerializerMethodField() - - - class Meta: - model = Compliance - fields = ( - 'id', - 'proposal', - 'due_date', - 'processing_status', - 'customer_status', - 'regions', - 'activity', - 'title', - 'text', - 'holder', - 'assigned_to', - 'approval', - 'documents', - 'requirement', - 'can_user_view', - 'can_process', - 'reference', - 'lodgement_number', - 'lodgement_date', - 'submitter', - 'allowed_assessors', - 'lodgement_date', - 'approval_lodgement_number' - - ) - - def get_documents(self,obj): - return [[d.name,d._file.url,d.can_delete,d.id] for d in obj.documents.all()] - - def get_approval_lodgement_number(self,obj): - return obj.approval.lodgement_number - - def get_assigned_to(self,obj): - if obj.assigned_to: - return obj.assigned_to.get_full_name() - return None - - def get_submitter(self,obj): - if obj.submitter: - return obj.submitter.get_full_name() - return None - -class InternalComplianceSerializer(serializers.ModelSerializer): - regions = serializers.CharField(source='proposal.region') - activity = serializers.CharField(source='proposal.activity') - title = serializers.CharField(source='proposal.title') - holder = serializers.CharField(source='proposal.applicant') - processing_status = serializers.CharField(source='get_processing_status_display') - customer_status = serializers.CharField(source='get_customer_status_display') - submitter = serializers.SerializerMethodField(read_only=True) - documents = serializers.SerializerMethodField() - #submitter = serializers.CharField(source='submitter.get_full_name') - submitter = serializers.SerializerMethodField(read_only=True) - allowed_assessors = EmailUserSerializer(many=True) - #assigned_to = serializers.CharField(source='assigned_to.get_full_name') - #assigned_to = serializers.SerializerMethodField(read_only=True) - requirement = serializers.CharField(source='requirement.requirement', required=False, allow_null=True) - approval_lodgement_number = serializers.SerializerMethodField() - - - class Meta: - model = Compliance - fields = ( - 'id', - 'proposal', - 'due_date', - 'processing_status', - 'customer_status', - 'regions', - 'activity', - 'title', - 'text', - 'holder', - 'assigned_to', - 'approval', - 'documents', - 'requirement', - 'can_user_view', - 'can_process', - 'reference', - 'lodgement_number', - 'lodgement_date', - 'submitter', - 'allowed_assessors', - 'lodgement_date', - 'approval_lodgement_number' - - ) - - def get_documents(self,obj): - return [[d.name,d._file.url,d.can_delete,d.id] for d in obj.documents.all()] - - def get_approval_lodgement_number(self,obj): - return obj.approval.lodgement_number - - # def get_assigned_to(self,obj): - # if obj.assigned_to: - # return obj.assigned_to.get_full_name() - # return None - - def get_submitter(self,obj): - if obj.submitter: - return obj.submitter.get_full_name() - return None - -class SaveComplianceSerializer(serializers.ModelSerializer): - class Meta: - model = Compliance - fields = ( - 'id', - 'title', - 'text', - - ) - -class ComplianceActionSerializer(serializers.ModelSerializer): - who = serializers.CharField(source='who.get_full_name') - class Meta: - model = ComplianceUserAction - fields = '__all__' - -class ComplianceCommsSerializer(serializers.ModelSerializer): - documents = serializers.SerializerMethodField() - class Meta: - model = ComplianceLogEntry - fields = '__all__' - def get_documents(self,obj): - return [[d.name,d._file.url] for d in obj.documents.all()] - -class ComplianceAmendmentRequestSerializer(serializers.ModelSerializer): - #reason = serializers.SerializerMethodField() - - class Meta: - model = ComplianceAmendmentRequest - fields = '__all__' - - # def get_reason (self,obj): - # return obj.get_reason_display() - -class CompAmendmentRequestDisplaySerializer(serializers.ModelSerializer): - reason = serializers.SerializerMethodField() - - class Meta: - model = ComplianceAmendmentRequest - fields = '__all__' - - def get_reason (self,obj): - #return obj.get_reason_display() - return obj.reason.reason if obj.reason else None - diff --git a/commercialoperator/components/compliances/signals.py b/commercialoperator/components/compliances/signals.py deleted file mode 100755 index e69de29bb2..0000000000 diff --git a/commercialoperator/components/compliances/templates/commercialoperator/emails/compliance_accept_notification.html b/commercialoperator/components/compliances/templates/commercialoperator/emails/compliance_accept_notification.html deleted file mode 100755 index 6fc1f7ad17..0000000000 --- a/commercialoperator/components/compliances/templates/commercialoperator/emails/compliance_accept_notification.html +++ /dev/null @@ -1,8 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} -

The licence requirement to submit {{ compliance.reference}} has been completed.

- - -{% endblock %} diff --git a/commercialoperator/components/compliances/templates/commercialoperator/emails/compliance_accept_notification.txt b/commercialoperator/components/compliances/templates/commercialoperator/emails/compliance_accept_notification.txt deleted file mode 100755 index 6ed0a5aab0..0000000000 --- a/commercialoperator/components/compliances/templates/commercialoperator/emails/compliance_accept_notification.txt +++ /dev/null @@ -1,6 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.txt' %} - -{% block content %} - The licence requirement to submit {{ compliance.reference}} has been completed. - -{% endblock %} diff --git a/commercialoperator/components/compliances/templates/commercialoperator/emails/send_amendment_notification.html b/commercialoperator/components/compliances/templates/commercialoperator/emails/send_amendment_notification.html deleted file mode 100755 index 78b5f2c76c..0000000000 --- a/commercialoperator/components/compliances/templates/commercialoperator/emails/send_amendment_notification.html +++ /dev/null @@ -1,26 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} - Your document to complete a requirement {{ compliance.reference }} of your licence has been submitted. However, further information is required. Please login to your account here. - - {% if reason %} -

- Amendment Reason: {{ reason }} -

- {% endif %} - - {% if amendment_request_text %} -

Amendment details:
{{ amendment_request_text }}

- {% endif %} - -

You will receive a confirmation email, and it will show up on your account if the document meets the requirement.

- -

You will receive a notification email if there is any incomplete information or documents missing.

- - - - -{% endblock %} diff --git a/commercialoperator/components/compliances/templates/commercialoperator/emails/send_amendment_notification.txt b/commercialoperator/components/compliances/templates/commercialoperator/emails/send_amendment_notification.txt deleted file mode 100755 index 1107e351f8..0000000000 --- a/commercialoperator/components/compliances/templates/commercialoperator/emails/send_amendment_notification.txt +++ /dev/null @@ -1,20 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.txt' %} - -{% block content %} - Your document to complete a requirement {{ compliance.reference }} of your licence has been submitted. However, further information is required. Please login to your account here. - - {% if reason %} -

- Amendment Reason: {{ reason }} -

- {% endif %} - - {% if amendment_request_text %} -

Amendment details:
{{ amendment_request_text }}

- {% endif %} - You will receive a confirmation email, and it will show up on your account if the document meets the requirement. - - You will receive a notification email if there is any incomplete information or documents missing. - - -{% endblock %} diff --git a/commercialoperator/components/compliances/templates/commercialoperator/emails/send_due_notification.html b/commercialoperator/components/compliances/templates/commercialoperator/emails/send_due_notification.html deleted file mode 100755 index 558653331c..0000000000 --- a/commercialoperator/components/compliances/templates/commercialoperator/emails/send_due_notification.html +++ /dev/null @@ -1,16 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} - - -

Please be aware that the following is due for submission:
- {{ compliance.reference }} {{compliance.requirement.requirement}}

-

- To complete the licence requirement please login to your account here. -

- -{% endblock %} diff --git a/commercialoperator/components/compliances/templates/commercialoperator/emails/send_due_notification.txt b/commercialoperator/components/compliances/templates/commercialoperator/emails/send_due_notification.txt deleted file mode 100755 index 166e52eb55..0000000000 --- a/commercialoperator/components/compliances/templates/commercialoperator/emails/send_due_notification.txt +++ /dev/null @@ -1,10 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.txt' %} - -{% block content %} - Please be aware that the following is due for submission:
- {{ compliance.reference }} {{compliance.requirement.requirement}} - - To complete the licence requirement please login to your account here. - - -{% endblock %} diff --git a/commercialoperator/components/compliances/templates/commercialoperator/emails/send_external_submit_notification.html b/commercialoperator/components/compliances/templates/commercialoperator/emails/send_external_submit_notification.html deleted file mode 100755 index c977753a6e..0000000000 --- a/commercialoperator/components/compliances/templates/commercialoperator/emails/send_external_submit_notification.html +++ /dev/null @@ -1,19 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} - Your document to complete a requirement {{ compliance.reference }} of your licence has been submitted.
- - - -

You will receive a confirmation email, and it will show up on your account if the document meets the requirement.

- -

You will receive a notification email if there is any incomplete information or documents missing.

- - - - -{% endblock %} diff --git a/commercialoperator/components/compliances/templates/commercialoperator/emails/send_external_submit_notification.txt b/commercialoperator/components/compliances/templates/commercialoperator/emails/send_external_submit_notification.txt deleted file mode 100755 index 96174a3109..0000000000 --- a/commercialoperator/components/compliances/templates/commercialoperator/emails/send_external_submit_notification.txt +++ /dev/null @@ -1,11 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.txt' %} - -{% block content %} - Your document to complete a requirement {{ compliance.reference }} of your licence has been submitted.. - - You will receive a confirmation email, and it will show up on your account if the document meets the requirement. - - You will receive a notification email if there is any incomplete information or documents missing. - - -{% endblock %} diff --git a/commercialoperator/components/compliances/templates/commercialoperator/emails/send_internal_due_notification.html b/commercialoperator/components/compliances/templates/commercialoperator/emails/send_internal_due_notification.html deleted file mode 100755 index c56c1f9544..0000000000 --- a/commercialoperator/components/compliances/templates/commercialoperator/emails/send_internal_due_notification.html +++ /dev/null @@ -1,12 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} - - A Compliance with requirements {{ compliance.reference }} {{compliance.requirement.requirement}} is due for submission. -

- You can access this Compliance using the following link: -

- Access Compliance - - -{% endblock %} diff --git a/commercialoperator/components/compliances/templates/commercialoperator/emails/send_internal_due_notification.txt b/commercialoperator/components/compliances/templates/commercialoperator/emails/send_internal_due_notification.txt deleted file mode 100755 index 27c7844fc5..0000000000 --- a/commercialoperator/components/compliances/templates/commercialoperator/emails/send_internal_due_notification.txt +++ /dev/null @@ -1,12 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.txt' %} - -{% block content %} - A Compliance with requirements{{ compliance.reference }} {{compliance.requirement.requirement}} is due for submission. - -

- You can access this Compliance using the following link: -

- {{url}} - - -{% endblock %} diff --git a/commercialoperator/components/compliances/templates/commercialoperator/emails/send_internal_reminder_notification.html b/commercialoperator/components/compliances/templates/commercialoperator/emails/send_internal_reminder_notification.html deleted file mode 100755 index 65add0c78a..0000000000 --- a/commercialoperator/components/compliances/templates/commercialoperator/emails/send_internal_reminder_notification.html +++ /dev/null @@ -1,12 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} - - A Compliance with requirements {{ compliance.reference }} has passed the due date and has not been lodged yet. -

- You can access this Compliance using the following link: -

- Access Compliance - - -{% endblock %} diff --git a/commercialoperator/components/compliances/templates/commercialoperator/emails/send_internal_reminder_notification.txt b/commercialoperator/components/compliances/templates/commercialoperator/emails/send_internal_reminder_notification.txt deleted file mode 100755 index 865148ac85..0000000000 --- a/commercialoperator/components/compliances/templates/commercialoperator/emails/send_internal_reminder_notification.txt +++ /dev/null @@ -1,12 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.txt' %} - -{% block content %} - A Compliance with requirements{{ compliance.reference }} has passed the due date and has not been lodged yet. - -

- You can access this Compliance using the following link: -

- {{url}} - - -{% endblock %} diff --git a/commercialoperator/components/compliances/templates/commercialoperator/emails/send_reminder_notification.html b/commercialoperator/components/compliances/templates/commercialoperator/emails/send_reminder_notification.html deleted file mode 100755 index 7d503da99b..0000000000 --- a/commercialoperator/components/compliances/templates/commercialoperator/emails/send_reminder_notification.html +++ /dev/null @@ -1,20 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} - - - -

Please be aware that the following is overdue:

-

{{ compliance.reference }} - {{compliance.requirement.requirement}}

- -

To complete the licence requirement please login to your account here.

- -

It is a condition of your licence that you complete all requirements. Failure to do so may result in cancellation or suspension of the commercial operations licence.

- -

If you have any queries please contact a licensing officer on {{settings.DEP_PHONE}}, or email {{settings.SUPPORT_EMAIL}}

- -{% endblock %} diff --git a/commercialoperator/components/compliances/templates/commercialoperator/emails/send_reminder_notification.txt b/commercialoperator/components/compliances/templates/commercialoperator/emails/send_reminder_notification.txt deleted file mode 100755 index fc45e662c2..0000000000 --- a/commercialoperator/components/compliances/templates/commercialoperator/emails/send_reminder_notification.txt +++ /dev/null @@ -1,14 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.txt' %} - -{% block content %} - Please be aware that the following is overdue: - {{ compliance.reference }} - {{compliance.requirement.requirement}} - - To complete the licence requirement please login to your account here. - - It is a condition of your licence that you complete all requirements. Failure to do so may result in cancellation or suspension of the commercial operations licence. - - If you have any queries please contact a licensing officer on {{settings.DEP_PHONE}}, or email {{settings.SUPPORT_EMAIL}} - - -{% endblock %} diff --git a/commercialoperator/components/compliances/templates/commercialoperator/emails/send_submit_notification.html b/commercialoperator/components/compliances/templates/commercialoperator/emails/send_submit_notification.html deleted file mode 100755 index 149041f5fd..0000000000 --- a/commercialoperator/components/compliances/templates/commercialoperator/emails/send_submit_notification.html +++ /dev/null @@ -1,12 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} - The Compliance {{ compliance.reference }} has been submitted and can be assessed. - -

- You can access this Compliance using the following link: -

- Access Compliance - - -{% endblock %} diff --git a/commercialoperator/components/compliances/templates/commercialoperator/emails/send_submit_notification.txt b/commercialoperator/components/compliances/templates/commercialoperator/emails/send_submit_notification.txt deleted file mode 100755 index 6fe53e9ece..0000000000 --- a/commercialoperator/components/compliances/templates/commercialoperator/emails/send_submit_notification.txt +++ /dev/null @@ -1,12 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.txt' %} - -{% block content %} - The Compliance {{ Compliance.reference }} has been submitted and can be assessed. - -

- You can access this Compliance using the following link: -

- {{url}} - - -{% endblock %} diff --git a/commercialoperator/components/compliances/utils.py b/commercialoperator/components/compliances/utils.py deleted file mode 100755 index e69de29bb2..0000000000 diff --git a/commercialoperator/components/emails/__init__.py b/commercialoperator/components/emails/__init__.py deleted file mode 100755 index e69de29bb2..0000000000 diff --git a/commercialoperator/components/emails/emails.py b/commercialoperator/components/emails/emails.py deleted file mode 100755 index dc0854a2ad..0000000000 --- a/commercialoperator/components/emails/emails.py +++ /dev/null @@ -1,91 +0,0 @@ -import logging -import mimetypes - -import six -from django.conf import settings -from django.core.mail import EmailMultiAlternatives -from django.core.urlresolvers import reverse -from django.template import loader, Template, Context -from django.utils.html import strip_tags - -from ledger.accounts.models import Document - -logger = logging.getLogger('log') - - -def _render(template, context): - if isinstance(context, dict): - context = Context(context) - context.update({'settings': settings}) - if isinstance(template, six.string_types): - template = Template(template) - return template.render(context) - - -def host_reverse(name, args=None, kwargs=None): - return "{}{}".format(settings.DEFAULT_HOST, reverse(name, args=args, kwargs=kwargs)) - - -class TemplateEmailBase(object): - subject = '' - html_template = 'commercialoperator/emails/base_email.html' - # txt_template can be None, in this case a 'tag-stripped' version of the html will be sent. (see send) - txt_template = 'commercialoperator/emails/base-email.txt' - - def send_to_user(self, user, context=None): - return self.send(user.email, context=context) - - def send(self, to_addresses, from_address=None, context=None, attachments=None, cc=None, bcc=None): - """ - Send an email using EmailMultiAlternatives with text and html. - :param to_addresses: a string or a list of addresses - :param from_address: if None the settings.DEFAULT_FROM_EMAIL is used - :param context: a dictionary or a Context object used for rendering the templates. - :param attachments: a list of (filepath, content, mimetype) triples - (see https://docs.djangoproject.com/en/1.9/topics/email/) - or Documents - :param bcc: - :param cc: - :return: - """ - # The next line will throw a TemplateDoesNotExist if html template cannot be found - html_template = loader.get_template(self.html_template) - # render html - html_body = _render(html_template, context) - if self.txt_template is not None: - txt_template = loader.get_template(self.txt_template) - txt_body = _render(txt_template, context) - else: - txt_body = strip_tags(html_body) - - # build message - if isinstance(to_addresses, six.string_types): - to_addresses = [to_addresses] - if attachments is None: - attachments = [] - if attachments is not None and not isinstance(attachments, list): - attachments = list(attachments) - - if attachments is None: - attachments = [] - - # Convert Documents to (filename, content, mime) attachment - _attachments = [] - for attachment in attachments: - if isinstance(attachment, Document): - filename = str(attachment) - content = attachment.file.read() - mime = mimetypes.guess_type(attachment.filename)[0] - _attachments.append((filename, content, mime)) - else: - _attachments.append(attachment) - msg = EmailMultiAlternatives(self.subject, txt_body, from_email=from_address, to=to_addresses, - attachments=_attachments, cc=cc, bcc=bcc) - msg.attach_alternative(html_body, 'text/html') - try: - if not settings.DISABLE_EMAIL: - msg.send(fail_silently=False) - return msg - except Exception as e: - logger.exception("Error while sending email to {}: {}".format(to_addresses, e)) - return None diff --git a/commercialoperator/components/emails/templates/commercialoperator/emails/base_email.html b/commercialoperator/components/emails/templates/commercialoperator/emails/base_email.html deleted file mode 100755 index 685b57bfc0..0000000000 --- a/commercialoperator/components/emails/templates/commercialoperator/emails/base_email.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - {% block greetings %} -

- Dear Sir/Madam, -

- {% endblock %} - {% block content %} - {% endblock %} - {% block signature %} -

- Regards, -

-

-

- {{settings.BRANCH_NAME}}
- {{settings.DEP_NAME}}
- Phone: {{ settings.DEP_PHONE_SUPPORT }}
- Address: {{ settings.DEP_ADDRESS}}
- -

- {% endblock %} - {% block reply_statement %} -

-

-

- - - - Please do not reply directly to this email. Should you need to contact the {{ settings.BRANCH_NAME}}, - please send emails to {{ settings.SUPPORT_EMAIL }} or call {{ settings.DEP_PHONE_SUPPORT }}. - -

- - - {% endblock %} - - diff --git a/commercialoperator/components/emails/templates/commercialoperator/emails/base_email.txt b/commercialoperator/components/emails/templates/commercialoperator/emails/base_email.txt deleted file mode 100755 index fd0f8a0ef2..0000000000 --- a/commercialoperator/components/emails/templates/commercialoperator/emails/base_email.txt +++ /dev/null @@ -1,21 +0,0 @@ -{% block greetings %} -Dear Sir/Madam, -{% endblock %} - -{% block content %} -{% endblock %} - -{% block signature %} -Regards, -{{settings.BRANCH_NAME}} -{{settings.DEP_NAME}} -Phone: {{ settings.DEP_PHONE_SUPPORT }} -Address: {{ settings.DEP_ADDRESS}} -{% endblock %} - - - -{% block reply_statement %} -Please do not reply directly to this email. Should you need to contact the {{ settings.BRANCH_NAME}}, please send emails to {{ settings.SUPPORT_EMAIL }} or call {{ settings.DEP_PHONE_SUPPORT }}. -{% endblock %} - diff --git a/commercialoperator/components/main/__init__.py b/commercialoperator/components/main/__init__.py deleted file mode 100755 index e69de29bb2..0000000000 diff --git a/commercialoperator/components/main/api.py b/commercialoperator/components/main/api.py deleted file mode 100755 index 25ead9604e..0000000000 --- a/commercialoperator/components/main/api.py +++ /dev/null @@ -1,318 +0,0 @@ -import traceback -from django.http import Http404, HttpResponse, HttpResponseRedirect, JsonResponse -from django.conf import settings -from django.db import transaction -from wsgiref.util import FileWrapper -from rest_framework import viewsets, serializers, status, generics, views -from rest_framework.decorators import detail_route, list_route, renderer_classes, parser_classes -from rest_framework.response import Response -from rest_framework.renderers import JSONRenderer -from rest_framework.permissions import IsAuthenticated, AllowAny, IsAdminUser, BasePermission -from rest_framework.pagination import PageNumberPagination -from django.urls import reverse -from commercialoperator.components.main.models import Region, District, Tenure, ApplicationType, ActivityMatrix, AccessType, Park, Trail, ActivityCategory, Activity, RequiredDocument, Question, GlobalSettings -from commercialoperator.components.main.serializers import RegionSerializer, DistrictSerializer, TenureSerializer, ApplicationTypeSerializer, ActivityMatrixSerializer, AccessTypeSerializer, ParkSerializer, ParkFilterSerializer, TrailSerializer, ActivitySerializer, ActivityCategorySerializer, RequiredDocumentSerializer, QuestionSerializer, GlobalSettingsSerializer, OracleSerializer, BookingSettlementReportSerializer, LandActivityTabSerializer, MarineActivityTabSerializer -from django.core.exceptions import ValidationError -from django.db.models import Q -from commercialoperator.components.proposals.models import Proposal -from commercialoperator.components.proposals.serializers import ProposalSerializer -from commercialoperator.components.bookings.utils import oracle_integration -from commercialoperator.components.bookings import reports -from ledger.checkout.utils import create_basket_session, create_checkout_session, place_order_submission, get_cookie_basket -from collections import namedtuple -import json -from decimal import Decimal - -import logging -logger = logging.getLogger('payment_checkout') - - -class DistrictViewSet(viewsets.ReadOnlyModelViewSet): - queryset = District.objects.all().order_by('id') - serializer_class = DistrictSerializer - - -class RegionViewSet(viewsets.ReadOnlyModelViewSet): - queryset = Region.objects.all().order_by('id') - serializer_class = RegionSerializer - - -class ActivityMatrixViewSet(viewsets.ReadOnlyModelViewSet): - #queryset = ActivityMatrix.objects.all().order_by('id') - queryset = ActivityMatrix.objects.none() - serializer_class = ActivityMatrixSerializer - - def get_queryset(self): - user = self.request.user - if user.is_authenticated(): - return [ActivityMatrix.objects.filter(name='Commercial Operator').order_by('-version').first()] - return ActivityMatrix.objects.none() - - -class TenureViewSet(viewsets.ReadOnlyModelViewSet): - queryset = Tenure.objects.all().order_by('order') - serializer_class = TenureSerializer - - -class ApplicationTypeViewSet(viewsets.ReadOnlyModelViewSet): - #queryset = ApplicationType.objects.all().order_by('order') - queryset = ApplicationType.objects.none() - serializer_class = ApplicationTypeSerializer - - def get_queryset(self): - return ApplicationType.objects.order_by('order').filter(visible=True) - - -class AccessTypeViewSet(viewsets.ReadOnlyModelViewSet): - queryset = AccessType.objects.all().order_by('id') - serializer_class = AccessTypeSerializer - - -class ParkFilterViewSet(viewsets.ReadOnlyModelViewSet): - queryset = Park.objects.all().order_by('id') - serializer_class = ParkFilterSerializer - - -class GlobalSettingsViewSet(viewsets.ReadOnlyModelViewSet): - queryset = GlobalSettings.objects.all().order_by('id') - serializer_class = GlobalSettingsSerializer - -class LandActivityTabViewSet(viewsets.ReadOnlyModelViewSet): - """ - A simple ViewSet for listing the various serialized viewsets in a single container - """ - def list(self, request): - #Container = namedtuple('ActivityLandTab', ('access_types', 'activity_types', 'regions')) - Container = namedtuple('ActivityLandTab', ('access_types', 'land_activity_types', 'marine_activity_types', 'trails', 'marine_activities', 'land_required_documents', 'regions')) - container = Container( - access_types=AccessType.objects.all().order_by('id'), - land_activity_types=Activity.objects.filter(activity_category__activity_type='land').order_by('id'), - marine_activity_types=Activity.objects.filter(activity_category__activity_type='marine').order_by('id'), - trails=Trail.objects.all().order_by('id'), - marine_activities=ActivityCategory.objects.filter(activity_type='marine').order_by('id'), - land_required_documents=RequiredDocument.objects.filter().order_by('id'), - regions=Region.objects.all().order_by('id'), - ) - serializer = LandActivityTabSerializer(container) - return Response(serializer.data) - - -class MarineActivityTabViewSet(viewsets.ReadOnlyModelViewSet): - """ - A simple ViewSet for listing the various serialized viewsets in a single container - """ - def list(self, request): - #Container = namedtuple('ActivityLandTab', ('access_types', 'activity_types', 'regions')) - Container = namedtuple('ActivityMarineTab', ('marine_activities', 'marine_parks', 'required_documents')) - container = Container( - #marine_activity_types=Activity.objects.filter(activity_category__activity_type='marine').order_by('id'), - marine_activities=ActivityCategory.objects.filter(activity_type='marine').order_by('id'), - #marine_parks=ActivityCategory.objects.filter(activity_type='marine').order_by('id'), - marine_parks=Park.objects.filter(park_type='marine').order_by('id'), - required_documents=RequiredDocument.objects.filter().order_by('id'), - ) - serializer = MarineActivityTabSerializer(container) - return Response(serializer.data) - - -class ParkViewSet(viewsets.ReadOnlyModelViewSet): - queryset = Park.objects.all().order_by('id') - serializer_class = ParkSerializer - - @list_route(methods=['GET',]) - def filter_list(self, request, *args, **kwargs): - serializer = ParkFilterSerializer(self.get_queryset(),context={'request':request}, many=True) - return Response(serializer.data) - - @list_route(methods=['GET',]) - def marine_parks(self, request, *args, **kwargs): - qs = self.get_queryset().filter(park_type='marine') - serializer = ParkSerializer(qs,context={'request':request}, many=True) - return Response(serializer.data) - - @detail_route(methods=['GET',]) - def allowed_activities(self, request, *args, **kwargs): - instance = self.get_object() - qs = instance.allowed_activities.all() - serializer = ActivitySerializer(qs,context={'request':request}, many=True) - #serializer = ActivitySerializer(qs) - return Response(serializer.data) - - @detail_route(methods=['GET',]) - def allowed_access(self, request, *args, **kwargs): - instance = self.get_object() - qs = instance.allowed_access.all() - serializer = AccessTypeSerializer(qs,context={'request':request}, many=True) - #serializer = ActivitySerializer(qs) - return Response(serializer.data) - - -class TrailViewSet(viewsets.ReadOnlyModelViewSet): - queryset = Trail.objects.all().order_by('id') - serializer_class = TrailSerializer - - @detail_route(methods=['GET',]) - def allowed_activities(self, request, *args, **kwargs): - instance = self.get_object() - qs = instance.allowed_activities.all() - serializer = ActivitySerializer(qs,context={'request':request}, many=True) - #serializer = ActivitySerializer(qs) - return Response(serializer.data) - - -class LandActivitiesViewSet(viewsets.ReadOnlyModelViewSet): - queryset = Activity.objects.none() - serializer_class = ActivitySerializer - - def get_queryset(self): - categories=ActivityCategory.objects.filter(activity_type='land') - activities=Activity.objects.filter(Q(activity_category__in = categories)& Q(visible=True)) - return activities - - -class MarineActivitiesViewSet(viewsets.ReadOnlyModelViewSet): - queryset = ActivityCategory.objects.none() - serializer_class = ActivityCategorySerializer - - def get_queryset(self): - categories=ActivityCategory.objects.filter(activity_type='marine') - return categories - - -class RequiredDocumentViewSet(viewsets.ReadOnlyModelViewSet): - queryset = RequiredDocument.objects.all() - serializer_class = RequiredDocumentSerializer - - # def get_queryset(self): - # categories=ActivityCategory.objects.filter(activity_type='marine') - # return categories - - -class QuestionViewSet(viewsets.ReadOnlyModelViewSet): - queryset = Question.objects.all() - serializer_class = QuestionSerializer - - -class PaymentViewSet(viewsets.ModelViewSet): - #queryset = Proposal.objects.all() - queryset = Proposal.objects.none() - #serializer_class = ProposalSerializer - serializer_class = ProposalSerializer - lookup_field = 'id' - - def create(self, request, *args, **kwargs): - response = super(PaymentViewSet, self).create(request, *args, **kwargs) - # here may be placed additional operations for - # extracting id of the object and using reverse() - fallback_url = request.build_absolute_uri('/') - return HttpResponseRedirect(redirect_to=fallback_url + '/success/') - - @detail_route(methods=['POST',]) - @renderer_classes((JSONRenderer,)) - def park_payment(self, request, *args, **kwargs): - - try: - with transaction.atomic(): - #instance = self.get_object() - proposal = Proposal.objects.get(id=kwargs['id']) - lines = self.create_lines(request) - response = self.checkout(request, proposal, lines, invoice_text='Some invoice text') - - return response - - #data = [dict(key='My Response')] - #return Response(data) - - #return Response(serializer.data) - - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - -class BookingSettlementReportView(views.APIView): - renderer_classes = (JSONRenderer,) - - def get(self,request,format=None): - try: - http_status = status.HTTP_200_OK - #parse and validate data - report = None - data = { - "date":request.GET.get('date'), - } - serializer = BookingSettlementReportSerializer(data=data) - serializer.is_valid(raise_exception=True) - filename = 'Booking Settlement Report-{}'.format(str(serializer.validated_data['date'])) - # Generate Report - report = reports.booking_bpoint_settlement_report(serializer.validated_data['date']) - if report: - response = HttpResponse(FileWrapper(report), content_type='text/csv') - response['Content-Disposition'] = 'attachment; filename="{}.csv"'.format(filename) - return response - else: - raise serializers.ValidationError('No report was generated.') - except serializers.ValidationError: - raise - except Exception as e: - traceback.print_exc() - - -#class BookingReportView(views.APIView): -# renderer_classes = (JSONRenderer,) -# -# def get(self,request,format=None): -# try: -# http_status = status.HTTP_200_OK -# #parse and validate data -# report = None -# data = { -# "date":request.GET.get('date'), -# } -# serializer = BookingSettlementReportSerializer(data=data) -# serializer.is_valid(raise_exception=True) -# filename = 'Booking Report-{}'.format(str(serializer.validated_data['date'])) -# # Generate Report -# report = reports.bookings_report(serializer.validated_data['date']) -# if report: -# response = HttpResponse(FileWrapper(report), content_type='text/csv') -# response['Content-Disposition'] = 'attachment; filename="{}.csv"'.format(filename) -# return response -# else: -# raise serializers.ValidationError('No report was generated.') -# except serializers.ValidationError: -# raise -# except Exception as e: -# traceback.print_exc() - - -class OracleJob(views.APIView): - renderer_classes = [JSONRenderer,] - def get(self, request, format=None): - try: - data = { - "date":request.GET.get("date"), - "override": request.GET.get("override") - } - serializer = OracleSerializer(data=data) - serializer.is_valid(raise_exception=True) - oracle_integration(serializer.validated_data['date'].strftime('%Y-%m-%d'),serializer.validated_data['override']) - data = {'successful':True} - return Response(data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e[0])) - - - diff --git a/commercialoperator/components/main/models.py b/commercialoperator/components/main/models.py deleted file mode 100755 index e5765ba01d..0000000000 --- a/commercialoperator/components/main/models.py +++ /dev/null @@ -1,459 +0,0 @@ -from __future__ import unicode_literals -import os - -from django.db import models -from django.dispatch import receiver -from django.db.models.signals import pre_delete -from django.utils.encoding import python_2_unicode_compatible -from django.core.exceptions import ValidationError -from ledger.accounts.models import EmailUser, Document, RevisionedMixin -from django.contrib.postgres.fields.jsonb import JSONField - - -@python_2_unicode_compatible -class Region(models.Model): - name = models.CharField(max_length=200, unique=True) - forest_region = models.BooleanField(default=False) - - class Meta: - ordering = ['name'] - app_label = 'commercialoperator' - - def __str__(self): - return self.name - - # @property - # def districts(self): - # return District.objects.filter(region=self) - - -@python_2_unicode_compatible -class District(models.Model): - region = models.ForeignKey(Region, related_name='districts') - name = models.CharField(max_length=200, unique=True) - code = models.CharField(max_length=3) - archive_date = models.DateField(null=True, blank=True) - - class Meta: - ordering = ['name'] - app_label = 'commercialoperator' - - def __str__(self): - return self.name - - @property - def parks(self): - return Parks.objects.filter(district=self) - - @property - def land_parks(self): - return Park.objects.filter(district=self, park_type='land') - - @property - def marine_parks(self): - return Park.objects.filter(district=self, park_type='marine') - - - -@python_2_unicode_compatible -class AccessType(models.Model): - name = models.CharField(max_length=200, blank=True) - visible = models.BooleanField(default=True) - - class Meta: - ordering = ['name'] - app_label = 'commercialoperator' - - def __str__(self): - return self.name - -@python_2_unicode_compatible -class ActivityType(models.Model): - ACTIVITY_TYPE_CHOICES = ( - ('land', 'Land'), - ('marine', 'Marine'), - ('Film', 'Film'), - ) - type_name = models.CharField('Activity Type', max_length=40, choices=ACTIVITY_TYPE_CHOICES, - default=ACTIVITY_TYPE_CHOICES[0][0]) - visible = models.BooleanField(default=True) - - class Meta: - ordering = ['type_name'] - app_label = 'commercialoperator' - - def __str__(self): - return self.type_name - -@python_2_unicode_compatible -class ActivityCategory(models.Model): - ACTIVITY_TYPE_CHOICES = ( - ('land', 'Land'), - ('marine', 'Marine'), - ('Film', 'Film'), - ) - name = models.CharField(max_length=200, blank=True) - visible = models.BooleanField(default=True) - activity_type = models.CharField('Activity Type', max_length=40, choices=ACTIVITY_TYPE_CHOICES, - default=ACTIVITY_TYPE_CHOICES[0][0]) - - class Meta: - ordering = ['name'] - app_label = 'commercialoperator' - verbose_name_plural= 'Activity Categories' - - def __str__(self): - return self.name - -@python_2_unicode_compatible -class Activity(models.Model): - name = models.CharField(max_length=200, blank=True) - visible = models.BooleanField(default=True) - activity_category = models.ForeignKey(ActivityCategory, related_name='activities') - - class Meta: - ordering = ['name'] - verbose_name_plural = "Activities" - app_label = 'commercialoperator' - - def __str__(self): - return self.name - - -@python_2_unicode_compatible -class Park(models.Model): - PARK_TYPE_CHOICES = ( - ('land', 'Land'), - ('marine', 'Marine'), - ('Film', 'Film'), - ) - district = models.ForeignKey(District, related_name='parks') - name = models.CharField(max_length=200, unique=True) - code = models.CharField(max_length=10, blank=True) - park_type = models.CharField('Park Type', max_length=40, choices=PARK_TYPE_CHOICES, - default=PARK_TYPE_CHOICES[0][0]) - allowed_activities = models.ManyToManyField(Activity, blank=True) - allowed_access = models.ManyToManyField(AccessType, blank=True) - - adult_price = models.DecimalField('Adult (price per adult)', max_digits=5, decimal_places=2) - child_price = models.DecimalField('Child (price per child)', max_digits=5, decimal_places=2) - #senior = models.DecimalField('Senior (price per senior)', max_digits=5, decimal_places=2) - oracle_code = models.CharField(max_length=50) - - # editable=False --> related to invoice PDF generation, currently GST is computed assuming GST is payable for ALL parks. - # Must fix invoice calc. GST per park in pdf line_items, for net GST if editable is to be set to True - is_gst_exempt = models.BooleanField(default=False, editable=False) - - class Meta: - ordering = ['name'] - app_label = 'commercialoperator' - #unique_together = ('id', 'proposal',) - - def __str__(self): - return self.name - - @property - def allowed_activities_ids(self): - return [i.id for i in self.allowed_activities.all()] - - @property - def allowed_access_ids(self): - return [i.id for i in self.allowed_access.all()] - - @property - def zone_ids(self): - return [i.id for i in self.zones.all()] - - -@python_2_unicode_compatible -class Zone(models.Model): - name = models.CharField(max_length=200, blank=True) - visible = models.BooleanField(default=True) - park = models.ForeignKey(Park, related_name='zones') - allowed_activities = models.ManyToManyField(Activity, blank=True) - - - class Meta: - ordering = ['name'] - app_label = 'commercialoperator' - - def __str__(self): - return self.name - - @property - def allowed_activities_ids(self): - return [i.id for i in self.allowed_activities.all()] - - -@python_2_unicode_compatible -class Trail(models.Model): - name = models.CharField(max_length=200, unique=True) - code = models.CharField(max_length=10, blank=True) - allowed_activities = models.ManyToManyField(Activity, blank=True) - - class Meta: - ordering = ['name'] - app_label = 'commercialoperator' - #unique_together = ('id', 'proposal',) - - def __str__(self): - return self.name - - @property - def section_ids(self): - return [i.id for i in self.sections.all()] - - @property - def allowed_activities_ids(self): - return [i.id for i in self.allowed_activities.all()] - -@python_2_unicode_compatible -class Section(models.Model): - name = models.CharField(max_length=200, blank=True) - visible = models.BooleanField(default=True) - trail = models.ForeignKey(Trail, related_name='sections') - doc_url= models.CharField('Document URL',max_length=255, blank=True) - - class Meta: - ordering = ['name'] - app_label = 'commercialoperator' - - def __str__(self): - return self.name - -@python_2_unicode_compatible -class RequiredDocument(models.Model): - question = models.TextField(blank=False) - activity = models.ForeignKey(Activity,null=True, blank=True) - park= models.ForeignKey(Park,null=True, blank=True) - - class Meta: - app_label = 'commercialoperator' - - def __str__(self): - return self.question - -@python_2_unicode_compatible -class ApplicationType(models.Model): - """ - for park in Park.objects.all().order_by('id'): - ParkPrice.objects.create(park=park, adult=10.0, child=7.50, senior=5.00) - """ - name = models.CharField(max_length=64, unique=True) - order = models.PositiveSmallIntegerField(default=0) - visible = models.BooleanField(default=True) - - max_renewals = models.PositiveSmallIntegerField('Maximum number of times an Approval can be renewed', null=True, blank=True) - max_renewal_period = models.PositiveSmallIntegerField('Maximum period of each Approval renewal (Years)', null=True, blank=True) - application_fee = models.DecimalField(max_digits=6, decimal_places=2) - licence_fee_2mth = models.DecimalField('Licence Fee (2 Months)', max_digits=6, decimal_places=2) - licence_fee_1yr = models.DecimalField('Licence Fee (1 Year)', max_digits=6, decimal_places=2) - oracle_code_application = models.CharField(max_length=50) - oracle_code_licence = models.CharField(max_length=50) - is_gst_exempt = models.BooleanField(default=True) - - class Meta: - ordering = ['order', 'name'] - app_label = 'commercialoperator' - - def __str__(self): - return self.name - -@python_2_unicode_compatible -class ActivityMatrix(models.Model): - name = models.CharField(verbose_name='Activity matrix name', max_length=24, choices=[('Commercial Operator', u'Commercial Operator')], default='Commercial Operator') - description = models.CharField(max_length=256, blank=True, null=True) - schema = JSONField() - replaced_by = models.ForeignKey('self', on_delete=models.PROTECT, blank=True, null=True) - version = models.SmallIntegerField(default=1, blank=False, null=False) - ordered = models.BooleanField('Activities Ordered Alphabetically', default=False) - - class Meta: - app_label = 'commercialoperator' - unique_together = ('name', 'version') - verbose_name_plural = "Activity matrix" - - def __str__(self): - return '{} - v{}'.format(self.name, self.version) - - -@python_2_unicode_compatible -class Tenure(models.Model): - name = models.CharField(max_length=255, unique=True) - order = models.PositiveSmallIntegerField(default=0) - application_type = models.ForeignKey(ApplicationType, related_name='tenure_app_types') - - class Meta: - ordering = ['order', 'name'] - app_label = 'commercialoperator' - - def __str__(self): - return '{}: {}'.format(self.name, self.application_type) - -@python_2_unicode_compatible -class Question(models.Model): - CORRECT_ANSWER_CHOICES = ( - ('answer_one', 'Answer one'), ('answer_two', 'Answer two'), ('answer_three', 'Answer three'), - ('answer_four', 'Answer four')) - question_text = models.TextField(blank=False) - answer_one = models.CharField(max_length=200, blank=True) - answer_two = models.CharField(max_length=200, blank=True) - answer_three = models.CharField(max_length=200, blank=True) - answer_four = models.CharField(max_length=200, blank=True) - #answer_five = models.CharField(max_length=200, blank=True) - correct_answer = models.CharField('Correct Answer', max_length=40, choices=CORRECT_ANSWER_CHOICES, - default=CORRECT_ANSWER_CHOICES[0][0]) - - - - class Meta: - #ordering = ['name'] - app_label = 'commercialoperator' - - def __str__(self): - return self.question_text - - @property - def correct_answer_value(self): - return getattr(self, self.correct_answer) - - -@python_2_unicode_compatible -class UserAction(models.Model): - who = models.ForeignKey(EmailUser, null=False, blank=False) - when = models.DateTimeField(null=False, blank=False, auto_now_add=True) - what = models.TextField(blank=False) - - def __str__(self): - return "{what} ({who} at {when})".format( - what=self.what, - who=self.who, - when=self.when - ) - - class Meta: - abstract = True - app_label = 'commercialoperator' - - -class CommunicationsLogEntry(models.Model): - TYPE_CHOICES = [ - ('email', 'Email'), - ('phone', 'Phone Call'), - ('mail', 'Mail'), - ('person', 'In Person'), - ('onhold', 'On Hold'), - ('onhold_remove', 'Remove On Hold'), - ('with_qaofficer', 'With QA Officer'), - ('with_qaofficer_completed', 'QA Officer Completed'), - ] - DEFAULT_TYPE = TYPE_CHOICES[0][0] - - #to = models.CharField(max_length=200, blank=True, verbose_name="To") - to = models.TextField(blank=True, verbose_name="To") - fromm = models.CharField(max_length=200, blank=True, verbose_name="From") - #cc = models.CharField(max_length=200, blank=True, verbose_name="cc") - cc = models.TextField(blank=True, verbose_name="cc") - - type = models.CharField(max_length=35, choices=TYPE_CHOICES, default=DEFAULT_TYPE) - reference = models.CharField(max_length=100, blank=True) - subject = models.CharField(max_length=200, blank=True, verbose_name="Subject / Description") - text = models.TextField(blank=True) - - customer = models.ForeignKey(EmailUser, null=True, related_name='+') - staff = models.ForeignKey(EmailUser, null=True, related_name='+') - - created = models.DateTimeField(auto_now_add=True, null=False, blank=False) - - class Meta: - app_label = 'commercialoperator' - - -@python_2_unicode_compatible -class Document(models.Model): - name = models.CharField(max_length=100, blank=True, - verbose_name='name', help_text='') - description = models.TextField(blank=True, - verbose_name='description', help_text='') - uploaded_date = models.DateTimeField(auto_now_add=True) - - class Meta: - app_label = 'commercialoperator' - abstract = True - - @property - def path(self): - #return self.file.path - #return self._file.path - #comment above line to fix the error "The '_file' attribute has no file associated with it." when adding comms log entry. - if self._file: - return self._file.path - else: - return '' - - @property - def filename(self): - return os.path.basename(self.path) - - def __str__(self): - return self.name or self.filename - -class GlobalSettings(models.Model): - keys = ( - ('credit_facility_link', 'Credit Facility Link'), - ('deed_poll', 'Deed poll'), - ('online_training_document', 'Online Training Document'), - - ) - key = models.CharField(max_length=255, choices=keys, blank=False, null=False,) - value = models.CharField(max_length=255) - - class Meta: - app_label = 'commercialoperator' - verbose_name_plural = "Global Settings" - - -@python_2_unicode_compatible -class SystemMaintenance(models.Model): - name = models.CharField(max_length=100) - description = models.TextField() - start_date = models.DateTimeField() - end_date = models.DateTimeField() - - def duration(self): - """ Duration of system maintenance (in mins) """ - return int( (self.end_date - self.start_date).total_seconds()/60.) if self.end_date and self.start_date else '' - #return (datetime.now(tz=tz) - self.start_date).total_seconds()/60. - duration.short_description = 'Duration (mins)' - - class Meta: - app_label = 'commercialoperator' - verbose_name_plural = "System maintenance" - - def __str__(self): - return 'System Maintenance: {} ({}) - starting {}, ending {}'.format(self.name, self.description, self.start_date, self.end_date) - -import reversion -reversion.register(Region, follow=['districts']) -reversion.register(District, follow=['parks']) -#reversion.register(AccessType) -reversion.register(AccessType, follow=['park_set', 'proposalparkaccess_set', 'vehicles']) -reversion.register(ActivityType) -reversion.register(ActivityCategory, follow=['activities']) -#reversion.register(Activity, follow=['park_set', 'zone_set', 'trail_set', 'requireddocument_set']) -reversion.register(Activity, follow=['park_set', 'zone_set', 'trail_set', 'requireddocument_set', 'proposalparkactivity_set','proposalparkzoneactivity_set', 'proposaltrailsectionactivity_set']) -#reversion.register(Park, follow=['zones', 'requireddocument_set', 'proposals', 'park_entries', 'bookings']) -reversion.register(Park, follow=['zones', 'requireddocument_set', 'proposals']) -reversion.register(Zone, follow=['proposal_zones']) -reversion.register(Trail, follow=['sections', 'proposals']) -reversion.register(Section, follow=['proposal_trails']) -reversion.register(RequiredDocument) -reversion.register(ApplicationType, follow=['tenure_app_types', 'helppage_set']) -reversion.register(ActivityMatrix) -reversion.register(Tenure) -reversion.register(Question) -reversion.register(UserAction) -reversion.register(CommunicationsLogEntry) -reversion.register(Document) -reversion.register(SystemMaintenance) - diff --git a/commercialoperator/components/main/serializers.py b/commercialoperator/components/main/serializers.py deleted file mode 100755 index e3f086501a..0000000000 --- a/commercialoperator/components/main/serializers.py +++ /dev/null @@ -1,348 +0,0 @@ -from rest_framework import serializers -from commercialoperator.components.main.models import CommunicationsLogEntry, Region, District, Tenure, ApplicationType, ActivityMatrix, AccessType, Park, Trail, Activity, ActivityCategory, Section, Zone, RequiredDocument, Question, GlobalSettings #, ParkPrice -from commercialoperator.components.proposals.models import ProposalParkActivity -from ledger.accounts.models import EmailUser -#from commercialoperator.components.proposals.serializers import ProposalTypeSerializer - -class CommunicationLogEntrySerializer(serializers.ModelSerializer): - customer = serializers.PrimaryKeyRelatedField(queryset=EmailUser.objects.all(),required=False) - documents = serializers.SerializerMethodField() - class Meta: - model = CommunicationsLogEntry - fields = ( - 'id', - 'customer', - 'to', - 'fromm', - 'cc', - 'type', - 'reference', - 'subject' - 'text', - 'created', - 'staff', - 'proposal' - 'documents' - ) - - def get_documents(self,obj): - return [[d.name,d._file.url] for d in obj.documents.all()] - - -class SectionSerializer(serializers.ModelSerializer): - class Meta: - model = Section - fields = ('id', 'name', 'visible', 'doc_url') - -class ActivitySerializer(serializers.ModelSerializer): - #node_id = serializers.SerializerMethodField() - last_leaf = serializers.SerializerMethodField() - node_id = serializers.SerializerMethodField() - class Meta: - model = Activity - fields = ('id', 'name', 'last_leaf', 'node_id') - - #def get_node_id(self, obj): - # return '{}_{}_id-{}'.format(obj.activity_category.name.replace(' ',''), obj.name.replace(' ',''), obj.id) - - def get_last_leaf(self, obj): - return True - - def get_node_id(self, obj): - """ Pulled from parent (out serializer) --> ZoneSerializer - """ - return '{}_{}'.format(self.context.get('parent_id'), obj.id) if self.context.get('parent_id') else obj.id - - -class ZoneSerializer(serializers.ModelSerializer): - label = serializers.SerializerMethodField() - park_id = serializers.SerializerMethodField() - can_edit = serializers.SerializerMethodField() - last_leaf = serializers.SerializerMethodField() - last_leaf = serializers.SerializerMethodField() - allowed_zone_activities=ActivitySerializer(many=True, source='allowed_activities') - #children=ActivitySerializer(many=True, source='allowed_activities', context={'request': self.context.get('request'), 'customer_id': obj.id}) - #children=ActivitySerializer(many=True, source='allowed_activities') - #children = serializers.SerializerMethodField() - - class Meta: - model = Zone - #fields = ('id', 'name', 'can_edit', 'last_leaf','visible', 'children') - fields = ('id', 'name', 'label', 'park_id', 'can_edit', 'last_leaf','visible', 'allowed_zone_activities') - - def get_can_edit(self, obj): - return True - - def get_last_leaf(self, obj): - return True - - def get_label(self, obj): - """ Pulled from parent (out serializer) --> ZoneSerializer - """ - return '{} - {}'.format(self.context.get('parent_name'), obj.name) if self.context.get('parent_id') else obj.name - - def get_park_id(self, obj): - """ Pulled from parent (out serializer) --> ZoneSerializer - """ - return self.context.get('parent_id') - - - -# def get_children(self, obj): -# """ The way ro push parent date to child level nested childen (ZoneSerializer --> ActivitySerializer) -# """ -# children = obj.allowed_activities -# serializer_context = {'request': self.context.get('request'), -# 'parent_id': obj.id} -# serializer = ActivitySerializer(children, many=True, context=serializer_context) -# return serializer.data - -class ParkFilterSerializer(serializers.ModelSerializer): - class Meta: - model = Park - fields=('id', 'name', 'park_type') - -class MarineParkSerializer(serializers.ModelSerializer): - can_edit = serializers.SerializerMethodField() - last_leaf = serializers.SerializerMethodField() - #zones=ZoneSerializer(many=True) - #children=ZoneSerializer(many=True, source='zones') - children = serializers.SerializerMethodField() - - class Meta: - model = Park - fields=('id', 'name', 'can_edit', 'last_leaf', 'code', 'park_type', 'allowed_activities', 'zone_ids', 'adult_price', 'child_price', 'oracle_code', 'children' ) - - def get_can_edit(self, obj): - return False - - def get_last_leaf(self, obj): - return False - - def get_children(self, obj): - """ The way ro push parent date to child level nested childen (ZoneSerializer --> ActivitySerializer) - """ - children = obj.zones - serializer_context = { - 'request': self.context.get('request'), - 'parent_id': obj.id, - 'parent_name': obj.name - } - serializer = ZoneSerializer(children, many=True, context=serializer_context) - return serializer.data - - - -class ParkSerializer(serializers.ModelSerializer): - can_edit = serializers.SerializerMethodField() - last_leaf = serializers.SerializerMethodField() - zones=ZoneSerializer(many=True) - #children=ZoneSerializer(many=True, source='zones') - - class Meta: - model = Park - fields=('id', 'name', 'can_edit', 'last_leaf', 'code', 'park_type', 'allowed_activities', 'zone_ids', 'adult_price', 'child_price', 'oracle_code', 'zones' ) - - def get_can_edit(self, obj): - #proposal = self.context['request'].GET.get('proposal') - #activities = ProposalParkActivity.objects.filter(proposal_park__park=obj.id, proposal_park__proposal=proposal) - #return True if activities else False - return True - - def get_last_leaf(self, obj): - return True - - -class DistrictSerializer(serializers.ModelSerializer): - land_parks = ParkSerializer(many=True) - marine_parks = ParkSerializer(many=True) - class Meta: - model = District - fields = ('id', 'name', 'code', 'land_parks', 'marine_parks') - -class RegionSerializer(serializers.ModelSerializer): - districts = DistrictSerializer(many=True) - class Meta: - model = Region - fields = ('id', 'name','forest_region', 'districts') - -#class ParkSerializer2(serializers.ModelSerializer): -# can_edit = serializers.SerializerMethodField() -# last_leaf = serializers.SerializerMethodField() -# -# class Meta: -# model = Park -# fields=('id', 'name', 'can_edit', 'last_leaf') -# -# def get_can_edit(self, obj): -# #proposal = self.context['request'].GET.get('proposal') -# #activities = ProposalParkActivity.objects.filter(proposal_park__park=obj.id, proposal_park__proposal=proposal) -# #return True if activities else False -# return True -# -# def get_last_leaf(self, obj): -# return True - -class DistrictSerializer2(serializers.ModelSerializer): - pk = serializers.SerializerMethodField() - last_leaf = serializers.SerializerMethodField() - is_disabled = serializers.SerializerMethodField() - #children = ParkSerializer2(many=True, read_only=True, source='land_parks') - children = ParkSerializer(many=True, read_only=True, source='land_parks') - - class Meta: - model = District - #fields = ('id', 'name', 'land_parks', 'marine_parks') - fields = ('pk', 'id', 'name', 'last_leaf', 'is_disabled', 'children') - - def get_pk(self, obj): - return obj.id - - def get_last_leaf(self, obj): - return False - - def get_is_disabled(self, obj): - return True if obj.parks.count()==0 else False - - -class RegionSerializer2(serializers.ModelSerializer): - pk = serializers.SerializerMethodField() - last_leaf = serializers.SerializerMethodField() - children = DistrictSerializer2(many=True, read_only=True, source='districts') - - class Meta: - model = Region - fields = ('pk', 'id', 'name', 'last_leaf', 'children') - - def get_pk(self, obj): - return obj.id - - def get_last_leaf(self, obj): - return False - - -class AccessTypeSerializer(serializers.ModelSerializer): - last_leaf = serializers.SerializerMethodField() - class Meta: - model = AccessType - fields = ('id', 'name', 'last_leaf', 'visible') - - def get_last_leaf(self, obj): - return True - - -class ActivityMatrixSerializer(serializers.ModelSerializer): - class Meta: - model = ActivityMatrix - fields = ('id', 'name', 'description', 'version', 'ordered', 'schema') - - -#class ActivitySerializer(serializers.ModelSerializer): -# class Meta: -# model = Activity -# #ordering = ('order', 'name') -# fields = ('id', 'name', 'application_type') - - -class TenureSerializer(serializers.ModelSerializer): - class Meta: - model = Tenure - fields = ('id', 'name', 'application_type') - - -class ApplicationTypeSerializer(serializers.ModelSerializer): - #regions = RegionSerializer(many=True) - #activity_app_types = ActivitySerializer(many=True) - #tenure_app_types = TenureSerializer(many=True) - class Meta: - model = ApplicationType - #fields = ('id', 'name', 'activity_app_types', 'tenure_app_types') - #fields = ('id', 'name', 'tenure_app_types') - fields = '__all__' - #extra_fields = ['pizzas'] - - -class GlobalSettingsSerializer(serializers.ModelSerializer): - class Meta: - model = GlobalSettings - fields = ('key', 'value') - - - -class RequiredDocumentSerializer(serializers.ModelSerializer): - class Meta: - model = RequiredDocument - fields = ('id', 'park','activity', 'question') - - -class ActivityCategorySerializer(serializers.ModelSerializer): - #activities = ActivitySerializer(many=True) - pk = serializers.SerializerMethodField() - children = serializers.SerializerMethodField() - #children = ActivitySerializer(many=True, source='activities') - - class Meta: - model = ActivityCategory - fields = ('pk', 'id', 'name','children') - #fields = ('pk', 'id', 'name','activities') - - def get_pk(self, obj): - return obj.id - - def get_children(self, obj): - """ The way ro push parent date to child level nested childen (ActivityCategorySerializer --> ActivitySerializer) - """ - children = obj.activities - serializer_context = {'request': self.context.get('request'), - 'parent_id': obj.id} - serializer = ActivitySerializer(children, many=True, context=serializer_context) - return serializer.data - - -class TrailSerializer(serializers.ModelSerializer): - can_edit = serializers.SerializerMethodField() - last_leaf = serializers.SerializerMethodField() - sections=SectionSerializer(many=True) - allowed_activities=ActivitySerializer(many=True) - class Meta: - model = Trail - fields = ('id', 'name', 'can_edit', 'last_leaf', 'code', 'section_ids', 'sections', 'allowed_activities') - - def get_can_edit(self, obj): - return True - - def get_last_leaf(self, obj): - return True - - -class QuestionSerializer(serializers.ModelSerializer): - class Meta: - model = Question - fields = ('id', 'question_text', 'answer_one', 'answer_two', 'answer_three', 'answer_four','correct_answer', 'correct_answer_value') - - -class LandActivityTabSerializer(serializers.Serializer): - land_parks = RegionSerializer2(many=True, read_only=True, source='regions') - access_types = AccessTypeSerializer(many=True, read_only=True) - land_activity_types = ActivitySerializer(many=True, read_only=True) - trails = TrailSerializer(many=True, read_only=True) - land_required_documents = RequiredDocumentSerializer(many=True, read_only=True) - #marine_activity_types = ActivitySerializer(many=True, read_only=True) - #marine_activities = ActivityCategorySerializer(many=True, read_only=True) - - -class MarineActivityTabSerializer(serializers.Serializer): - required_documents = RequiredDocumentSerializer(many=True, read_only=True) - marine_activities = ActivityCategorySerializer(many=True, read_only=True) - marine_parks = MarineParkSerializer(many=True, read_only=True) - - -class BookingSettlementReportSerializer(serializers.Serializer): - date = serializers.DateTimeField(input_formats=['%d/%m/%Y']) - - -class OracleSerializer(serializers.Serializer): - date = serializers.DateField(input_formats=['%d/%m/%Y','%Y-%m-%d']) - override = serializers.BooleanField(default=False) - - diff --git a/commercialoperator/components/main/utils.py b/commercialoperator/components/main/utils.py deleted file mode 100755 index 271c6fc75d..0000000000 --- a/commercialoperator/components/main/utils.py +++ /dev/null @@ -1,46 +0,0 @@ -import requests -import json -from datetime import timedelta, date -from django.conf import settings -from django.core.cache import cache - - -def retrieve_department_users(): - try: - res = requests.get('{}/api/users?minimal'.format(settings.CMS_URL), auth=(settings.LEDGER_USER,settings.LEDGER_PASS), verify=False) - res.raise_for_status() - cache.set('department_users',json.loads(res.content).get('objects'),10800) - except: - raise - -def get_department_user(email): - try: - res = requests.get('{}/api/users?email={}'.format(settings.CMS_URL,email), auth=(settings.LEDGER_USER,settings.LEDGER_PASS), verify=False) - res.raise_for_status() - data = json.loads(res.content).get('objects') - if len(data) > 0: - return data[0] - else: - return None - except: - raise - -#def add_business_days(from_date, number_of_days): -# """ given from_date and number_of_days, returns the next weekday date i.e. excludes Sat/Sun """ -# to_date = from_date -# while number_of_days: -# to_date += timedelta(1) -# if to_date.weekday() < 5: # i.e. is not saturday or sunday -# number_of_days -= 1 -# return to_date -# -#def get_next_weekday(from_date): -# """ given from_date and number_of_days, returns the next weekday date i.e. excludes Sat/Sun """ -# if from_date.weekday() == 5: # i.e. Sat -# from_date += timedelta(2) -# elif from_date.weekday() == 6: # i.e. Sun -# from_date += timedelta(1) -# -# return from_date - - diff --git a/commercialoperator/components/organisations/__init__.py b/commercialoperator/components/organisations/__init__.py deleted file mode 100755 index e69de29bb2..0000000000 diff --git a/commercialoperator/components/organisations/admin.py b/commercialoperator/components/organisations/admin.py deleted file mode 100755 index b40f027e51..0000000000 --- a/commercialoperator/components/organisations/admin.py +++ /dev/null @@ -1,33 +0,0 @@ -from django.contrib import admin -from ledger.accounts.models import EmailUser -from commercialoperator.components.organisations import models -from django.contrib.admin import actions -# Register your models here. - -@admin.register(models.Organisation) -class OrganisationAdmin(admin.ModelAdmin): - list_display = ['organisation','admin_pin_one', 'admin_pin_two', 'user_pin_one', 'user_pin_two'] - search_fields = ('organisation__name','admin_pin_one', 'admin_pin_two', 'user_pin_one', 'user_pin_two' ) - -@admin.register(models.OrganisationRequest) -class OrganisationRequestAdmin(admin.ModelAdmin): - list_display = ['name','requester', 'abn', 'status'] - -@admin.register(models.OrganisationAccessGroup) -class OrganisationAccessGroupAdmin(admin.ModelAdmin): - filter_horizontal = ('members',) - exclude = ('site',) - actions = None - - def formfield_for_manytomany(self, db_field, request, **kwargs): - if db_field.name == "members": - #kwargs["queryset"] = EmailUser.objects.filter(email__icontains='@dbca.wa.gov.au') - kwargs["queryset"] = EmailUser.objects.filter(is_staff=True) - return super(OrganisationAccessGroupAdmin, self).formfield_for_manytomany(db_field, request, **kwargs) - - def has_add_permission(self, request): - return True if models.OrganisationAccessGroup.objects.count() == 0 else False - - def has_delete_permission(self, request, obj=None): - return False - diff --git a/commercialoperator/components/organisations/api.py b/commercialoperator/components/organisations/api.py deleted file mode 100755 index 56fc51157f..0000000000 --- a/commercialoperator/components/organisations/api.py +++ /dev/null @@ -1,923 +0,0 @@ -import traceback -import base64 -import geojson -from six.moves.urllib.parse import urlparse -from wsgiref.util import FileWrapper -from django.db.models import Q, Min -from django.db import transaction -from django.http import HttpResponse -from django.core.files.base import ContentFile -from django.core.exceptions import ValidationError -from django.conf import settings -from django.contrib import messages -from django.views.decorators.http import require_http_methods -from django.views.decorators.csrf import csrf_exempt -from django.utils import timezone -from rest_framework import viewsets, serializers, status, generics, views -from rest_framework.decorators import detail_route, list_route,renderer_classes -from rest_framework.response import Response -from rest_framework.renderers import JSONRenderer -from rest_framework.permissions import IsAuthenticated, AllowAny, IsAdminUser, BasePermission -from rest_framework.pagination import PageNumberPagination -from datetime import datetime, timedelta -from collections import OrderedDict -from django.core.cache import cache -from ledger.accounts.models import EmailUser,OrganisationAddress -from ledger.address.models import Country -from datetime import datetime,timedelta, date -from commercialoperator.helpers import is_customer, is_internal -from commercialoperator.components.organisations.models import ( - Organisation, - OrganisationContact, - OrganisationRequest, - OrganisationRequestUserAction, - OrganisationContact, - OrganisationAccessGroup, - OrganisationRequestLogEntry, - OrganisationAction, - ledger_organisation, - ) - -from commercialoperator.components.organisations.serializers import ( - OrganisationSerializer, - OrganisationAddressSerializer, - DetailsSerializer, - OrganisationRequestSerializer, - OrganisationRequestDTSerializer, - OrganisationContactSerializer, - OrganisationCheckSerializer, - OrganisationPinCheckSerializer, - OrganisationRequestActionSerializer, - OrganisationActionSerializer, - OrganisationRequestCommsSerializer, - OrganisationCommsSerializer, - OrganisationUnlinkUserSerializer, - OrgUserAcceptSerializer, - MyOrganisationsSerializer, - OrganisationCheckExistSerializer, - LedgerOrganisationFilterSerializer, - OrganisationLogEntrySerializer, - ) -#from commercialoperator.components.applications.serializers import ( -# BaseApplicationSerializer, -# ) - -from commercialoperator.components.organisations.emails import ( - send_organisation_address_updated_email_notification, - send_organisation_id_upload_email_notification, - send_organisation_request_email_notification, - ) - - -#from wildlifecompliance.components.applications.models import ( -# Application, -# Assessment, -# ApplicationRequest, -# ApplicationGroupType -# ) - - -class OrganisationViewSet(viewsets.ModelViewSet): - queryset = Organisation.objects.all() - serializer_class = OrganisationSerializer - - def _get_queryset(self): - user = self.request.user - if is_internal(self.request): - return Organisation.objects.all() - elif is_customer(self.request): - return user.commercialoperator_organisations.all() - return Organisation.objects.none() - - @detail_route(methods=['GET',]) - def contacts(self, request, *args, **kwargs): - try: - instance = self.get_object() - serializer = OrganisationContactSerializer(instance.contacts.all(),many=True) - return Response(serializer.data); - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['GET',]) - def contacts_linked(self, request, *args, **kwargs): - try: - qs = self.get_queryset() - serializer = OrganisationContactSerializer(qs,many=True) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['GET',]) - def contacts_exclude(self, request, *args, **kwargs): - try: - instance = self.get_object() - qs = instance.contacts.exclude(user_status='draft') - serializer = OrganisationContactSerializer(qs,many=True) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - - @detail_route(methods=['POST',]) - def validate_pins(self, request, *args, **kwargs): - try: - instance = self.get_object() - serializer = OrganisationPinCheckSerializer(data=request.data) - serializer.is_valid(raise_exception=True) - ret = instance.validate_pins(serializer.validated_data['pin1'],serializer.validated_data['pin2'],request) - - if ret == None: - # user has already been to this organisation - don't add again - data = {'valid': ret} - return Response({'valid' : 'User already exists'}) - - data = {'valid': ret} - if data['valid']: - # Notify each Admin member of request. - instance.send_organisation_request_link_notification(request) - return Response(data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['POST', ]) - def accept_user(self, request, *args, **kwargs): - try: - instance = self.get_object() - serializer = OrgUserAcceptSerializer(data=request.data) - serializer.is_valid(raise_exception=True) - user_obj = EmailUser.objects.get( - email=serializer.validated_data['email'] - ) - instance.accept_user(user_obj, request) - serializer = self.get_serializer(instance) - return Response(serializer.data); - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['POST', ]) - def accept_declined_user(self, request, *args, **kwargs): - try: - instance = self.get_object() - serializer = OrgUserAcceptSerializer(data=request.data) - serializer.is_valid(raise_exception=True) - user_obj = EmailUser.objects.get( - email=serializer.validated_data['email'] - ) - instance.accept_declined_user(user_obj, request) - serializer = self.get_serializer(instance) - return Response(serializer.data); - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - - @detail_route(methods=['POST',]) - def decline_user(self, request, *args, **kwargs): - try: - instance = self.get_object() - serializer = OrgUserAcceptSerializer(data=request.data) - serializer.is_valid(raise_exception=True) - user_obj = EmailUser.objects.get( - email = serializer.validated_data['email'] - ) - instance.decline_user(user_obj,request) - serializer = self.get_serializer(instance) - return Response(serializer.data); - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - - @detail_route(methods=['POST',]) - def unlink_user(self, request, *args, **kwargs): - try: - instance = self.get_object() - serializer = OrgUserAcceptSerializer(data=request.data) - serializer.is_valid(raise_exception=True) - user_obj = EmailUser.objects.get( - email = serializer.validated_data['email'] - ) - instance.unlink_user(user_obj,request) - serializer = self.get_serializer(instance) - return Response(serializer.data); - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - - - - @detail_route(methods=['POST',]) - def make_admin_user(self, request, *args, **kwargs): - try: - instance = self.get_object() - serializer = OrgUserAcceptSerializer(data=request.data) - serializer.is_valid(raise_exception=True) - user_obj = EmailUser.objects.get( - email = serializer.validated_data['email'] - ) - instance.make_admin_user(user_obj,request) - serializer = self.get_serializer(instance) - return Response(serializer.data); - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['POST',]) - def make_user(self, request, *args, **kwargs): - try: - instance = self.get_object() - serializer = OrgUserAcceptSerializer(data=request.data) - serializer.is_valid(raise_exception=True) - user_obj = EmailUser.objects.get( - email = serializer.validated_data['email'] - ) - instance.make_user(user_obj,request) - serializer = self.get_serializer(instance) - return Response(serializer.data); - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['POST',]) - def make_consultant(self, request, *args, **kwargs): - try: - instance = self.get_object() - serializer = OrgUserAcceptSerializer(data=request.data) - serializer.is_valid(raise_exception=True) - user_obj = EmailUser.objects.get( - email = serializer.validated_data['email'] - ) - instance.make_consultant(user_obj,request) - serializer = self.get_serializer(instance) - return Response(serializer.data); - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - - @detail_route(methods=['POST',]) - def suspend_user(self, request, *args, **kwargs): - try: - instance = self.get_object() - serializer = OrgUserAcceptSerializer(data=request.data) - serializer.is_valid(raise_exception=True) - user_obj = EmailUser.objects.get( - email = serializer.validated_data['email'] - ) - instance.suspend_user(user_obj,request) - serializer = self.get_serializer(instance) - return Response(serializer.data); - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - - @detail_route(methods=['POST',]) - def reinstate_user(self, request, *args, **kwargs): - try: - instance = self.get_object() - serializer = OrgUserAcceptSerializer(data=request.data) - serializer.is_valid(raise_exception=True) - user_obj = EmailUser.objects.get( - email = serializer.validated_data['email'] - ) - instance.reinstate_user(user_obj,request) - serializer = self.get_serializer(instance) - return Response(serializer.data); - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - - @detail_route(methods=['POST',]) - def relink_user(self, request, *args, **kwargs): - try: - instance = self.get_object() - serializer = OrgUserAcceptSerializer(data=request.data) - serializer.is_valid(raise_exception=True) - user_obj = EmailUser.objects.get( - email = serializer.validated_data['email'] - ) - instance.relink_user(user_obj,request) - serializer = self.get_serializer(instance) - return Response(serializer.data); - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - - - @detail_route(methods=['GET',]) - def action_log(self, request, *args, **kwargs): - try: - instance = self.get_object() - qs = instance.action_logs.all() - serializer = OrganisationActionSerializer(qs,many=True) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - -# @detail_route(methods=['GET',]) -# def applications(self, request, *args, **kwargs): -# try: -# instance = self.get_object() -# qs = instance.org_applications.all() -# serializer = BaseApplicationSerializer(qs,many=True) -# return Response(serializer.data) -# except serializers.ValidationError: -# print(traceback.print_exc()) -# raise -# except ValidationError as e: -# print(traceback.print_exc()) -# raise serializers.ValidationError(repr(e.error_dict)) -# except Exception as e: -# print(traceback.print_exc()) -# raise serializers.ValidationError(str(e)) - - @detail_route(methods=['GET',]) - def comms_log(self, request, *args, **kwargs): - try: - instance = self.get_object() - qs = instance.comms_logs.all() - serializer = OrganisationCommsSerializer(qs,many=True) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - - @detail_route(methods=['POST',]) - @renderer_classes((JSONRenderer,)) - def add_comms_log(self, request, *args, **kwargs): - try: - with transaction.atomic(): - instance = self.get_object() - request.data['organisation'] = u'{}'.format(instance.id) - request.data['staff'] = u'{}'.format(request.user.id) - serializer = OrganisationLogEntrySerializer(data=request.data) - serializer.is_valid(raise_exception=True) - comms = serializer.save() - # Save the files - for f in request.FILES: - document = comms.documents.create() - document.name = str(request.FILES[f]) - document._file = request.FILES[f] - document.save() - # End Save Documents - - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @list_route(methods=['POST',]) - def existance(self, request, *args, **kwargs): - try: - serializer = OrganisationCheckSerializer(data=request.data) - serializer.is_valid(raise_exception=True) - data = Organisation.existance(serializer.validated_data['abn']) - # Check request user cannot be relinked to org. - data.update([('user', request.user.id)]) - data.update([('abn', request.data['abn'])]) - serializer = OrganisationCheckExistSerializer(data=data) - serializer.is_valid(raise_exception=True) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['POST',]) - def update_details(self, request, *args, **kwargs): - try: - org = self.get_object() - instance = org.organisation - serializer = DetailsSerializer(instance,data=request.data) - serializer.is_valid(raise_exception=True) - instance = serializer.save() - serializer = self.get_serializer(org) - return Response(serializer.data); - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['POST',]) - def update_address(self, request, *args, **kwargs): - try: - org = self.get_object() - instance = org.organisation - serializer = OrganisationAddressSerializer(data=request.data) - serializer.is_valid(raise_exception=True) - address, created = OrganisationAddress.objects.get_or_create( - line1 = serializer.validated_data['line1'], - locality = serializer.validated_data['locality'], - state = serializer.validated_data['state'], - country = serializer.validated_data['country'], - postcode = serializer.validated_data['postcode'], - organisation = instance - ) - instance.postal_address = address - instance.save() - #send_organisation_address_updated_email_notification(request.user, instance, org, request) - serializer = self.get_serializer(org) - return Response(serializer.data); - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['POST',]) - def upload_id(self, request, *args, **kwargs): - pass -# try: -# instance = self.get_object() -# instance.organisation.upload_identification(request) -# with transaction.atomic(): -# instance.save() -# instance.log_user_action(OrganisationAction.ACTION_ID_UPDATE.format( -# '{} ({})'.format(instance.name, instance.abn)), request) -# -# _applications = Application.objects.filter(org_applicant=instance.organisation.id) -# # Notify internal users new ID uploaded. -# if _applications: -# emails = set() -# for _application in _applications: -# # Officer assigned to the application -# if _application.assigned_officer_id: -# emails.add(EmailUser.objects.get(id=_application.assigned_officer_id).email) -# # Officer belonging to a group assigned to the application -# if ApplicationRequest.objects.filter(application_id=_application.id).exists(): -# _requests = ApplicationRequest.objects.filter(application_id=_application.id) -# for _request in _requests: -# if Assessment.objects.filter(id=_request.id).exists(): -# _group = Assessment.objects.filter(id=_request.id).first() -# if _group.assessor_group_id: -# _group_type = ApplicationGroupType.objects\ -# .filter(id=_group.assessor_group_id).first() -# _group_emails = _group_type.members.values_list('email', flat=True) -# for _email in _group_emails: -# emails.add(EmailUser.objects.get(email=_email).email) -# contact = OrganisationContact.objects.get(organisation=instance).email -# contact_email = EmailUser.objects.filter(email=request.user).first() -# if EmailUser.objects.filter(email=contact).first(): -# contact_email = EmailUser.objects.filter(email=contact).first() -# send_organisation_id_upload_email_notification(emails, instance, contact_email, request) -# -# serializer = OrganisationSerializer(instance, partial=True) -# return Response(serializer.data) -# except serializers.ValidationError: -# print(traceback.print_exc()) -# raise -# except ValidationError as e: -# print(traceback.print_exc()) -# raise serializers.ValidationError(repr(e.error_dict)) -# except Exception as e: -# print(traceback.print_exc()) -# raise serializers.ValidationError(str(e)) - -from rest_framework import filters -class OrganisationListFilterView(generics.ListAPIView): - """ https://cop-internal.dbca.wa.gov.au/api/filtered_organisations?search=Org1 - """ - #queryset = Organisation.objects.all() - queryset = ledger_organisation.objects.none() - serializer_class = LedgerOrganisationFilterSerializer - filter_backends = (filters.SearchFilter,) - search_fields = ('name',) - - def get_queryset(self): - org_list = Organisation.objects.all().values_list('id', flat=True) - return ledger_organisation.objects.filter(id__in=org_list) - -class OrganisationRequestsViewSet(viewsets.ModelViewSet): - queryset = OrganisationRequest.objects.all() - serializer_class = OrganisationRequestSerializer - - def get_queryset(self): - user = self.request.user - if is_internal(self.request): - return OrganisationRequest.objects.all() - elif is_customer(self.request): - return user.organisationrequest_set.all() - return OrganisationRequest.objects.none() - - @list_route(methods=['GET',]) - def datatable_list(self, request, *args, **kwargs): - try: - qs = self.get_queryset() - serializer = OrganisationRequestDTSerializer(qs,many=True) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - # @list_route(methods=['GET',]) - # def user_organisation_request_list(self, request, *args, **kwargs): - # try: - # queryset = self.get_queryset() - # queryset = queryset.filter(requester = request.user) - - # # instance = OrganisationRequest.objects.get(requester = request.user) - # serializer = self.get_serializer(queryset, many=True) - # return Response(serializer.data) - # except serializers.ValidationError: - # print(traceback.print_exc()) - # raise - # except ValidationError as e: - # print(traceback.print_exc()) - # raise serializers.ValidationError(repr(e.error_dict)) - # except Exception as e: - # print(traceback.print_exc()) - # raise serializers.ValidationError(str(e)) - - @list_route(methods=['GET', ]) - def get_pending_requests(self, request, *args, **kwargs): - try: - qs = self.get_queryset().filter(requester=request.user, status='with_assessor') - serializer = OrganisationRequestDTSerializer(qs, many=True) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @list_route(methods=['GET', ]) - def get_amendment_requested_requests(self, request, *args, **kwargs): - try: - qs = self.get_queryset().filter(requester=request.user, status='amendment_requested') - serializer = OrganisationRequestDTSerializer(qs, many=True) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - - @detail_route(methods=['GET',]) - def assign_request_user(self, request, *args, **kwargs): - try: - instance = self.get_object(requester =request.user) - serializer = OrganisationRequestSerializer(instance) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['GET',]) - def unassign(self, request, *args, **kwargs): - try: - instance = self.get_object() - instance.unassign(request) - serializer = OrganisationRequestSerializer(instance) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['GET',]) - def accept(self, request, *args, **kwargs): - try: - instance = self.get_object() - instance.accept(request) - serializer = OrganisationRequestSerializer(instance) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['GET',]) - def amendment_request(self, request, *args, **kwargs): - try: - instance = self.get_object() - instance.amendment_request(request) - serializer = OrganisationRequestSerializer(instance) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['PUT',]) - def reupload_identification_amendment_request(self, request, *args, **kwargs): - try: - instance = self.get_object() - instance.reupload_identification_amendment_request(request) - serializer = OrganisationRequestSerializer(instance, partial=True) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['GET',]) - def decline(self, request, *args, **kwargs): - try: - instance = self.get_object() - instance.decline(request) - serializer = OrganisationRequestSerializer(instance) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['POST',]) - def assign_to(self, request, *args, **kwargs): - try: - instance = self.get_object() - user_id = request.data.get('user_id',None) - user = None - if not user_id: - raise serializers.ValiationError('A user id is required') - try: - user = EmailUser.objects.get(id=user_id) - except EmailUser.DoesNotExist: - raise serializers.ValidationError('A user with the id passed in does not exist') - instance.assign_to(user,request) - serializer = OrganisationRequestSerializer(instance) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['GET',]) - def action_log(self, request, *args, **kwargs): - try: - instance = self.get_object() - qs = instance.action_logs.all() - serializer = OrganisationRequestActionSerializer(qs,many=True) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['GET',]) - def comms_log(self, request, *args, **kwargs): - try: - instance = self.get_object() - qs = instance.comms_logs.all() - serializer = OrganisationRequestCommsSerializer(qs,many=True) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - def create(self, request, *args, **kwargs): - try: - serializer = self.get_serializer(data=request.data) - serializer.is_valid(raise_exception=True) - serializer.validated_data['requester'] = request.user - if request.data['role'] == 'consultant': - # Check if consultant can be relinked to org. - data = Organisation.existance(request.data['abn']) - data.update([('user', request.user.id)]) - data.update([('abn', request.data['abn'])]) - existing_org = OrganisationCheckExistSerializer(data=data) - existing_org.is_valid(raise_exception=True) - with transaction.atomic(): - instance = serializer.save() - instance.log_user_action(OrganisationRequestUserAction.ACTION_LODGE_REQUEST.format(instance.id),request) - instance.send_organisation_request_email_notification(request) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - -class OrganisationAccessGroupMembers(views.APIView): - - renderer_classes = [JSONRenderer,] - def get(self,request, format=None): - members = [] - if is_internal(request): - group = OrganisationAccessGroup.objects.first() - if group: - for m in group.all_members: - members.append({'name': m.get_full_name(),'id': m.id}) - else: - for m in EmailUser.objects.filter(is_superuser=True,is_staff=True,is_active=True): - members.append({'name': m.get_full_name(),'id': m.id}) - return Response(members) - - -class OrganisationContactViewSet(viewsets.ModelViewSet): - serializer_class = OrganisationContactSerializer - queryset = OrganisationContact.objects.all() - - def get_queryset(self): - user = self.request.user - if is_internal(self.request): - return OrganisationContact.objects.all() - elif is_customer(self.request): - user_orgs = [org.id for org in user.commercialoperator_organisations.all()] - return OrganisationContact.objects.filter( Q(organisation_id__in = user_orgs) ) - return OrganisationContact.objects.none() - -class MyOrganisationsViewSet(viewsets.ModelViewSet): - queryset = Organisation.objects.all() - serializer_class = MyOrganisationsSerializer - - def get_queryset(self): - user = self.request.user - if is_internal(self.request): - return Organisation.objects.all() - elif is_customer(self.request): - return user.commercialoperator_organisations.all() - return Organisation.objects.none() diff --git a/commercialoperator/components/organisations/emails.py b/commercialoperator/components/organisations/emails.py deleted file mode 100755 index 7d50ca3fb2..0000000000 --- a/commercialoperator/components/organisations/emails.py +++ /dev/null @@ -1,374 +0,0 @@ -import logging - -from django.core.mail import EmailMultiAlternatives, EmailMessage -from django.utils.encoding import smart_text -from django.core.urlresolvers import reverse -from django.conf import settings - -from commercialoperator.components.emails.emails import TemplateEmailBase - -logger = logging.getLogger(__name__) - -SYSTEM_NAME = settings.SYSTEM_NAME_SHORT + ' Automated Message' -class OrganisationRequestAcceptNotificationEmail(TemplateEmailBase): - subject = 'Your organisation request has been accepted.' - html_template = 'commercialoperator/emails/organisation_request_accept_notification.html' - txt_template = 'commercialoperator/emails/organisation_request_accept_notification.txt' - -class OrganisationAccessGroupRequestAcceptNotificationEmail(TemplateEmailBase): - subject = 'New organisation request has been submitted.' - html_template = 'commercialoperator/emails/org_access_group_request_accept_notification.html' - txt_template = 'commercialoperator/emails/org_access_group_request_accept_notification.txt' - -class OrganisationRequestNotificationEmail(TemplateEmailBase): - subject = 'An organisation request has been submitted for approval' - html_template = 'commercialoperator/emails/organisation_request_notification.html' - txt_template = 'commercialoperator/emails/organisation_request_notification.txt' - -class OrganisationRequestDeclineNotificationEmail(TemplateEmailBase): - subject = 'Your organisation request has been declined.' - html_template = 'commercialoperator/emails/organisation_request_decline_notification.html' - txt_template = 'commercialoperator/emails/organisation_request_decline_notification.txt' - -class OrganisationLinkNotificationEmail(TemplateEmailBase): - subject = '{} - Confirmation - Account linked.'.format(settings.DEP_NAME) - html_template = 'commercialoperator/emails/organisation_link_notification.html' - txt_template = 'commercialoperator/emails/organisation_link_notification.txt' - -class OrganisationUnlinkNotificationEmail(TemplateEmailBase): - subject = 'You have been unlinked from an organisation.' - html_template = 'commercialoperator/emails/organisation_unlink_notification.html' - txt_template = 'commercialoperator/emails/organisation_unlink_notification.txt' - -class OrganisationContactAdminUserNotificationEmail(TemplateEmailBase): - subject = 'You have been linked as Company Admin Role.' - html_template = 'commercialoperator/emails/organisation_contact_admin_notification.html' - txt_template = 'commercialoperator/emails/organisation_contact_admin_notification.txt' - -class OrganisationContactUserNotificationEmail(TemplateEmailBase): - subject = 'You have been linked as Company User Role.' - html_template = 'commercialoperator/emails/organisation_contact_user_notification.html' - txt_template = 'commercialoperator/emails/organisation_contact_user_notification.txt' - -class OrganisationContactSuspendNotificationEmail(TemplateEmailBase): - subject = 'You have been suspended as Company User.' - html_template = 'commercialoperator/emails/organisation_contact_suspend_notification.html' - txt_template = 'commercialoperator/emails/organisation_contact_suspend_notification.txt' - -class OrganisationContactReinstateNotificationEmail(TemplateEmailBase): - subject = 'You have been Reinstated as Company User.' - html_template = 'commercialoperator/emails/organisation_contact_reinstate_notification.html' - txt_template = 'commercialoperator/emails/organisation_contact_reinstate_notification.txt' - -class OrganisationContactDeclineNotificationEmail(TemplateEmailBase): - subject = 'Your organisation link request has been declined.' - html_template = 'commercialoperator/emails/organisation_contact_decline_notification.html' - txt_template = 'commercialoperator/emails/organisation_contact_decline_notification.txt' - -class OrganisationAddressUpdatedNotificationEmail(TemplateEmailBase): - subject = 'An organisation''s address has been updated' - html_template = 'commercialoperator/emails/organisation_address_updated_notification.html' - txt_template = 'commercialoperator/emails/organisation_address_updated_notification.txt' - -class OrganisationIdUploadNotificationEmail(TemplateEmailBase): - subject = 'An organisation''s identification has been uploaded' - html_template = 'commercialoperator/emails/organisation_id_upload_notification.html' - txt_template = 'commercialoperator/emails/organisation_id_upload_notification.txt' - -class OrganisationRequestLinkNotificationEmail(TemplateEmailBase): - subject = 'An organisation request to be linked has been sent for approval' - html_template = 'commercialoperator/emails/organisation_request_link_notification.html' - txt_template = 'commercialoperator/emails/organisation_request_link_notification.txt' - - - -def send_organisation_id_upload_email_notification(emails, organisation, org_contact, request): - email = OrganisationIdUploadNotificationEmail() - - context = { - 'organisation': organisation - } - - msg = email.send(emails, context=context) - sender = request.user if request else settings.DEFAULT_FROM_EMAIL - _log_org_email(msg, organisation, org_contact, sender=sender) - -def send_organisation_request_link_email_notification( - org_request, request, contact): - email = OrganisationRequestLinkNotificationEmail() - - url = request.build_absolute_uri( - '/external/organisations/manage/{}'.format(org_request.id)) - - context = { - 'request': org_request, - 'url': url, - } - - msg = email.send(contact, context=context) - sender = request.user if request else settings.DEFAULT_FROM_EMAIL - _log_org_email(msg, org_request, request.user, sender=sender) - -def send_organisation_reinstate_email_notification(linked_user,linked_by,organisation,request): - email = OrganisationContactReinstateNotificationEmail() - - context = { - 'user': linked_user, - 'linked_by': linked_by, - 'organisation': organisation - } - - msg = email.send(linked_user.email, context=context) - sender = request.user if request else settings.DEFAULT_FROM_EMAIL - _log_org_email(msg, organisation, linked_user, sender=sender) - - -def send_organisation_contact_suspend_email_notification(linked_user,linked_by,organisation,request): - email = OrganisationContactSuspendNotificationEmail() - - context = { - 'user': linked_user, - 'linked_by': linked_by, - 'organisation': organisation - } - - msg = email.send(linked_user.email, context=context) - sender = request.user if request else settings.DEFAULT_FROM_EMAIL - _log_org_email(msg, organisation, linked_user, sender=sender) - -def send_organisation_contact_decline_email_notification(user_contact,deleted_by,organisation,request): - email = OrganisationContactDeclineNotificationEmail() - - context = { - 'user': user_contact, - 'linked_by': deleted_by, - 'organisation': organisation - } - - msg = email.send(user_contact.email, context=context) - sender = request.user if request else settings.DEFAULT_FROM_EMAIL - _log_org_email(msg, organisation, user_contact, sender=sender) - - - -def send_organisation_contact_user_email_notification(linked_user,linked_by,organisation,request): - email = OrganisationContactUserNotificationEmail() - - context = { - 'user': linked_user, - 'linked_by': linked_by, - 'organisation': organisation - } - - msg = email.send(linked_user.email, context=context) - sender = request.user if request else settings.DEFAULT_FROM_EMAIL - _log_org_email(msg, organisation, linked_user, sender=sender) - - -def send_organisation_contact_adminuser_email_notification(linked_user,linked_by,organisation,request): - email = OrganisationContactAdminUserNotificationEmail() - - context = { - 'user': linked_user, - 'linked_by': linked_by, - 'organisation': organisation - } - - msg = email.send(linked_user.email, context=context) - sender = request.user if request else settings.DEFAULT_FROM_EMAIL - _log_org_email(msg, organisation, linked_user, sender=sender) - - -def send_organisation_link_email_notification(linked_user,linked_by,organisation,request): - email = OrganisationLinkNotificationEmail() - - context = { - 'user': linked_user, - 'linked_by': linked_by, - 'organisation': organisation - } - - msg = email.send(linked_user.email, context=context) - sender = request.user if request else settings.DEFAULT_FROM_EMAIL - _log_org_email(msg, organisation, linked_user, sender=sender) - -def send_organisation_request_email_notification(org_request, request, contact): - email = OrganisationRequestNotificationEmail() - - url = request.build_absolute_uri('/internal/organisations/access/{}'.format(org_request.id)) - if "-internal" not in url: - url = "{0}://{1}{2}.{3}{4}".format(request.scheme, settings.SITE_PREFIX, '-internal', settings.SITE_DOMAIN, - url.split(request.get_host())[1]) - - context = { - 'request': request.data, - 'url': url, - } - - msg = email.send(contact, context=context) - sender = request.user if request else settings.DEFAULT_FROM_EMAIL - _log_org_request_email(msg, org_request, sender=sender) - -def send_organisation_unlink_email_notification(unlinked_user,unlinked_by,organisation,request): - email = OrganisationUnlinkNotificationEmail() - - context = { - 'user': unlinked_user, - 'unlinked_by': unlinked_by, - 'organisation': organisation - } - - msg = email.send(unlinked_user.email, context=context) - sender = request.user if request else settings.DEFAULT_FROM_EMAIL - _log_org_email(msg, organisation, unlinked_user, sender=sender) - -def send_organisation_request_accept_email_notification(org_request,organisation,request): - email = OrganisationRequestAcceptNotificationEmail() - - context = { - 'request': org_request - } - - msg = email.send(org_request.requester.email, context=context) - sender = request.user if request else settings.DEFAULT_FROM_EMAIL - _log_org_request_email(msg, org_request, sender=sender) - _log_org_email(msg, organisation, org_request.requester, sender=sender) - -def send_org_access_group_request_accept_email_notification(org_request, request, recipient_list): - email = OrganisationAccessGroupRequestAcceptNotificationEmail() - - url = request.build_absolute_uri('/internal/organisations/access/{}'.format(org_request.id)) - if "-internal" not in url: - url = '-internal.{}'.format(settings.SITE_DOMAIN).join(url.split('.' + settings.SITE_DOMAIN)) - - context = { - 'name': request.data.get('name'), - 'abn': request.data.get('abn'), - 'url': url, - } - - msg = email.send(recipient_list, context=context) - sender = request.user if request else settings.DEFAULT_FROM_EMAIL - _log_org_request_email(msg, org_request, sender=sender) - - # commenting out because Organisation does not yet exist - only OrganisationRequest exists - #_log_org_email(msg, organisation, org_request.requester, sender=sender) - - -def send_organisation_request_decline_email_notification(org_request,request): - email = OrganisationRequestDeclineNotificationEmail() - - context = { - 'request': org_request - } - - msg = email.send(org_request.requester.email, context=context) - sender = request.user if request else settings.DEFAULT_FROM_EMAIL - _log_org_request_email(msg, org_request, sender=sender) - #_log_org_email(msg, organisation, org_request.requester, sender=sender) - -def send_organisation_address_updated_email_notification(address_updated_by,ledger_organisation,wc_organisation,request): - from commercialoperator.components.organisations.models import OrganisationContact - - email = OrganisationAddressUpdatedNotificationEmail() - - context = { - 'address_updated_by': address_updated_by, - 'organisation': ledger_organisation - } - - for org_contact in OrganisationContact.objects.filter(user_role='organisation_admin',organisation=wc_organisation): - msg = email.send(org_contact.email, context=context) - sender = request.user if request else settings.DEFAULT_FROM_EMAIL - -def _log_org_request_email(email_message, request, sender=None): - from commercialoperator.components.organisations.models import OrganisationRequestLogEntry - if isinstance(email_message, (EmailMultiAlternatives, EmailMessage,)): - # TODO this will log the plain text body, should we log the html instead - text = email_message.body - subject = email_message.subject - fromm = smart_text(sender) if sender else smart_text(email_message.from_email) - # the to email is normally a list - if isinstance(email_message.to, list): - to = ','.join(email_message.to) - else: - to = smart_text(email_message.to) - # we log the cc and bcc in the same cc field of the log entry as a ',' comma separated string - all_ccs = [] - if email_message.cc: - all_ccs += list(email_message.cc) - if email_message.bcc: - all_ccs += list(email_message.bcc) - all_ccs = ','.join(all_ccs) - - else: - text = smart_text(email_message) - subject = '' - to = request.requester.email - fromm = smart_text(sender) if sender else SYSTEM_NAME - all_ccs = '' - - customer = request.requester - - staff = sender - - kwargs = { - 'subject': subject, - 'text': text, - 'request': request, - 'customer': customer, - 'staff': staff, - 'to': to, - 'fromm': fromm, - 'cc': all_ccs - } - - email_entry = OrganisationRequestLogEntry.objects.create(**kwargs) - - return email_entry - -def _log_org_email(email_message, organisation, customer ,sender=None): - from commercialoperator.components.organisations.models import OrganisationLogEntry - if isinstance(email_message, (EmailMultiAlternatives, EmailMessage,)): - # TODO this will log the plain text body, should we log the html instead - text = email_message.body - subject = email_message.subject - fromm = smart_text(sender) if sender else smart_text(email_message.from_email) - # the to email is normally a list - if isinstance(email_message.to, list): - to = ','.join(email_message.to) - else: - to = smart_text(email_message.to) - # we log the cc and bcc in the same cc field of the log entry as a ',' comma separated string - all_ccs = [] - if email_message.cc: - all_ccs += list(email_message.cc) - if email_message.bcc: - all_ccs += list(email_message.bcc) - all_ccs = ','.join(all_ccs) - - else: - text = smart_text(email_message) - subject = '' - to = request.requester.email - fromm = smart_text(sender) if sender else SYSTEM_NAME - all_ccs = '' - - customer = customer - - staff = sender - - kwargs = { - 'subject': subject, - 'text': text, - 'organisation': organisation, - 'customer': customer, - 'staff': staff, - 'to': to, - 'fromm': fromm, - 'cc': all_ccs - } - - email_entry = OrganisationLogEntry.objects.create(**kwargs) - - return email_entry diff --git a/commercialoperator/components/organisations/models.py b/commercialoperator/components/organisations/models.py deleted file mode 100755 index effa4b0bba..0000000000 --- a/commercialoperator/components/organisations/models.py +++ /dev/null @@ -1,766 +0,0 @@ -from __future__ import unicode_literals - -from django.db import models, transaction -from django.contrib.sites.models import Site -from django.dispatch import receiver -from django.db.models.signals import pre_delete -from django.utils.encoding import python_2_unicode_compatible -from django.core.exceptions import ValidationError -from django.contrib.postgres.fields.jsonb import JSONField -from ledger.accounts.models import Organisation as ledger_organisation -from ledger.accounts.models import EmailUser,RevisionedMixin #,Document -from commercialoperator.components.main.models import UserAction,CommunicationsLogEntry, Document -from commercialoperator.components.organisations.utils import random_generator -from commercialoperator.components.organisations.emails import ( - send_organisation_request_accept_email_notification, - send_organisation_request_decline_email_notification, - send_organisation_link_email_notification, - send_organisation_unlink_email_notification, - send_org_access_group_request_accept_email_notification, - send_organisation_contact_adminuser_email_notification, - send_organisation_contact_user_email_notification, - send_organisation_contact_suspend_email_notification, - send_organisation_reinstate_email_notification, - send_organisation_contact_decline_email_notification, - send_organisation_request_email_notification, - send_organisation_request_link_email_notification, - - ) - -@python_2_unicode_compatible -class Organisation(models.Model): - organisation = models.ForeignKey(ledger_organisation) - # TODO: business logic related to delegate changes. - delegates = models.ManyToManyField(EmailUser, blank=True, through='UserDelegation', related_name='commercialoperator_organisations') - #pin_one = models.CharField(max_length=50,blank=True) - #pin_two = models.CharField(max_length=50,blank=True) - admin_pin_one = models.CharField(max_length=50,blank=True) - admin_pin_two = models.CharField(max_length=50,blank=True) - user_pin_one = models.CharField(max_length=50,blank=True) - user_pin_two = models.CharField(max_length=50,blank=True) - bpay_allowed = models.BooleanField('BPAY Allowed', default=False) - monthly_invoicing_allowed = models.BooleanField(default=False) - monthly_invoicing_period = models.SmallIntegerField('Monthly Invoicing Period (in #days from beginning of the following month)', default=0) - monthly_payment_due_period = models.SmallIntegerField('Monthly Payment Due Period (in #days from Invoicing Date)', default=20) - - class Meta: - app_label = 'commercialoperator' - - def __str__(self): - return str(self.organisation) - - def log_user_action(self, action, request): - return OrganisationAction.log_action(self, action, request.user) - - def validate_pins(self,pin1,pin2,request): - try: - val_admin = self.admin_pin_one == pin1 and self.admin_pin_two == pin2 - val_user = self.user_pin_one == pin1 and self.user_pin_two == pin2 - if val_admin: - val= val_admin - admin_flag= True - role = 'organisation_admin' - elif val_user: - val = val_user - admin_flag = False - role = 'organisation_user' - else: - val = False - return val - - self.add_user_contact(request.user,request,admin_flag,role) - return val - except Exception: - return None - - def check_user_contact(self,request,admin_flag,role): - user = request.user - try: - org = OrganisationContact.objects.create( - organisation = self, - first_name = user.first_name, - last_name = user.last_name, - mobile_number = user.mobile_number, - phone_number = user.phone_number, - fax_number = user.fax_number, - email = user.email, - user_role = role, - user_status='pending', - is_admin = admin_flag - - ) - return org - except Exception: - return False - - def add_user_contact(self,user,request,admin_flag,role): - with transaction.atomic(): - - OrganisationContact.objects.create( - organisation = self, - first_name = user.first_name, - last_name = user.last_name, - mobile_number = user.mobile_number, - phone_number = user.phone_number, - fax_number = user.fax_number, - email = user.email, - user_role = role, - user_status='pending', - is_admin = admin_flag - - ) - - # log linking - self.log_user_action(OrganisationAction.ACTION_CONTACT_ADDED.format('{} {}({})'.format(user.first_name,user.last_name,user.email)),request) - - def update_organisation(self, request): - # log organisation details updated (eg ../internal/organisations/access/2) - incorrect - this is for OrganisationRequesti not Organisation - # should be ../internal/organisations/1 - with transaction.atomic(): - self.log_user_action(OrganisationAction.ACTION_UPDATE_ORGANISATION, request) - - def update_address(self, request): - self.log_user_action(OrganisationAction.ACTION_UPDATE_ADDRESS, request) - - def update_contacts(self, request): - try: - contact = self.contact.last() - self.log_user_action(OrganisationAction.ACTION_UPDATE_CONTACTS.format('{} {}({})'.format(contact.first_name, contact.last_name, contact.email)), request) - except: - pass - - def generate_pins(self): - #self.pin_one = self._generate_pin() - #self.pin_two = self._generate_pin() - self.admin_pin_one = self._generate_pin() - self.admin_pin_two = self._generate_pin() - self.user_pin_one = self._generate_pin() - self.user_pin_two = self._generate_pin() - self.save() - - def _generate_pin(self): - return random_generator() - - def send_organisation_request_link_notification(self, request): - # Notify each Admin member of request to be linked to org. - contacts = OrganisationContact.objects.filter( - organisation_id=self.id, - user_role='organisation_admin', - user_status='active', - is_admin=True) - recipients = [c.email for c in contacts] - send_organisation_request_link_email_notification( - self, request, recipients) - - @staticmethod - def existance(abn): - exists = True - org = None - l_org = None - try: - try: - l_org = ledger_organisation.objects.get(abn=abn) - except ledger_organisation.DoesNotExist: - exists = False - if l_org: - try: - org = Organisation.objects.get(organisation=l_org) - except Organisation.DoesNotExist: - exists = False - if exists: - return {'exists': exists, 'id': org.id,'first_five':org.first_five} - return {'exists': exists } - - except: - raise - - - def accept_user(self, user,request): - with transaction.atomic(): - # try: - # UserDelegation.objects.get(organisation=self,user=user) - # raise ValidationError('This user has already been linked to {}'.format(str(self.organisation))) - # except UserDelegation.DoesNotExist: - delegate = UserDelegation.objects.create(organisation=self,user=user) - - try: - org_contact = OrganisationContact.objects.get(organisation = self,email = delegate.user.email) - org_contact.user_status ='active' - org_contact.save() - except OrganisationContact.DoesNotExist: - pass - - #log linking - self.log_user_action(OrganisationAction.ACTION_LINK.format('{} {}({})'.format(delegate.user.first_name,delegate.user.last_name,delegate.user.email)),request) - send_organisation_link_email_notification(user,request.user,self,request) - - def decline_user(self, user,request): - try: - org_contact = OrganisationContact.objects.get(organisation = self,email = user.email) - org_contact.user_status ='declined' - org_contact.save() - except OrganisationContact.DoesNotExist: - pass - OrganisationContactDeclinedDetails.objects.create( - officer = request.user, - request = org_contact - ) - - #log linking - self.log_user_action(OrganisationAction.ACTION_CONTACT_DECLINED.format('{} {}({})'.format(user.first_name,user.last_name,user.email)),request) - send_organisation_contact_decline_email_notification(user,request.user,self,request) - - def link_user(self, user, request, admin_flag): - with transaction.atomic(): - try: - UserDelegation.objects.get(organisation=self, user=user) - raise ValidationError('This user has already been linked to {}'.format(str(self.organisation))) - except UserDelegation.DoesNotExist: - delegate = UserDelegation.objects.create(organisation=self, user=user) - if self.first_five_admin: - is_admin = True - role = 'organisation_admin' - elif admin_flag: - role = 'organisation_admin' - is_admin = True - else: - role = 'organisation_user' - is_admin = False - - # Create contact person - try: - OrganisationContact.objects.create( - organisation=self, - first_name=user.first_name, - last_name=user.last_name, - mobile_number=user.mobile_number, - phone_number=user.phone_number, - fax_number=user.fax_number, - email=user.email, - user_role=role, - user_status='pending', - is_admin=is_admin - - ) - except: - pass # user already exists - - # log linking - self.log_user_action(OrganisationAction.ACTION_LINK.format( - '{} {}({})'.format(delegate.user.first_name, delegate.user.last_name, delegate.user.email)), request) - # send email - send_organisation_link_email_notification(user, request.user, self, request) - - - def accept_declined_user(self, user, request): - with transaction.atomic(): - try: - UserDelegation.objects.get(organisation=self, user=user) - raise ValidationError('This user has already been linked to {}'.format(str(self.organisation))) - except UserDelegation.DoesNotExist: - delegate = UserDelegation.objects.create(organisation=self, user=user) - if self.first_five_admin: - is_admin = True - role = 'organisation_admin' - elif admin_flag: - role = 'organisation_admin' - is_admin = True - else: - role = 'organisation_user' - is_admin = False - - try: - org_contact = OrganisationContact.objects.get(organisation = self,email = delegate.user.email) - org_contact.user_status ='active' - org_contact.save() - except OrganisationContact.DoesNotExist: - pass - - # log linking - self.log_user_action(OrganisationAction.ACTION_LINK.format( - '{} {}({})'.format(delegate.user.first_name, delegate.user.last_name, delegate.user.email)), request) - # send email - send_organisation_link_email_notification(user, request.user, self, request) - - - def relink_user(self, user, request): - with transaction.atomic(): - try: - UserDelegation.objects.get(organisation=self, user=user) - raise ValidationError('This user has not yet been linked to {}'.format(str(self.organisation))) - except UserDelegation.DoesNotExist: - delegate = UserDelegation.objects.create(organisation=self, user=user) - try: - org_contact = OrganisationContact.objects.get(organisation = self,email = delegate.user.email) - org_contact.user_status ='active' - org_contact.save() - except OrganisationContact.DoesNotExist: - pass - # log linking - self.log_user_action(OrganisationAction.ACTION_MAKE_CONTACT_REINSTATE.format('{} {}({})'.format(delegate.user.first_name,delegate.user.last_name,delegate.user.email)),request) - # send email - send_organisation_reinstate_email_notification(user,request.user,self,request) - - - - def unlink_user(self,user,request): - with transaction.atomic(): - try: - delegate = UserDelegation.objects.get(organisation=self,user=user) - except UserDelegation.DoesNotExist: - raise ValidationError('This user is not a member of {}'.format(str(self.organisation))) - # delete contact person - try: - org_contact = OrganisationContact.objects.get(organisation = self,email = delegate.user.email) - if org_contact.user_role == 'organisation_admin': - if OrganisationContact.objects.filter(organisation = self,user_role = 'organisation_admin', user_status ='active').count() > 1 : - org_contact.user_status ='unlinked' - org_contact.save() - # delete delegate - delegate.delete() - else: - raise ValidationError('This user is last Organisation Administrator.') - - else: - org_contact.user_status ='unlinked' - org_contact.save() - # delete delegate - delegate.delete() - except OrganisationContact.DoesNotExist: - pass - - - # log linking - self.log_user_action(OrganisationAction.ACTION_UNLINK.format('{} {}({})'.format(delegate.user.first_name,delegate.user.last_name,delegate.user.email)),request) - # send email - send_organisation_unlink_email_notification(user,request.user,self,request) - - - def make_admin_user(self,user,request): - with transaction.atomic(): - try: - delegate = UserDelegation.objects.get(organisation=self,user=user) - except UserDelegation.DoesNotExist: - raise ValidationError('This user is not a member of {}'.format(str(self.organisation))) - # delete contact person - try: - org_contact = OrganisationContact.objects.get(organisation = self,email = delegate.user.email) - org_contact.user_role ='organisation_admin' - org_contact.is_admin = True - org_contact.save() - except OrganisationContact.DoesNotExist: - pass - # log linking - self.log_user_action(OrganisationAction.ACTION_MAKE_CONTACT_ADMIN.format('{} {}({})'.format(delegate.user.first_name,delegate.user.last_name,delegate.user.email)),request) - # send email - send_organisation_contact_adminuser_email_notification(user,request.user,self,request) - - - def make_user(self,user,request): - with transaction.atomic(): - try: - delegate = UserDelegation.objects.get(organisation=self,user=user) - except UserDelegation.DoesNotExist: - raise ValidationError('This user is not a member of {}'.format(str(self.organisation))) - # delete contact person - try: - org_contact = OrganisationContact.objects.get(organisation = self,email = delegate.user.email) - org_contact.user_role ='organisation_user' - org_contact.is_admin = False - org_contact.save() - except OrganisationContact.DoesNotExist: - pass - # log linking - self.log_user_action(OrganisationAction.ACTION_MAKE_CONTACT_USER.format('{} {}({})'.format(delegate.user.first_name,delegate.user.last_name,delegate.user.email)),request) - # send email - send_organisation_contact_user_email_notification(user,request.user,self,request) - - def suspend_user(self,user,request): - with transaction.atomic(): - try: - delegate = UserDelegation.objects.get(organisation=self,user=user) - except UserDelegation.DoesNotExist: - raise ValidationError('This user is not a member of {}'.format(str(self.organisation))) - # delete contact person - try: - org_contact = OrganisationContact.objects.get(organisation = self,email = delegate.user.email) - org_contact.user_status ='suspended' - org_contact.save() - except OrganisationContact.DoesNotExist: - pass - # log linking - self.log_user_action(OrganisationAction.ACTION_MAKE_CONTACT_SUSPEND.format('{} {}({})'.format(delegate.user.first_name,delegate.user.last_name,delegate.user.email)),request) - # send email - send_organisation_contact_suspend_email_notification(user,request.user,self,request) - - - - def reinstate_user(self,user,request): - with transaction.atomic(): - try: - delegate = UserDelegation.objects.get(organisation=self,user=user) - except UserDelegation.DoesNotExist: - raise ValidationError('This user is not a member of {}'.format(str(self.organisation))) - # delete contact person - try: - org_contact = OrganisationContact.objects.get(organisation = self,email = delegate.user.email) - org_contact.user_status ='active' - org_contact.save() - except OrganisationContact.DoesNotExist: - pass - # log linking - self.log_user_action(OrganisationAction.ACTION_MAKE_CONTACT_REINSTATE.format('{} {}({})'.format(delegate.user.first_name,delegate.user.last_name,delegate.user.email)),request) - # send email - send_organisation_reinstate_email_notification(user,request.user,self,request) - - - - @property - def name(self): - return self.organisation.name - - @property - def abn(self): - return self.organisation.abn - - @property - def address(self): - return self.organisation.postal_address - - @property - def phone_number(self): - return self.organisation.phone_number - - @property - def email(self): - return self.organisation.email - - @property - def first_five(self): - return ','.join([user.get_full_name() for user in self.delegates.all()[:5]]) - -@python_2_unicode_compatible -class OrganisationContact(models.Model): - USER_STATUS_CHOICES = (('draft', 'Draft'), - ('pending', 'Pending'), - ('active', 'Active'), - ('declined', 'Declined'), - ('unlinked', 'Unlinked'), - ('suspended', 'Suspended')) - USER_ROLE_CHOICES = (('organisation_admin', 'Organisation Admin'), - ('organisation_user', 'Organisation User'), - ('consultant','Consultant') - ) - user_status = models.CharField('Status', max_length=40, choices=USER_STATUS_CHOICES,default=USER_STATUS_CHOICES[0][0]) - user_role = models.CharField('Role', max_length=40, choices=USER_ROLE_CHOICES,default='organisation_user') - is_admin = models.BooleanField(default= False) - organisation = models.ForeignKey(Organisation, related_name='contacts') - email = models.EmailField(blank=False) - first_name = models.CharField(max_length=128, blank=False, verbose_name='Given name(s)') - last_name = models.CharField(max_length=128, blank=False) - phone_number = models.CharField(max_length=50, null=True, blank=True, - verbose_name="phone number", help_text='') - mobile_number = models.CharField(max_length=50, null=True, blank=True, - verbose_name="mobile number", help_text='') - fax_number = models.CharField(max_length=50, null=True, blank=True, - verbose_name="fax number", help_text='') - - class Meta: - app_label = 'commercialoperator' - unique_together = (('organisation','email'),) - - def __str__(self): - return '{} {}'.format(self.last_name,self.first_name) - - @property - def can_edit(self): - """ - :return: True if the application is in one of the editable status. - """ - return self.is_admin and self.user_status == 'active' and self.user_role =='organisation_admin' - - @property - def check_consultant(self): - """ - :return: True if the application is in one of the editable status. - """ - return self.user_status == 'active' and self.user_role =='consultant' - -class UserDelegation(models.Model): - organisation = models.ForeignKey(Organisation) - user = models.ForeignKey(EmailUser) - - class Meta: - unique_together = (('organisation','user'),) - app_label = 'commercialoperator' - - -class OrganisationAction(UserAction): - ACTION_REQUEST_APPROVED = "Organisation Request {} Approved" - ACTION_LINK = "Linked {}" - ACTION_UNLINK = "Unlinked {}" - ACTION_CONTACT_ADDED = "Added new contact {}" - ACTION_CONTACT_REMOVED = "Removed contact {}" - ACTION_CONTACT_DECLINED = "Declined contact {}" - ACTION_MAKE_CONTACT_ADMIN = "Made contact Organisation Admin {}" - ACTION_MAKE_CONTACT_USER = "Made contact Organisation User {}" - #ACTION_CONTACT_REMOVED = "Removed contact {}" - ACTION_ORGANISATIONAL_DETAILS_SAVED_NOT_CHANGED = "Details saved without changes" - ACTION_ORGANISATIONAL_DETAILS_SAVED_CHANGED = "Details saved with the following changes: \n{}" - ACTION_ORGANISATIONAL_ADDRESS_DETAILS_SAVED_NOT_CHANGED = "Address Details saved without changes" - ACTION_ORGANISATIONAL_ADDRESS_DETAILS_SAVED_CHANGED = "Addres Details saved with folowing changes: \n{}" - ACTION_ORGANISATION_CONTACT_ACCEPT = "Accepted contact {}" - #ACTION_CONTACT_DECLINE = "Declined contact {}" - ACTION_MAKE_CONTACT_SUSPEND = "Suspended contact {}" - ACTION_MAKE_CONTACT_REINSTATE = "REINSTATED contact {}" - - ACTION_ORGANISATIONAL_DETAILS_SAVED_NOT_CHANGED = "Details saved without changes" - ACTION_ORGANISATIONAL_DETAILS_SAVED_CHANGED = "Details saved with the following changes: \n{}" - ACTION_ORGANISATIONAL_ADDRESS_DETAILS_SAVED_NOT_CHANGED = "Address Details saved without changes" - ACTION_ORGANISATIONAL_ADDRESS_DETAILS_SAVED_CHANGED = "Addres Details saved with folowing changes: \n{}" - - ACTION_UPDATE_ORGANISATION = "Updated organisation name" - ACTION_UPDATE_ADDRESS = "Updated address" - ACTION_UPDATE_CONTACTS = "Updated contacts" - - @classmethod - def log_action(cls, organisation, action, user): - return cls.objects.create( - organisation=organisation, - who=user, - what=str(action) - ) - - organisation = models.ForeignKey(Organisation,related_name='action_logs') - - class Meta: - app_label = 'commercialoperator' - -def update_organisation_comms_log_filename(instance, filename): - return 'organisations/{}/communications/{}/{}'.format(instance.log_entry.organisation.id,instance.id,filename) - - -class OrganisationLogDocument(Document): - log_entry = models.ForeignKey('OrganisationLogEntry',related_name='documents') - _file = models.FileField(upload_to=update_organisation_comms_log_filename) - - class Meta: - app_label = 'commercialoperator' - - -class OrganisationLogEntry(CommunicationsLogEntry): - organisation = models.ForeignKey(Organisation, related_name='comms_logs') - - def save(self, **kwargs): - # save the request id if the reference not provided - if not self.reference: - self.reference = self.organisation.id - super(OrganisationLogEntry, self).save(**kwargs) - - class Meta: - app_label = 'commercialoperator' - - -class OrganisationRequest(models.Model): - STATUS_CHOICES = ( - ('with_assessor','With Assessor'), - ('approved','Approved'), - ('declined','Declined') - ) - ROLE_CHOICES = ( - ('employee','Employee'), - ('consultant','Consultant') - ) - name = models.CharField(max_length=128, unique=True) - abn = models.CharField(max_length=50, null=True, blank=True, verbose_name='ABN') - requester = models.ForeignKey(EmailUser) - assigned_officer = models.ForeignKey(EmailUser, blank=True, null=True, related_name='org_request_assignee') - identification = models.FileField(upload_to='organisation/requests/%Y/%m/%d', null=True, blank=True) - status = models.CharField(max_length=100,choices=STATUS_CHOICES, default="with_assessor") - lodgement_date = models.DateTimeField(auto_now_add=True) - role = models.CharField(max_length=100,choices=ROLE_CHOICES, default="employee") - - class Meta: - app_label = 'commercialoperator' - - def accept(self, request): - with transaction.atomic(): - self.status = 'approved' - self.save() - self.log_user_action(OrganisationRequestUserAction.ACTION_CONCLUDE_REQUEST.format(self.id),request) - # Continue with remaining logic - self.__accept(request) - - def __accept(self,request): - # Check if orgsanisation exists in ledger - ledger_org = None - try: - ledger_org = ledger_organisation.objects.get(abn=self.abn) - except ledger_organisation.DoesNotExist: - ledger_org = ledger_organisation.objects.create(name=self.name,abn=self.abn) - # Create Organisation in commercialoperator - org, created = Organisation.objects.get_or_create(organisation=ledger_org) - # Link requester to organisation - delegate = UserDelegation.objects.create(user=self.requester,organisation=org) - # log who approved the request - org.log_user_action(OrganisationAction.ACTION_REQUEST_APPROVED.format(self.id),request) - # log who created the link - org.log_user_action(OrganisationAction.ACTION_LINK.format('{} {}({})'.format(delegate.user.first_name,delegate.user.last_name,delegate.user.email)),request) - # Create contact person - if self.role == 'consultant': - role = 'consultant' - else: - role = 'organisation_admin' - # Create contact person - - OrganisationContact.objects.create( - organisation=org, - first_name=self.requester.first_name, - last_name=self.requester.last_name, - mobile_number=self.requester.mobile_number, - phone_number=self.requester.phone_number, - fax_number=self.requester.fax_number, - email=self.requester.email, - user_role=role, - user_status='active', - is_admin=True - - ) - # send email to requester - send_organisation_request_accept_email_notification(self, org, request) - - def send_org_access_group_request_notification(self,request): - # user submits a new organisation request - # send email to organisation access group - org_access_recipients = [i.email for i in OrganisationAccessGroup.objects.last().all_members] - send_org_access_group_request_accept_email_notification(self, request, org_access_recipients) - - def assign_to(self, user,request): - with transaction.atomic(): - self.assigned_officer = user - self.save() - self.log_user_action(OrganisationRequestUserAction.ACTION_ASSIGN_TO.format(user.get_full_name()),request) - - def unassign(self,request): - with transaction.atomic(): - self.assigned_officer = None - self.save() - self.log_user_action(OrganisationRequestUserAction.ACTION_UNASSIGN,request) - - def decline(self, reason, request): - with transaction.atomic(): - self.status = 'declined' - self.save() - OrganisationRequestDeclinedDetails.objects.create( - officer = request.user, - reason = reason, - request = self - ) - self.log_user_action(OrganisationRequestUserAction.ACTION_DECLINE_REQUEST,request) - send_organisation_request_decline_email_notification(self,request) - - def send_organisation_request_email_notification(self, request): - # user submits a new organisation request - # send email to organisation access group - group = OrganisationAccessGroup.objects.first() - if group and group.filtered_members: - org_access_recipients = [m.email for m in group.filtered_members] - send_organisation_request_email_notification(self, request, org_access_recipients) - - def log_user_action(self, action, request): - return OrganisationRequestUserAction.log_action(self, action, request.user) - -class OrganisationAccessGroup(models.Model): - site = models.OneToOneField(Site, default='1') - members = models.ManyToManyField(EmailUser) - - def __str__(self): - return 'Organisation Access Group' - - @property - def all_members(self): - all_members = [] - all_members.extend(self.members.all()) - member_ids = [m.id for m in self.members.all()] - #all_members.extend(EmailUser.objects.filter(is_superuser=True,is_staff=True,is_active=True).exclude(id__in=member_ids)) - return all_members - - @property - def filtered_members(self): - return self.members.all() - - class Meta: - app_label = 'commercialoperator' - verbose_name_plural = "Organisation access group" - -class OrganisationRequestUserAction(UserAction): - ACTION_LODGE_REQUEST = "Lodge request {}" - ACTION_ASSIGN_TO = "Assign to {}" - ACTION_UNASSIGN = "Unassign" - ACTION_DECLINE_REQUEST = "Decline request" - # Assessors - - ACTION_CONCLUDE_REQUEST = "Conclude request {}" - - @classmethod - def log_action(cls, request, action, user): - return cls.objects.create( - request=request, - who=user, - what=str(action) - ) - - request = models.ForeignKey(OrganisationRequest,related_name='action_logs') - - class Meta: - app_label = 'commercialoperator' - - -class OrganisationRequestDeclinedDetails(models.Model): - request = models.ForeignKey(OrganisationRequest) - officer = models.ForeignKey(EmailUser, null=False) - reason = models.TextField(blank=True) - - class Meta: - app_label = 'commercialoperator' - -def update_organisation_request_comms_log_filename(instance, filename): - return 'organisation_requests/{}/communications/{}/{}'.format(instance.log_entry.request.id,instance.id,filename) - - -class OrganisationRequestLogDocument(Document): - log_entry = models.ForeignKey('OrganisationRequestLogEntry',related_name='documents') - _file = models.FileField(upload_to=update_organisation_request_comms_log_filename) - - class Meta: - app_label = 'commercialoperator' - -class OrganisationRequestLogEntry(CommunicationsLogEntry): - request = models.ForeignKey(OrganisationRequest, related_name='comms_logs') - - def save(self, **kwargs): - # save the request id if the reference not provided - if not self.reference: - self.reference = self.request.id - super(OrganisationRequestLogEntry, self).save(**kwargs) - - class Meta: - app_label = 'commercialoperator' - - - -import reversion -reversion.register(ledger_organisation, follow=['organisation_set']) -reversion.register(Organisation, follow=['org_approvals', 'contacts', 'userdelegation_set', 'action_logs', 'comms_logs']) -reversion.register(OrganisationContact) -reversion.register(OrganisationAction) -reversion.register(OrganisationLogEntry, follow=['documents']) -reversion.register(OrganisationLogDocument) -reversion.register(OrganisationRequest, follow=['action_logs', 'organisationrequestdeclineddetails_set', 'comms_logs']) -reversion.register(OrganisationAccessGroup) -reversion.register(OrganisationRequestUserAction) -reversion.register(OrganisationRequestDeclinedDetails) -reversion.register(OrganisationRequestLogDocument) -reversion.register(OrganisationRequestLogEntry, follow=['documents']) -reversion.register(UserDelegation) - diff --git a/commercialoperator/components/organisations/serializers.py b/commercialoperator/components/organisations/serializers.py deleted file mode 100755 index 89ca81804e..0000000000 --- a/commercialoperator/components/organisations/serializers.py +++ /dev/null @@ -1,306 +0,0 @@ -from django.conf import settings -from ledger.accounts.models import EmailUser,OrganisationAddress -from commercialoperator.components.organisations.models import ( - Organisation, - OrganisationContact, - OrganisationRequest, - OrganisationRequestUserAction, - OrganisationAction, - OrganisationRequestLogEntry, - OrganisationLogEntry, - ledger_organisation, - ) -from commercialoperator.components.organisations.utils import ( - can_manage_org, - can_admin_org, - is_consultant, - can_approve, - can_relink, - is_last_admin, - ) -from commercialoperator.components.main.serializers import CommunicationLogEntrySerializer -from rest_framework import serializers, status -import rest_framework_gis.serializers as gis_serializers - - -class LedgerOrganisationSerializer(serializers.ModelSerializer): - class Meta: - model = ledger_organisation - fields = '__all__' - - -class LedgerOrganisationFilterSerializer(serializers.ModelSerializer): - #address = serializers.SerializerMethodField(read_only=True) - email = serializers.SerializerMethodField(read_only=True) - - class Meta: - model = ledger_organisation - fields = ( - 'id', - 'name', - 'email', - #'address', - ) - - def get_email(self, obj): - return '' - - -class OrganisationCheckSerializer(serializers.Serializer): - # Validation serializer for new Organisations - abn = serializers.CharField() - name = serializers.CharField() - - def validate(self, data): - # Check no admin request pending approval. - requests = OrganisationRequest.objects.filter(abn=data['abn'], role='employee')\ - .exclude(status__in=('declined', 'approved')) - if requests.exists(): - raise serializers.ValidationError('A request has been submitted and is Pending Approval.') - return data - -class OrganisationPinCheckSerializer(serializers.Serializer): - pin1 = serializers.CharField() - pin2 = serializers.CharField() - -class OrganisationAddressSerializer(serializers.ModelSerializer): - class Meta: - model = OrganisationAddress - fields = ( - 'id', - 'line1', - 'locality', - 'state', - 'country', - 'postcode' - ) - -class DelegateSerializer(serializers.ModelSerializer): - name = serializers.CharField(source='get_full_name') - class Meta: - model = EmailUser - fields = ( - 'id', - 'name', - ) - - -class OrganisationSerializer(serializers.ModelSerializer): - address = OrganisationAddressSerializer(read_only=True) - pins = serializers.SerializerMethodField(read_only=True) - delegates = DelegateSerializer(many=True, read_only=True) - organisation = LedgerOrganisationSerializer() - trading_name = serializers.SerializerMethodField(read_only=True) - - class Meta: - model = Organisation - fields = ( - 'id', - 'name', - 'trading_name', - 'abn', - 'address', - 'email', - 'organisation', - 'phone_number', - 'pins', - 'delegates' - ) - - def get_trading_name(self, obj): - return obj.organisation.trading_name - - def get_pins(self, obj): - try: - user = self.context['request'].user - # Check if the request user is among the first five delegates in the organisation - if can_manage_org(obj, user): - return {'one': obj.admin_pin_one, 'two': obj.admin_pin_two, 'three': obj.user_pin_one, - 'four': obj.user_pin_two} - else: - return None - except KeyError: - return None - - -class OrganisationCheckExistSerializer(serializers.Serializer): - # Validation Serializer for existing Organisations - exists = serializers.BooleanField(default=False) - id = serializers.IntegerField(default=0) - first_five = serializers.CharField(allow_blank=True, required=False) - user = serializers.IntegerField() - abn = serializers.CharField() - - def validate(self, data): - user = EmailUser.objects.get(id=data['user']) - if data['exists']: - org = Organisation.objects.get(id=data['id']) - if can_relink(org, user): - raise serializers.ValidationError('Please contact {} to re-link to Organisation.' - .format(data['first_five'])) - if can_approve(org, user): - raise serializers.ValidationError('Please contact {} to Approve your request.' - .format(data['first_five'])) - # Check no consultant request is pending approval for an ABN - if OrganisationRequest.objects.filter(abn=data['abn'], requester=user, role='consultant')\ - .exclude(status__in=('declined', 'approved')).exists(): - raise serializers.ValidationError('A request has been submitted and is Pending Approval.') - return data - - -class MyOrganisationsSerializer(serializers.ModelSerializer): - is_admin = serializers.SerializerMethodField(read_only=True) - is_consultant = serializers.SerializerMethodField(read_only=True) - - class Meta: - model = Organisation - fields = ( - 'id', - 'name', - 'abn', - 'is_admin', - 'is_consultant' - ) - - def get_is_consultant(self, obj): - user = self.context['request'].user - # Check if the request user is among the first five delegates in the organisation - return is_consultant(obj, user) - - def get_is_admin(self, obj): - user = self.context['request'].user - # Check if the request user is among the first five delegates in the organisation - return can_admin_org(obj, user) - - -class DetailsSerializer(serializers.ModelSerializer): - class Meta: - model = ledger_organisation - fields = ('id','name', 'trading_name') - -class OrganisationContactSerializer(serializers.ModelSerializer): - user_status= serializers.SerializerMethodField() - user_role= serializers.SerializerMethodField() - - class Meta: - model = OrganisationContact - fields = '__all__' - - def get_user_status(self,obj): - return obj.get_user_status_display() - - def get_user_role(self,obj): - return obj.get_user_role_display() - - - -class OrgRequestRequesterSerializer(serializers.ModelSerializer): - full_name = serializers.SerializerMethodField() - class Meta: - model = EmailUser - fields = ( - 'email', - 'mobile_number', - 'phone_number', - 'full_name' - ) - - def get_full_name(self, obj): - return obj.get_full_name() - -class OrganisationRequestSerializer(serializers.ModelSerializer): - identification = serializers.FileField() - requester = OrgRequestRequesterSerializer(read_only=True) - status = serializers.SerializerMethodField() - # role = serializers.SerializerMethodField() - - class Meta: - model = OrganisationRequest - fields = '__all__' - read_only_fields = ('requester','lodgement_date','assigned_officer') - - def get_status(self,obj): - return obj.get_status_display() - # def get_role(self,obj): - # return obj.get_role_display() - - -class OrganisationRequestDTSerializer(OrganisationRequestSerializer): - assigned_officer = serializers.CharField(source='assigned_officer.get_full_name') - requester = serializers.SerializerMethodField() - - def get_requester(self,obj): - return obj.requester.get_full_name() - -class UserOrganisationSerializer(serializers.ModelSerializer): - name = serializers.CharField(source='organisation.name') - abn = serializers.CharField(source='organisation.abn') - class Meta: - model = Organisation - fields = ( - 'id', - 'name', - 'abn' - ) - -class OrganisationRequestActionSerializer(serializers.ModelSerializer): - who = serializers.CharField(source='who.get_full_name') - class Meta: - model = OrganisationRequestUserAction - fields = '__all__' - -class OrganisationActionSerializer(serializers.ModelSerializer): - who = serializers.CharField(source='who.get_full_name') - class Meta: - model = OrganisationAction - fields = '__all__' - -class OrganisationRequestCommsSerializer(serializers.ModelSerializer): - class Meta: - model = OrganisationRequestLogEntry - fields = '__all__' - -class OrganisationCommsSerializer(serializers.ModelSerializer): - class Meta: - model = OrganisationLogEntry - fields = '__all__' - -class OrganisationLogEntrySerializer(CommunicationLogEntrySerializer): - documents = serializers.SerializerMethodField() - class Meta: - model = OrganisationLogEntry - fields = '__all__' - read_only_fields = ( - 'customer', - ) - - def get_documents(self,obj): - return [[d.name,d._file.url] for d in obj.documents.all()] - -class OrganisationUnlinkUserSerializer(serializers.Serializer): - user = serializers.IntegerField() - - def validate(self,obj): - user = None - try: - user = EmailUser.objects.get(id=obj['user']) - obj['user_obj'] = user - except EmailUser.DoesNotExist: - raise serializers.ValidationError('The user you want to unlink does not exist.') - return obj - -class OrgUserAcceptSerializer(serializers.Serializer): - - first_name = serializers.CharField() - last_name =serializers.CharField() - email= serializers.EmailField() - mobile_number = serializers.CharField(required=False, allow_null=True, allow_blank=True) - phone_number = serializers.CharField(required=False, allow_null=True, allow_blank=True) - - def validate(self, data): - ''' - Check for either mobile number or phone number - ''' - if not (data['mobile_number'] or data['phone_number']): - raise serializers.ValidationError("User must have an associated phone number or mobile number.") - return data diff --git a/commercialoperator/components/organisations/serializers.py.orig b/commercialoperator/components/organisations/serializers.py.orig deleted file mode 100755 index 35be919c07..0000000000 --- a/commercialoperator/components/organisations/serializers.py.orig +++ /dev/null @@ -1,221 +0,0 @@ -from django.conf import settings -from ledger.accounts.models import EmailUser,OrganisationAddress -from commercialoperator.components.organisations.models import ( - Organisation, - OrganisationContact, - OrganisationRequest, - OrganisationRequestUserAction, - OrganisationAction, - OrganisationRequestLogEntry, - OrganisationLogEntry, - ledger_organisation, - ) -from commercialoperator.components.organisations.utils import can_manage_org, can_admin_org,is_consultant -from rest_framework import serializers -import rest_framework_gis.serializers as gis_serializers - - -class LedgerOrganisationSerializer(serializers.ModelSerializer): - class Meta: - model = ledger_organisation - fields = '__all__' - -class OrganisationCheckSerializer(serializers.Serializer): - abn = serializers.CharField() - name = serializers.CharField() - -class OrganisationPinCheckSerializer(serializers.Serializer): - pin1 = serializers.CharField() - pin2 = serializers.CharField() - -class OrganisationAddressSerializer(serializers.ModelSerializer): - class Meta: - model = OrganisationAddress - fields = ( - 'id', - 'line1', - 'locality', - 'state', - 'country', - 'postcode' - ) - -class DelegateSerializer(serializers.ModelSerializer): - name = serializers.CharField(source='get_full_name') - class Meta: - model = EmailUser - fields = ( - 'id', - 'name', - ) - -class OrganisationSerializer(serializers.ModelSerializer): - address = OrganisationAddressSerializer(read_only=True) - pins = serializers.SerializerMethodField(read_only=True) - delegates = DelegateSerializer(many=True,read_only=True) - class Meta: - model = Organisation - fields = ( - 'id', - 'name', - 'abn', - 'address', - 'email', - 'phone_number', - 'pins', - 'delegates', - ) - - def get_pins(self,obj): - user = self.context['request'].user - # Check if the request user is among the first five delegates in the organisation - if can_manage_org(obj,user): - return {'one': obj.admin_pin_one, 'two': obj.admin_pin_two, - 'three': obj.user_pin_one, 'four': obj.user_pin_two} - else: - return None - -class DetailsSerializer(serializers.ModelSerializer): - class Meta: - model = ledger_organisation - fields = ('id','name') - -class OrganisationContactSerializer(serializers.ModelSerializer): - user_status= serializers.SerializerMethodField() - user_role= serializers.SerializerMethodField() - - class Meta: - model = OrganisationContact - fields = '__all__' - - def get_user_status(self,obj): - return obj.get_user_status_display() - - def get_user_role(self,obj): - return obj.get_user_role_display() - -class OrgRequestRequesterSerializer(serializers.ModelSerializer): - full_name = serializers.SerializerMethodField() - class Meta: - model = EmailUser - fields = ( - 'email', - 'mobile_number', - 'phone_number', - 'full_name' - ) - - def get_full_name(self, obj): - return obj.get_full_name() - -class OrganisationRequestSerializer(serializers.ModelSerializer): - identification = serializers.FileField() - requester = OrgRequestRequesterSerializer(read_only=True) - status = serializers.SerializerMethodField() - class Meta: - model = OrganisationRequest - fields = '__all__' - read_only_fields = ('requester','lodgement_date','assigned_officer') - - def get_status(self,obj): - return obj.get_status_display() - -class OrganisationRequestDTSerializer(OrganisationRequestSerializer): - assigned_officer = serializers.CharField(source='assigned_officer.get_full_name', allow_null=True) - requester = serializers.SerializerMethodField() - - def get_requester(self,obj): - return obj.requester.get_full_name() - -class UserOrganisationSerializer(serializers.ModelSerializer): - name = serializers.CharField(source='organisation.name') - abn = serializers.CharField(source='organisation.abn') - class Meta: - model = Organisation - fields = ( - 'id', - 'name', - 'abn' - ) - -class OrganisationRequestActionSerializer(serializers.ModelSerializer): - who = serializers.CharField(source='who.get_full_name') - class Meta: - model = OrganisationRequestUserAction - fields = '__all__' - -class OrganisationActionSerializer(serializers.ModelSerializer): - who = serializers.CharField(source='who.get_full_name') - class Meta: - model = OrganisationAction - fields = '__all__' - -class OrganisationRequestCommsSerializer(serializers.ModelSerializer): - documents = serializers.SerializerMethodField() - class Meta: - model = OrganisationRequestLogEntry - fields = '__all__' - def get_documents(self,obj): - return [[d.name,d._file.url] for d in obj.documents.all()] - -class OrganisationCommsSerializer(serializers.ModelSerializer): - documents = serializers.SerializerMethodField() - class Meta: - model = OrganisationLogEntry - fields = '__all__' - - def get_documents(self,obj): - return [[d.name,d._file.url] for d in obj.documents.all()] - -class OrganisationUnlinkUserSerializer(serializers.Serializer): - user = serializers.IntegerField() - - def validate(self,obj): - user = None - try: - user = EmailUser.objects.get(id=obj['user']) - obj['user_obj'] = user - except EmailUser.DoesNotExist: - raise serializers.ValidationError('The user you want to unlink does not exist.') - return obj - -class MyOrganisationsSerializer(serializers.ModelSerializer): - is_admin = serializers.SerializerMethodField(read_only=True) - is_consultant = serializers.SerializerMethodField(read_only=True) - - class Meta: - model = Organisation - fields = ( - 'id', - 'name', - 'abn', - 'is_admin', - 'is_consultant' - ) - - def get_is_consultant(self, obj): - user = self.context['request'].user - # Check if the request user is among the first five delegates in the organisation - return is_consultant(obj, user) - - def get_is_admin(self, obj): - user = self.context['request'].user - # Check if the request user is among the first five delegates in the organisation - return can_admin_org(obj, user) - -class OrgUserAcceptSerializer(serializers.Serializer): - - first_name = serializers.CharField() - last_name =serializers.CharField() - email= serializers.EmailField() - mobile_number = serializers.CharField(required=False, allow_null=True, allow_blank=True) - phone_number = serializers.CharField(required=False, allow_null=True, allow_blank=True) - - def validate(self, data): - ''' - Check for either mobile number or phone number - ''' - if not (data['mobile_number'] or data['phone_number']): - raise serializers.ValidationError("User must have an associated phone number or mobile number.") - return data - diff --git a/commercialoperator/components/organisations/signals.py b/commercialoperator/components/organisations/signals.py deleted file mode 100755 index 43a6cfd394..0000000000 --- a/commercialoperator/components/organisations/signals.py +++ /dev/null @@ -1,46 +0,0 @@ -from django.dispatch import receiver -from django.db.models.signals import post_delete, pre_save, post_save -from django.conf import settings - -from commercialoperator.components.organisations.models import Organisation,OrganisationContact -from ledger.accounts.models import EmailUser - -class OrganisationListener(object): - """ - Event listener for Organisation - """ - - @staticmethod - @receiver(pre_save, sender=Organisation) - def _pre_save(sender, instance, **kwargs): - if instance.pk: - original_instance = Organisation.objects.get(pk=instance.pk) - setattr(instance, "_original_instance", original_instance) - - elif hasattr(instance, "_original_instance"): - delattr(instance, "_original_instance") - else: - #instance.pin_one = instance._generate_pin() - #instance.pin_two = instance._generate_pin() - instance.admin_pin_one = instance._generate_pin() - instance.admin_pin_two = instance._generate_pin() - instance.user_pin_one = instance._generate_pin() - instance.user_pin_two = instance._generate_pin() - -class EmailUserUpdateContactListener(object): - @staticmethod - @receiver(post_save, sender=EmailUser) - def _post_save(sender, instance, **kwargs): - original_instance = getattr(instance, "_original_instance") if hasattr(instance, "_original_instance") else None - if original_instance: - try: - OrganisationContact.objects.filter(email=original_instance.email).update( - first_name = instance.first_name, - last_name = instance.last_name, - mobile_number = instance.mobile_number, - phone_number = instance.phone_number, - fax_number = instance.fax_number, - email = instance.email - ) - except EmailUser.DoesNotExist: - pass diff --git a/commercialoperator/components/organisations/templates/commercialoperator/emails/org_access_group_request_accept_notification.html b/commercialoperator/components/organisations/templates/commercialoperator/emails/org_access_group_request_accept_notification.html deleted file mode 100755 index 44c3a63e9d..0000000000 --- a/commercialoperator/components/organisations/templates/commercialoperator/emails/org_access_group_request_accept_notification.html +++ /dev/null @@ -1,15 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} -

A new organisation request has been submitted:

-

Organisation : {{ name }}

-

ABN : {{ abn }}

-
- -

- You can access this Organisation Request using the following link: -

- Access Organisation Request -
- -{% endblock %} diff --git a/commercialoperator/components/organisations/templates/commercialoperator/emails/org_access_group_request_accept_notification.txt b/commercialoperator/components/organisations/templates/commercialoperator/emails/org_access_group_request_accept_notification.txt deleted file mode 100755 index 7eba8994a1..0000000000 --- a/commercialoperator/components/organisations/templates/commercialoperator/emails/org_access_group_request_accept_notification.txt +++ /dev/null @@ -1,15 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.txt' %} - -{% block content %} - A new organisation request has been submitted: - - Organisation : {{ request.name }} - - ABN : {{ request.abn}} - -

- You can access this Organisation Request using the following link: -

- Access Organisation Request - -{% endblock %} diff --git a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_address_updated_notification.html b/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_address_updated_notification.html deleted file mode 100644 index 0c8deac78b..0000000000 --- a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_address_updated_notification.html +++ /dev/null @@ -1,10 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} -

The address for an organisation you are linked to has been updated by {{address_updated_by.get_full_name}} ({{address_updated_by.email}}).

-

Organisation: {{ organisation.name }}

-

ABN: {{ organisation.abn }}

-

Address: {{ organisation.postal_address.line1 }}, {{ organisation.postal_address.locality }}, - {{ organisation.postal_address.state }}, {{ organisation.postal_address.postcode}}, - {{ organisation.postal_address.country}}

-{% endblock %} diff --git a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_address_updated_notification.txt b/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_address_updated_notification.txt deleted file mode 100644 index 8f645e7b41..0000000000 --- a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_address_updated_notification.txt +++ /dev/null @@ -1,14 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.txt' %} - -{% block content %} - The address for an organisation you are linked to has been updated by {{address_updated_by.get_full_name}} ({{address_updated_by.email}}). - - Organisation: {{ organisation.name }} - - ABN: {{ organisation.abn }} - - Address: {{ organisation.postal_address.line1 }}, {{ organisation.postal_address.locality }}, - {{ organisation.postal_address.state }}, {{ organisation.postal_address.postcode}}, - {{ organisation.postal_address.country}} - -{% endblock %} diff --git a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_contact_admin_notification.html b/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_contact_admin_notification.html deleted file mode 100644 index 22f9560d9e..0000000000 --- a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_contact_admin_notification.html +++ /dev/null @@ -1,9 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} -

Your have been made Company Admin to:

-

Organisation : {{ organisation.name }}

-

ABN : {{ organisation.abn}}

-

You were linked to this organisation by {{linked_by.get_full_name}}({{linked_by.email}}).

-

You can now make applications on behalf of this organisation.

-{% endblock %} diff --git a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_contact_admin_notification.txt b/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_contact_admin_notification.txt deleted file mode 100644 index 3c9eb8d32f..0000000000 --- a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_contact_admin_notification.txt +++ /dev/null @@ -1,13 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.txt' %} - -{% block content %} - Your have been made Company Admin to: - - Organisation : {{ organisation.name }} - - ABN : {{ organisation.abn}} - - You were linked to this organisation by {{ linked_by.get_full_name }}({{linked_by.email}}). - You can now make applications on behalf of this organisation. - -{% endblock %} diff --git a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_contact_decline_notification.html b/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_contact_decline_notification.html deleted file mode 100644 index 15ad083626..0000000000 --- a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_contact_decline_notification.html +++ /dev/null @@ -1,9 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} -

Your Organisation link request has been declined from:

-

Organisation : {{ organisation.name }}

-

ABN : {{ organisation.abn}}

- -

You can not make applications on behalf of this organisation now.

-{% endblock %} diff --git a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_contact_decline_notification.txt b/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_contact_decline_notification.txt deleted file mode 100644 index 290a8bb225..0000000000 --- a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_contact_decline_notification.txt +++ /dev/null @@ -1,10 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.txt' %} - -{% block content %} - Your Organisation link request has been declined from: - Organisation : {{ organisation.name }} - ABN : {{ organisation.abn}} - - You can not make applications on behalf of this organisation now. - -{% endblock %} diff --git a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_contact_reinstate_notification.html b/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_contact_reinstate_notification.html deleted file mode 100644 index 5a732c1315..0000000000 --- a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_contact_reinstate_notification.html +++ /dev/null @@ -1,9 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} -

Your have been Reinstated to:

-

Organisation : {{ organisation.name }}

-

ABN : {{ organisation.abn}}

-

You were linked to this organisation by {{linked_by.get_full_name}}({{linked_by.email}}).

-

You can now make applications on behalf of this organisation.

-{% endblock %} diff --git a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_contact_reinstate_notification.txt b/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_contact_reinstate_notification.txt deleted file mode 100644 index 945c2a7be5..0000000000 --- a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_contact_reinstate_notification.txt +++ /dev/null @@ -1,14 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.txt' %} - -{% block content %} - Your have been reinstated to: - - Organisation : {{ organisation.name }} - - ABN : {{ organisation.abn}} - - You were linked to this organisation by {{ linked_by.get_full_name }}({{linked_by.email}}). - - You can now make applications on behalf of this organisation. - -{% endblock %} diff --git a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_contact_suspend_notification.html b/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_contact_suspend_notification.html deleted file mode 100644 index 4c23a6561a..0000000000 --- a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_contact_suspend_notification.html +++ /dev/null @@ -1,15 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} - {% if linked_by.email != user.email %} -

Your have been suspended from:

-

Organisation : {{ organisation.name }}

-

ABN : {{ organisation.abn}}

-

You were linked to this organisation by {{linked_by.get_full_name}}({{linked_by.email}}).

- {% else %} -

You have suspended yourself from:

-

Organisation : {{ organisation.name }}

-

ABN : {{ organisation.abn}}

- {% endif %} -

You can now make applications on behalf of this organisation.

-{% endblock %} diff --git a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_contact_suspend_notification.txt b/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_contact_suspend_notification.txt deleted file mode 100644 index a3b2fe7400..0000000000 --- a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_contact_suspend_notification.txt +++ /dev/null @@ -1,22 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.txt' %} - -{% block content %} - - {% if linked_by.email != user.email %} - Your have been suspended from: - - Organisation : {{ organisation.name }} - - ABN : {{ organisation.abn}} - - You were linked to this organisation by {{ linked_by.get_full_name }}({{linked_by.email}}). - {% else %} - Your have suspended yourself from: - - Organisation : {{ organisation.name }} - - ABN : {{ organisation.abn}} - {% endif %} - You can now make applications on behalf of this organisation. - -{% endblock %} diff --git a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_contact_user_notification.html b/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_contact_user_notification.html deleted file mode 100644 index e4867121ab..0000000000 --- a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_contact_user_notification.html +++ /dev/null @@ -1,15 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} - {% if linked_by.email != user.email %} -

Your have been made Company User to:

-

Organisation : {{ organisation.name }}

-

ABN : {{ organisation.abn}}

-

You were linked to this organisation by {{linked_by.get_full_name}}({{linked_by.email}}).

- {% else %} -

You have linked yourself to:

-

Organisation : {{ organisation.name }}

-

ABN : {{ organisation.abn}}

- {% endif %} -

You can now make applications on behalf of this organisation.

-{% endblock %} diff --git a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_contact_user_notification.txt b/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_contact_user_notification.txt deleted file mode 100644 index 6c5f5ec4f5..0000000000 --- a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_contact_user_notification.txt +++ /dev/null @@ -1,21 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.txt' %} - -{% block content %} - {% if linked_by.email != user.email %} - Your have been made company User to: - - Organisation : {{ organisation.name }} - - ABN : {{ organisation.abn}} - - You were linked to this organisation by {{ linked_by.get_full_name }}({{linked_by.email}}). - {% else %} - Your have made yourself Company User to: - - Organisation : {{ organisation.name }} - - ABN : {{ organisation.abn}} - {% endif %} - You can now make applications on behalf of this organisation. - -{% endblock %} diff --git a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_id_upload_notification.html b/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_id_upload_notification.html deleted file mode 100644 index f27e003ddf..0000000000 --- a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_id_upload_notification.html +++ /dev/null @@ -1,10 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} -

Identification for the following organisation you are linked to has been uploaded.

-

Organisation: {{ organisation.name }}

-

ABN: {{ organisation.abn }}

-

Address: {{ organisation.postal_address.line1 }}, {{ organisation.postal_address.locality }}, - {{ organisation.postal_address.state }}, {{ organisation.postal_address.postcode}}, - {{ organisation.postal_address.country}}

-{% endblock %} diff --git a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_id_upload_notification.txt b/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_id_upload_notification.txt deleted file mode 100644 index 2eda58121b..0000000000 --- a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_id_upload_notification.txt +++ /dev/null @@ -1,14 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.txt' %} - -{% block content %} - Identification for the following organisation you are linked to has been uploaded. - - Organisation: {{ organisation.name }} - - ABN: {{ organisation.abn }} - - Address: {{ organisation.postal_address.line1 }}, {{ organisation.postal_address.locality }}, - {{ organisation.postal_address.state }}, {{ organisation.postal_address.postcode}}, - {{ organisation.postal_address.country}} - -{% endblock %} diff --git a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_link_notification.html b/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_link_notification.html deleted file mode 100755 index 20c7bd45ce..0000000000 --- a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_link_notification.html +++ /dev/null @@ -1,19 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} - -

Your request to link your account to a company has been approved. Details are as follows:

-

Company : {{ organisation.name }}

-

ABN/ ACN: {{ organisation.abn}}

-

Now that your account has been linked you can proceed with an application for a Commercial Operations licence.

-{% endblock %} diff --git a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_link_notification.txt b/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_link_notification.txt deleted file mode 100755 index 4246c90063..0000000000 --- a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_link_notification.txt +++ /dev/null @@ -1,10 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.txt' %} - -{% block content %} - - Your request to link your account to a company has been approved. Details are as follows: - Company : {{ organisation.name }} - ABN/ ACN : {{ organisation.abn}} - Now that your account has been linked you can proceed with an application for a Commercial Operations licence. - -{% endblock %} diff --git a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_request_accept_notification.html b/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_request_accept_notification.html deleted file mode 100755 index 57419eb629..0000000000 --- a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_request_accept_notification.html +++ /dev/null @@ -1,8 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} -

Your organisation request has been approved:

-

Organisation : {{ request.name }}

-

ABN : {{ request.abn}}

-

You have been linked to this organisation and you can now make applications on behalf of this organisation.

-{% endblock %} diff --git a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_request_accept_notification.txt b/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_request_accept_notification.txt deleted file mode 100755 index fc3ef15dae..0000000000 --- a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_request_accept_notification.txt +++ /dev/null @@ -1,12 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.txt' %} - -{% block content %} - Your organisation request has been approved: - - Organisation : {{ request.name }} - - ABN : {{ request.abn}} - - You have been linked to this organisation and you can now make applications on behalf of this organisation. - -{% endblock %} diff --git a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_request_decline_notification.html b/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_request_decline_notification.html deleted file mode 100755 index ab7386f838..0000000000 --- a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_request_decline_notification.html +++ /dev/null @@ -1,7 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} -

Your organisation request has been declined:

-

Organisation : {{ request.name }}

-

ABN : {{ request.abn}}

-{% endblock %} diff --git a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_request_decline_notification.txt b/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_request_decline_notification.txt deleted file mode 100755 index 98e443bc14..0000000000 --- a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_request_decline_notification.txt +++ /dev/null @@ -1,11 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.txt' %} - -{% block content %} - Your organisation request has been declined: - - Organisation : {{ request.name }} - - ABN : {{ request.abn}} - - -{% endblock %} diff --git a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_request_link_notification.html b/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_request_link_notification.html deleted file mode 100644 index 75abae65da..0000000000 --- a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_request_link_notification.html +++ /dev/null @@ -1,10 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} -

A user has requested to be linked to the following organisation:

-

Organisation: {{ request.name }}

-

ABN: {{ request.abn }}

-

Link: {{url}}

-

Note: If you haven't logged into the Commercial Operator Licensing System recently you may need to login first before using the provided link.

- -{% endblock %} \ No newline at end of file diff --git a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_request_link_notification.txt b/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_request_link_notification.txt deleted file mode 100644 index 89c2fe55c0..0000000000 --- a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_request_link_notification.txt +++ /dev/null @@ -1,14 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.txt' %} - -{% block content %} - A user has requested to be linked to the following organisation: - - Organisation: {{ request.name }} - - ABN: {{ request.abn }} - - Link: {{url}} - - Note: If you haven't logged into the Commercial Operator Licensing System recently you may need to login first before using the provided link. - -{% endblock %} \ No newline at end of file diff --git a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_request_notification.html b/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_request_notification.html deleted file mode 100644 index 0aa11299ef..0000000000 --- a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_request_notification.html +++ /dev/null @@ -1,10 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} -

A new organisation request access has been submitted:

-

Organisation: {{ request.name }}

-

ABN: {{ request.abn }}

-

Link: {{url}}

-

Note: If you haven't logged into the Commercial Operator Licensing System recently you may need to login first before using the provided link.

- -{% endblock %} diff --git a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_request_notification.txt b/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_request_notification.txt deleted file mode 100644 index 7d01edca82..0000000000 --- a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_request_notification.txt +++ /dev/null @@ -1,14 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.txt' %} - -{% block content %} - A new organisation access request has been submitted: - - Organisation: {{ request.name }} - - ABN: {{ request.abn }} - - Link: {{url}} - - Note: If you haven't logged into the Commercial Operator Licensing System recently you may need to login first before using the provided link. - -{% endblock %} diff --git a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_unlink_notification.html b/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_unlink_notification.html deleted file mode 100755 index c78b7b60d1..0000000000 --- a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_unlink_notification.html +++ /dev/null @@ -1,15 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} - {% if unlinked_by.email != user.email %} -

Your have been unlinked from:

-

Organisation : {{ organisation.name }}

-

ABN : {{ organisation.abn}}

-

You were unlinked from this organisation by {{unlinked_by.get_full_name}}({{unlinked_by.email}}).

- {% else %} -

You have unlinked yourself from:

-

Organisation : {{ organisation.name }}

-

ABN : {{ organisation.abn}}

- {% endif %} -

You can no longer make applications on behalf of this organisation.

-{% endblock %} diff --git a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_unlink_notification.txt b/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_unlink_notification.txt deleted file mode 100755 index 62017d5a83..0000000000 --- a/commercialoperator/components/organisations/templates/commercialoperator/emails/organisation_unlink_notification.txt +++ /dev/null @@ -1,21 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.txt' %} - -{% block content %} - {% if unlinked_by.email != user.email %} - Your have been unlinked from: - - Organisation : {{ organisation.name }} - - ABN : {{ organisation.abn}} - - You were unlinked from this organisation by {{ unlinked_by.get_full_name }}({{unlinked_by.email}}). - {% else %} - Your have unlinked yourself from: - - Organisation : {{ organisation.name }} - - ABN : {{ organisation.abn}} - {% endif %} - You can no longer make applications on behalf of this organisation. - -{% endblock %} diff --git a/commercialoperator/components/organisations/utils.py b/commercialoperator/components/organisations/utils.py deleted file mode 100755 index 8087bc525c..0000000000 --- a/commercialoperator/components/organisations/utils.py +++ /dev/null @@ -1,93 +0,0 @@ -import string -import random - - -def can_manage_org(organisation,user): - from commercialoperator.components.organisations.models import Organisation, OrganisationAccessGroup,UserDelegation - from ledger.accounts.models import EmailUser - try: - UserDelegation.objects.get(organisation=organisation,user=user) - return True - except UserDelegation.DoesNotExist: - pass - try: - group = OrganisationAccessGroup.objects.first() - if group: - group.members.get(id=user.id) - return True - except EmailUser.DoesNotExist: - pass - if user.is_superuser: - return True - return False - - -def is_last_admin(organisation, user): - from commercialoperator.components.organisations.models import OrganisationContact - ''' A check for whether the user contact is the only administrator for the Organisation. ''' - _last_admin = False - try: - _admin_contacts = OrganisationContact.objects.filter(organisation_id=organisation, - user_status='active', - user_role='organisation_admin') - _is_admin = _admin_contacts.filter(email=user.email).exists() - if _is_admin and _admin_contacts.count() < 2: - _last_admin = True - except OrganisationContact.DoesNotExist: - _last_admin = False - return _last_admin - - -def can_admin_org(organisation,user): - from commercialoperator.components.organisations.models import Organisation, OrganisationAccessGroup,UserDelegation,OrganisationContact - from ledger.accounts.models import EmailUser - try: - org_contact=OrganisationContact.objects.get(organisation_id=organisation,email=user.email) - # if org_contact.can_edit - - return org_contact.can_edit - except OrganisationContact.DoesNotExist: - pass - return False - - -def can_relink(organisation, user): - from commercialoperator.components.organisations.models import OrganisationContact - ''' Check user contact can be relinked to the Organisation. ''' - _can_relink = False - try: - _can_relink = OrganisationContact.objects.filter(organisation_id=organisation.id, - email=user.email, - user_status='unlinked').exists() - except OrganisationContact.DoesNotExist: - _can_relink = False - return _can_relink - - -def can_approve(organisation, user): - from commercialoperator.components.organisations.models import OrganisationContact - ''' Check user contact linkage to the Organisation can be approved. ''' - _can_approve = False - try: - _can_approve = OrganisationContact.objects.filter(organisation_id=organisation.id, - email=user.email, - user_status__in=('declined', 'pending')).exists() - except OrganisationContact.DoesNotExist: - _can_approve = False - return _can_approve - - -def is_consultant(organisation,user): - from commercialoperator.components.organisations.models import Organisation, OrganisationAccessGroup,UserDelegation,OrganisationContact - from ledger.accounts.models import EmailUser - try: - org_contact=OrganisationContact.objects.get(organisation_id=organisation,email=user.email) - # if org_contact.can_edit - - return org_contact.check_consultant - except OrganisationContact.DoesNotExist: - pass - return False - -def random_generator(size=12, chars=string.digits): - return ''.join(random.choice(chars) for _ in range(size)) diff --git a/commercialoperator/components/organisations/views.py b/commercialoperator/components/organisations/views.py deleted file mode 100755 index 421a957382..0000000000 --- a/commercialoperator/components/organisations/views.py +++ /dev/null @@ -1,10 +0,0 @@ -from commercialoperator.components.organisations.models import Organisation -from reversion_compare.views import HistoryCompareDetailView - - -class OrganisationHistoryCompareView(HistoryCompareDetailView): - """ - View for reversion_compare - """ - model = Organisation - template_name = 'commercialoperator/reversion_history.html' diff --git a/commercialoperator/components/proposals/__init__.py b/commercialoperator/components/proposals/__init__.py deleted file mode 100755 index e69de29bb2..0000000000 diff --git a/commercialoperator/components/proposals/admin.py b/commercialoperator/components/proposals/admin.py deleted file mode 100755 index 3ce6422816..0000000000 --- a/commercialoperator/components/proposals/admin.py +++ /dev/null @@ -1,244 +0,0 @@ -from django.contrib import admin -from ledger.accounts.models import EmailUser -from commercialoperator.components.proposals import models -from commercialoperator.components.bookings.models import ApplicationFeeInvoice -from commercialoperator.components.proposals import forms -from commercialoperator.components.main.models import ( - ActivityMatrix, - SystemMaintenance, - ApplicationType, - Park, - #ParkPrice, - Trail, - ActivityType, - ActivityCategory, - Activity, - AccessType, - Section, - Zone, - RequiredDocument, - Question, - GlobalSettings -) -#from commercialoperator.components.main.models import Activity, SubActivityLevel1, SubActivityLevel2, SubCategory -from reversion.admin import VersionAdmin -from django.conf.urls import url -from django.template.response import TemplateResponse -from django.http import HttpResponse, HttpResponseRedirect -from commercialoperator.utils import create_helppage_object -# Register your models here. - -# Commented since COLS does not use schema - so will not require direct editing by user in Admin (although a ProposalType is still required for ApplicationType) -#@admin.register(models.ProposalType) -class ProposalTypeAdmin(admin.ModelAdmin): - list_display = ['name','description', 'version'] - ordering = ('name', '-version') - list_filter = ('name',) - #exclude=("site",) - -class ProposalDocumentInline(admin.TabularInline): - model = models.ProposalDocument - extra = 0 - -@admin.register(models.AmendmentReason) -class AmendmentReasonAdmin(admin.ModelAdmin): - list_display = ['reason'] - -@admin.register(models.Proposal) -class ProposalAdmin(VersionAdmin): - inlines =[ProposalDocumentInline,] - -@admin.register(models.ProposalAssessorGroup) -class ProposalAssessorGroupAdmin(admin.ModelAdmin): - list_display = ['name','default'] - filter_horizontal = ('members',) - form = forms.ProposalAssessorGroupAdminForm - readonly_fields = ['default'] - #readonly_fields = ['regions', 'activities'] - - def get_actions(self, request): - actions = super(ProposalAssessorGroupAdmin, self).get_actions(request) - if 'delete_selected' in actions: - del actions['delete_selected'] - return actions - - def has_delete_permission(self, request, obj=None): - if self.model.objects.count() == 1: - return False - return super(ProposalAssessorGroupAdmin, self).has_delete_permission(request, obj) - - def has_add_permission(self, request): - if self.model.objects.count() > 0: - return False - return super(ProposalAssessorGroupAdmin, self).has_add_permission(request) - - -@admin.register(models.ProposalApproverGroup) -class ProposalApproverGroupAdmin(admin.ModelAdmin): - list_display = ['name','default'] - filter_horizontal = ('members',) - form = forms.ProposalApproverGroupAdminForm - readonly_fields = ['default'] - #readonly_fields = ['default', 'regions', 'activities'] - - def get_actions(self, request): - actions = super(ProposalApproverGroupAdmin, self).get_actions(request) - if 'delete_selected' in actions: - del actions['delete_selected'] - return actions - - def has_delete_permission(self, request, obj=None): - if self.model.objects.count() == 1: - return False - return super(ProposalApproverGroupAdmin, self).has_delete_permission(request, obj) - - def has_add_permission(self, request): - if self.model.objects.count() > 0: - return False - return super(ProposalApproverGroupAdmin, self).has_add_permission(request) - -@admin.register(models.ProposalStandardRequirement) -class ProposalStandardRequirementAdmin(admin.ModelAdmin): - list_display = ['code','text','obsolete'] - -#@admin.register(models.HelpPage) -class HelpPageAdmin(admin.ModelAdmin): - list_display = ['application_type','help_type', 'description', 'version'] - form = forms.CommercialOperatorHelpPageAdminForm - change_list_template = "commercialoperator/help_page_changelist.html" - ordering = ('application_type', 'help_type', '-version') - list_filter = ('application_type', 'help_type') - - - def get_urls(self): - urls = super(HelpPageAdmin, self).get_urls() - my_urls = [ - url('create_commercialoperator_help/', self.admin_site.admin_view(self.create_commercialoperator_help)), - url('create_commercialoperator_help_assessor/', self.admin_site.admin_view(self.create_commercialoperator_help_assessor)), - ] - return my_urls + urls - - def create_commercialoperator_help(self, request): - create_helppage_object(application_type='T Class', help_type=models.HelpPage.HELP_TEXT_EXTERNAL) - return HttpResponseRedirect("../") - - def create_commercialoperator_help_assessor(self, request): - create_helppage_object(application_type='T Class', help_type=models.HelpPage.HELP_TEXT_INTERNAL) - return HttpResponseRedirect("../") - -@admin.register(models.ChecklistQuestion) -class ChecklistQuestionAdmin(admin.ModelAdmin): - list_display = ['text', 'list_type', 'obsolete','answer_type'] - ordering = ('list_type',) - -@admin.register(SystemMaintenance) -class SystemMaintenanceAdmin(admin.ModelAdmin): - list_display = ['name', 'description', 'start_date', 'end_date', 'duration'] - ordering = ('start_date',) - readonly_fields = ('duration',) - form = forms.SystemMaintenanceAdminForm - -@admin.register(ApplicationType) -class ApplicationTypeAdmin(admin.ModelAdmin): - list_display = ['name', 'order', 'visible', 'max_renewals', 'max_renewal_period', 'application_fee'] - ordering = ('order',) - -@admin.register(Park) -class ParkAdmin(admin.ModelAdmin): - list_display = ['name', 'district'] - #filter_horizontal = ('allowed_activities',) - filter_horizontal = ('allowed_activities', 'allowed_access') - ordering = ('name',) - -@admin.register(Trail) -class TrailAdmin(admin.ModelAdmin): - list_display = ['name', 'code'] - filter_horizontal = ('allowed_activities',) - ordering = ('name',) - -@admin.register(Section) -class SectionAdmin(admin.ModelAdmin): - list_display = ['name', 'visible', 'trail', 'doc_url'] - ordering = ('name',) - -@admin.register(Zone) -class ZoneAdmin(admin.ModelAdmin): - list_display = ['name', 'visible', 'park'] - filter_horizontal = ('allowed_activities',) - ordering = ('name',) - -@admin.register(models.Vehicle) -class VehicleAdmin(admin.ModelAdmin): - list_display = ['access_type','capacity', 'rego', 'license', 'rego_expiry'] - ordering = ('access_type',) - -@admin.register(models.Vessel) -class VesselAdmin(admin.ModelAdmin): - list_display = ['nominated_vessel','spv_no', 'hire_rego', 'craft_no', 'size', 'proposal'] - ordering = ('nominated_vessel',) - -@admin.register(RequiredDocument) -class RequiredDocumentAdmin(admin.ModelAdmin): - list_display = ['park', 'activity', 'question'] - #filter_horizontal = ('allowed_activities',) - #ordering = ('name',) - -@admin.register(ActivityCategory) -class ActivityCategory(admin.ModelAdmin): - list_display = ['name', 'visible', 'activity_type'] - ordering = ('name',) - -@admin.register(Activity) -class Activity(admin.ModelAdmin): - list_display = ['name', 'visible', 'activity_category'] - ordering = ('name',) - -@admin.register(AccessType) -class VehicleAdmin(admin.ModelAdmin): - list_display = ['id','name','visible'] - ordering = ('id',) - -@admin.register(GlobalSettings) -class GlobalSettingsAdmin(admin.ModelAdmin): - list_display = ['key', 'value'] - ordering = ('key',) - -@admin.register(models.ReferralRecipientGroup) -class ReferralRecipientGroupAdmin(admin.ModelAdmin): - filter_horizontal = ('members',) - list_display = ['name'] - exclude = ('site',) - actions = None - - def formfield_for_manytomany(self, db_field, request, **kwargs): - if db_field.name == "members": - kwargs["queryset"] = EmailUser.objects.filter(is_staff=True) - return super(ReferralRecipientGroupAdmin, self).formfield_for_manytomany(db_field, request, **kwargs) - -@admin.register(models.QAOfficerGroup) -class QAOfficerGroupAdmin(admin.ModelAdmin): - filter_horizontal = ('members',) - list_display = ['name'] - exclude = ('site',) - actions = None - - def formfield_for_manytomany(self, db_field, request, **kwargs): - if db_field.name == "members": - #kwargs["queryset"] = EmailUser.objects.filter(email__icontains='@dbca.wa.gov.au') - kwargs["queryset"] = EmailUser.objects.filter(is_staff=True) - return super(QAOfficerGroupAdmin, self).formfield_for_manytomany(db_field, request, **kwargs) - - #list_display = ['id','name', 'visible'] - list_display = ['name'] - ordering = ('id',) - - -@admin.register(Question) -class QuestionAdmin(admin.ModelAdmin): - list_display = ['question_text', 'answer_one', 'answer_two', 'answer_three', 'answer_four',] - ordering = ('question_text',) - -@admin.register(ApplicationFeeInvoice) -class SectionAdmin(admin.ModelAdmin): - list_display = [f.name for f in ApplicationFeeInvoice._meta.fields] - diff --git a/commercialoperator/components/proposals/api.py b/commercialoperator/components/proposals/api.py deleted file mode 100755 index 8a87d7be7f..0000000000 --- a/commercialoperator/components/proposals/api.py +++ /dev/null @@ -1,2102 +0,0 @@ -import traceback -import os -import base64 -import geojson -import json -from six.moves.urllib.parse import urlparse -from wsgiref.util import FileWrapper -from django.db.models import Q, Min -from django.db import transaction -from django.http import HttpResponse, HttpResponseRedirect -from django.core.files.base import ContentFile -from django.core.exceptions import ValidationError -from django.conf import settings -from django.contrib import messages -from django.views.decorators.http import require_http_methods -from django.views.decorators.csrf import csrf_exempt -from django.utils import timezone -from rest_framework import viewsets, serializers, status, generics, views -from rest_framework.decorators import detail_route, list_route, renderer_classes, parser_classes -from rest_framework.response import Response -from rest_framework.renderers import JSONRenderer -from rest_framework.permissions import IsAuthenticated, AllowAny, IsAdminUser, BasePermission -from rest_framework.pagination import PageNumberPagination -from collections import OrderedDict -from django.core.cache import cache -from ledger.accounts.models import EmailUser, Address -from ledger.address.models import Country -from datetime import datetime, timedelta, date -from commercialoperator.components.proposals.utils import save_proponent_data,save_assessor_data, proposal_submit -from commercialoperator.components.proposals.models import searchKeyWords, search_reference, ProposalUserAction -from commercialoperator.utils import missing_required_fields - -from django.urls import reverse -from django.shortcuts import render, redirect, get_object_or_404 -from commercialoperator.components.main.models import Document, Region, District, Tenure, ApplicationType, RequiredDocument -from commercialoperator.components.proposals.models import ( - ProposalType, - Proposal, - ProposalDocument, - Referral, - ReferralRecipientGroup, - QAOfficerGroup, - QAOfficerReferral, - ProposalRequirement, - ProposalStandardRequirement, - AmendmentRequest, - AmendmentReason, - Vehicle, - Vessel, - ProposalOtherDetails, - ProposalAccreditation, - ChecklistQuestion, - ProposalAssessment, - ProposalAssessmentAnswer, - RequirementDocument, -) -from commercialoperator.components.proposals.serializers import ( - SendReferralSerializer, - ProposalTypeSerializer, - ProposalSerializer, - InternalProposalSerializer, - SaveProposalSerializer, - DTProposalSerializer, - ProposalUserActionSerializer, - ProposalLogEntrySerializer, - DTReferralSerializer, - ReferralSerializer, - QAOfficerReferralSerializer, - ReferralProposalSerializer, - ProposalRequirementSerializer, - ProposalStandardRequirementSerializer, - ProposedApprovalSerializer, - PropedDeclineSerializer, - AmendmentRequestSerializer, - SearchReferenceSerializer, - SearchKeywordSerializer, - ListProposalSerializer, - ProposalReferralSerializer, - AmendmentRequestDisplaySerializer, - SaveVehicleSerializer, - VehicleSerializer, - VesselSerializer, - OnHoldSerializer, - ProposalOtherDetailsSerializer, - SaveProposalOtherDetailsSerializer, - ProposalParkSerializer, - ChecklistQuestionSerializer, - ProposalAssessmentSerializer, - ProposalAssessmentAnswerSerializer -) -from commercialoperator.components.bookings.models import Booking, ParkBooking, BookingInvoice -from commercialoperator.components.approvals.models import Approval -from commercialoperator.components.approvals.serializers import ApprovalSerializer -from commercialoperator.components.compliances.models import Compliance -from commercialoperator.components.compliances.serializers import ComplianceSerializer -from ledger.payments.invoice.models import Invoice - -from commercialoperator.helpers import is_customer, is_internal -from django.core.files.base import ContentFile -from django.core.files.storage import default_storage -from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination -from rest_framework_datatables.pagination import DatatablesPageNumberPagination -from rest_framework_datatables.filters import DatatablesFilterBackend -from rest_framework_datatables.renderers import DatatablesRenderer -from rest_framework.filters import BaseFilterBackend -import reversion -from reversion.models import Version - -import logging -logger = logging.getLogger(__name__) - - -class GetProposalType(views.APIView): - renderer_classes = [JSONRenderer, ] - - def get(self, request, format=None): - _type = ProposalType.objects.first() - if _type: - serializer = ProposalTypeSerializer(_type) - return Response(serializer.data) - else: - return Response({'error': 'There is currently no application type.'}, status=status.HTTP_404_NOT_FOUND) - -class GetEmptyList(views.APIView): - renderer_classes = [JSONRenderer, ] - - def get(self, request, format=None): - return Response([]) - -#class DatatablesFilterBackend(BaseFilterBackend): -# -# def filter_queryset(self, request, queryset, view): -# queryset = super(DatatablesFilterBackend, self).filter_queryset(request, queryset, view) -# return queryset - -''' -1. internal_proposal.json -2. regions.json -3. trails.json -4. vehicles.json -5. access_types.json -6. required_documents.json -7. land_activities.json -8. vessels.json -9. marine_activities.json -10. marine_parks.json -11. accreditation_choices.json -12. licence_period_choices.json -13. global_settings.json -14. questions.json -15. amendment_request_reason_choices.json -16. contacts.json - -''' -class ProposalFilterBackend(DatatablesFilterBackend): - """ - Custom filters - """ - - def filter_queryset(self, request, queryset, view): - total_count = queryset.count() - - def get_choice(status, choices=Proposal.PROCESSING_STATUS_CHOICES): - for i in choices: - if i[1]==status: - return i[0] - return None - - # on the internal dashboard, the Region filter is multi-select - have to use the custom filter below - regions = request.GET.get('regions') - if regions: - if queryset.model is Proposal: - queryset = queryset.filter(region__name__iregex=regions.replace(',', '|')) - elif queryset.model is Referral or queryset.model is Compliance: - queryset = queryset.filter(proposal__region__name__iregex=regions.replace(',', '|')) - - # on the internal dashboard, the Payment Status filter is a property field (not a DB field) - have to use the custom filter below - if queryset.model is Booking: - park = request.GET.get('park') - payment_method = request.GET.get('payment_method') - payment_status = request.GET.get('payment_status') - - if park: - queryset = queryset.filter(park_bookings__park__id__in=[park]) - - if payment_method: - #queryset = queryset.filter(invoices__payment_method=payment_method) - queryset = queryset.filter(Q(invoices__payment_method=payment_method) | Q(booking_type=Booking.BOOKING_TYPE_MONTHLY_INVOICING)) - - if payment_status: - if payment_status.lower() == 'overdue': - refs = [i.booking.invoices.last().invoice_reference for i in ParkBooking.objects.all() if i.booking and i.booking.invoices.last() and i.booking.invoices.last().overdue] - queryset = queryset.filter(invoices__invoice_reference__in=refs) - else: - refs = [i.booking.invoices.last().invoice_reference for i in ParkBooking.objects.all() if i.booking and i.booking.invoices.last()] - filtered_refs = [i.reference for i in Invoice.objects.filter(reference__in=refs) if i.payment_status==payment_status] - queryset = queryset.filter(invoices__invoice_reference__in=filtered_refs)#.distinct('id') - - date_from = request.GET.get('date_from') - date_to = request.GET.get('date_to') - if queryset.model is Proposal: - if date_from: - queryset = queryset.filter(lodgement_date__gte=date_from) - - if date_to: - queryset = queryset.filter(lodgement_date__lte=date_to) - elif queryset.model is Approval: - if date_from: - queryset = queryset.filter(start_date__gte=date_from) - - if date_to: - queryset = queryset.filter(expiry_date__lte=date_to) - elif queryset.model is Compliance: - if date_from: - queryset = queryset.filter(due_date__gte=date_from) - - if date_to: - queryset = queryset.filter(due_date__lte=date_to) - elif queryset.model is Referral: - if date_from: - queryset = queryset.filter(proposal__lodgement_date__gte=date_from) - - if date_to: - queryset = queryset.filter(proposal__lodgement_date__lte=date_to) - elif queryset.model is Booking: - if date_from and date_to: - queryset = queryset.filter(park_bookings__arrival__range=[date_from, date_to]) - elif date_from: - queryset = queryset.filter(park_bookings__arrival__gte=date_from) - elif date_to: - queryset = queryset.filter(park_bookings__arrival__lte=date_to) - - queryset = super(ProposalFilterBackend, self).filter_queryset(request, queryset, view) - setattr(view, '_datatables_total_count', total_count) - return queryset - -class ProposalRenderer(DatatablesRenderer): - def render(self, data, accepted_media_type=None, renderer_context=None): - if 'view' in renderer_context and hasattr(renderer_context['view'], '_datatables_total_count'): - data['recordsTotal'] = renderer_context['view']._datatables_total_count - #data.pop('recordsTotal') - #data.pop('recordsFiltered') - return super(ProposalRenderer, self).render(data, accepted_media_type, renderer_context) - - - -#from django.utils.decorators import method_decorator -#from django.views.decorators.cache import cache_page -class ProposalPaginatedViewSet(viewsets.ModelViewSet): - #queryset = Proposal.objects.all() - #filter_backends = (DatatablesFilterBackend,) - filter_backends = (ProposalFilterBackend,) - pagination_class = DatatablesPageNumberPagination - renderer_classes = (ProposalRenderer,) - queryset = Proposal.objects.none() - serializer_class = ListProposalSerializer - page_size = 10 - -# @method_decorator(cache_page(60)) -# def dispatch(self, *args, **kwargs): -# return super(ListProposalViewSet, self).dispatch(*args, **kwargs) - - @property - def excluded_type(self): - try: - return ApplicationType.objects.get(name='E Class') - except: - return ApplicationType.objects.none() - - def get_queryset(self): - user = self.request.user - if is_internal(self.request): #user.is_authenticated(): - qs= Proposal.objects.all().exclude(application_type=self.excluded_type) - return qs.exclude(migrated=True) - elif is_customer(self.request): - user_orgs = [org.id for org in user.commercialoperator_organisations.all()] - qs= Proposal.objects.filter( Q(org_applicant_id__in = user_orgs) | Q(submitter = user) ).exclude(application_type=self.excluded_type) - return qs.exclude(migrated=True) - return Proposal.objects.none() - -# def filter_queryset(self, request, queryset, view): -# return self.filter_backends[0]().filter_queryset(self.request, queryset, view) - #return super(ProposalPaginatedViewSet, self).filter_queryset(request, queryset, view) - -# def list(self, request, *args, **kwargs): -# response = super(ProposalPaginatedViewSet, self).list(request, args, kwargs) -# -# # Add extra data to response.data -# #response.data['regions'] = self.get_queryset().filter(region__isnull=False).values_list('region__name', flat=True).distinct() -# return response - - @list_route(methods=['GET',]) - def proposals_internal(self, request, *args, **kwargs): - """ - Used by the internal dashboard - - http://localhost:8499/api/proposal_paginated/proposal_paginated_internal/?format=datatables&draw=1&length=2 - """ - qs = self.get_queryset() - #qs = self.filter_queryset(self.request, qs, self) - qs = self.filter_queryset(qs) - - # on the internal organisations dashboard, filter the Proposal/Approval/Compliance datatables by applicant/organisation - applicant_id = request.GET.get('org_id') - if applicant_id: - qs = qs.filter(org_applicant_id=applicant_id) - submitter_id = request.GET.get('submitter_id', None) - if submitter_id: - qs = qs.filter(submitter_id=submitter_id) - - self.paginator.page_size = qs.count() - result_page = self.paginator.paginate_queryset(qs, request) - serializer = ListProposalSerializer(result_page, context={'request':request}, many=True) - return self.paginator.get_paginated_response(serializer.data) - - @list_route(methods=['GET',]) - def referrals_internal(self, request, *args, **kwargs): - """ - Used by the internal dashboard - - http://localhost:8499/api/proposal_paginated/referrals_internal/?format=datatables&draw=1&length=2 - """ - self.serializer_class = ReferralSerializer - #qs = Referral.objects.filter(referral=request.user) if is_internal(self.request) else Referral.objects.none() - qs = Referral.objects.filter(referral_group__in=request.user.referralrecipientgroup_set.all()) if is_internal(self.request) else Referral.objects.none() - #qs = self.filter_queryset(self.request, qs, self) - qs = self.filter_queryset(qs) - - self.paginator.page_size = qs.count() - result_page = self.paginator.paginate_queryset(qs, request) - serializer = DTReferralSerializer(result_page, context={'request':request}, many=True) - return self.paginator.get_paginated_response(serializer.data) - - @list_route(methods=['GET',]) - def qaofficer_info(self, request, *args, **kwargs): - """ - Used by the internal dashboard - - http://localhost:8499/api/proposal_paginated/qaofficer_internal/?format=datatables&draw=1&length=2 - """ - qa_officers = QAOfficerGroup.objects.get(default=True).members.all().values_list('email', flat=True) - if request.user.email in qa_officers: - return Response({'QA_Officer': True}) - else: - return Response({'QA_Officer': False}) - - - @list_route(methods=['GET',]) - def qaofficer_internal(self, request, *args, **kwargs): - """ - Used by the internal dashboard - - http://localhost:8499/api/proposal_paginated/qaofficer_internal/?format=datatables&draw=1&length=2 - """ - qa_officers = QAOfficerGroup.objects.get(default=True).members.all().values_list('email', flat=True) - if request.user.email not in qa_officers: - return self.paginator.get_paginated_response([]) - - qs = self.get_queryset() - qs = qs.filter(qaofficer_referrals__gt=0) - #qs = self.filter_queryset(self.request, qs, self) - qs = self.filter_queryset(qs) - - # on the internal organisations dashboard, filter the Proposal/Approval/Compliance datatables by applicant/organisation - applicant_id = request.GET.get('org_id') - if applicant_id: - qs = qs.filter(org_applicant_id=applicant_id) - submitter_id = request.GET.get('submitter_id', None) - if submitter_id: - qs = qs.filter(submitter_id=submitter_id) - - self.paginator.page_size = qs.count() - result_page = self.paginator.paginate_queryset(qs, request) - serializer = ListProposalSerializer(result_page, context={'request':request}, many=True) - return self.paginator.get_paginated_response(serializer.data) - - - @list_route(methods=['GET',]) - def proposals_external(self, request, *args, **kwargs): - """ - Used by the external dashboard - - http://localhost:8499/api/proposal_paginated/proposal_paginated_external/?format=datatables&draw=1&length=2 - """ - qs = self.get_queryset().exclude(processing_status='discarded') - #qs = self.filter_queryset(self.request, qs, self) - qs = self.filter_queryset(qs) - - # on the internal organisations dashboard, filter the Proposal/Approval/Compliance datatables by applicant/organisation - applicant_id = request.GET.get('org_id') - if applicant_id: - qs = qs.filter(org_applicant_id=applicant_id) - submitter_id = request.GET.get('submitter_id', None) - if submitter_id: - qs = qs.filter(submitter_id=submitter_id) - - self.paginator.page_size = qs.count() - result_page = self.paginator.paginate_queryset(qs, request) - serializer = ListProposalSerializer(result_page, context={'request':request}, many=True) - return self.paginator.get_paginated_response(serializer.data) - - -class VersionableModelViewSetMixin(viewsets.ModelViewSet): - @detail_route(methods=['GET',]) - def history(self, request, *args, **kwargs): - _object = self.get_object() - #_versions = reversion.get_for_object(_object) - _versions = Version.objects.get_for_object(_object) - - _context = { - 'request': request - } - - #_version_serializer = VersionSerializer(_versions, many=True, context=_context) - _version_serializer = ProposalSerializer([v.object for v in _versions], many=True, context=_context) - # TODO - # check pagination - return Response(_version_serializer.data) - -class ProposalSubmitViewSet(viewsets.ModelViewSet): - queryset = Proposal.objects.none() - serializer_class = ProposalSerializer - lookup_field = 'id' - - @property - def excluded_type(self): - try: - return ApplicationType.objects.get(name='E Class') - except: - return ApplicationType.objects.none() - - def get_queryset(self): - user = self.request.user - if is_internal(self.request): #user.is_authenticated(): - return Proposal.objects.all().exclude(application_type=self.excluded_type) - #return Proposal.objects.filter(region__isnull=False) - elif is_customer(self.request): - user_orgs = [org.id for org in user.commercialoperator_organisations.all()] - queryset = Proposal.objects.filter( Q(org_applicant_id__in = user_orgs) | Q(submitter = user) ) - #queryset = Proposal.objects.filter(region__isnull=False).filter( Q(applicant_id__in = user_orgs) | Q(submitter = user) ) - return queryset.exclude(application_type=self.excluded_type) - logger.warn("User is neither customer nor internal user: {} <{}>".format(user.get_full_name(), user.email)) - return Proposal.objects.none() - -# def perform_create(self, serializer): -# serializer.partial = True -# serializer.save(created_by=self.request.user) - - @detail_route(methods=['post']) - @renderer_classes((JSONRenderer,)) - def submit(self, request, *args, **kwargs): - try: - instance = self.get_object() - #instance.submit(request,self) - #instance.save() - serializer = self.get_serializer(instance) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - if hasattr(e,'error_dict'): - raise serializers.ValidationError(repr(e.error_dict)) - else: - raise serializers.ValidationError(repr(e[0].encode('utf-8'))) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - -class ProposalParkViewSet(viewsets.ModelViewSet): - """ - Similar to ProposalViewSet, except get_queryset include migrated_licences - """ - queryset = Proposal.objects.none() - serializer_class = ProposalSerializer - lookup_field = 'id' - - @property - def excluded_type(self): - try: - return ApplicationType.objects.get(name='E Class') - except: - return ApplicationType.objects.none() - - def get_queryset(self): - """ - Now excludes parks with free admission - """ - user = self.request.user - if is_internal(self.request): #user.is_authenticated(): - qs= Proposal.objects.all().exclude(application_type=self.excluded_type) - return qs #.exclude(migrated=True) - #return Proposal.objects.filter(region__isnull=False) - elif is_customer(self.request): - user_orgs = [org.id for org in user.commercialoperator_organisations.all()] - queryset = Proposal.objects.filter( Q(org_applicant_id__in = user_orgs) | Q(submitter = user) ) #.exclude(migrated=True) - return queryset.exclude(application_type=self.excluded_type) - logger.warn("User is neither customer nor internal user: {} <{}>".format(user.get_full_name(), user.email)) - return Proposal.objects.none() - - @detail_route(methods=['GET',]) - def proposal_parks(self, request, *args, **kwargs): - instance = self.get_object() - serializer = ProposalParkSerializer(instance,context={'request':request}) - return Response(serializer.data) - - - - -class ProposalViewSet(viewsets.ModelViewSet): -#class ProposalViewSet(VersionableModelViewSetMixin): - #queryset = Proposal.objects.all() - queryset = Proposal.objects.none() - serializer_class = ProposalSerializer - lookup_field = 'id' - - @property - def excluded_type(self): - try: - return ApplicationType.objects.get(name='E Class') - except: - return ApplicationType.objects.none() - - def get_queryset(self): - user = self.request.user - if is_internal(self.request): #user.is_authenticated(): - qs= Proposal.objects.all().exclude(application_type=self.excluded_type) - return qs.exclude(migrated=True) - #return Proposal.objects.filter(region__isnull=False) - elif is_customer(self.request): - user_orgs = [org.id for org in user.commercialoperator_organisations.all()] - queryset = Proposal.objects.filter( Q(org_applicant_id__in = user_orgs) | Q(submitter = user) ).exclude(migrated=True) - #queryset = Proposal.objects.filter(region__isnull=False).filter( Q(applicant_id__in = user_orgs) | Q(submitter = user) ) - return queryset.exclude(application_type=self.excluded_type) - logger.warn("User is neither customer nor internal user: {} <{}>".format(user.get_full_name(), user.email)) - return Proposal.objects.none() - - @list_route(methods=['GET',]) - def filter_list(self, request, *args, **kwargs): - """ Used by the internal/external dashboard filters """ - region_qs = self.get_queryset().filter(region__isnull=False).values_list('region__name', flat=True).distinct() - #district_qs = self.get_queryset().filter(district__isnull=False).values_list('district__name', flat=True).distinct() - activity_qs = self.get_queryset().filter(activity__isnull=False).values_list('activity', flat=True).distinct() - submitter_qs = self.get_queryset().filter(submitter__isnull=False).distinct('submitter__email').values_list('submitter__first_name','submitter__last_name','submitter__email') - submitters = [dict(email=i[2], search_term='{} {} ({})'.format(i[0], i[1], i[2])) for i in submitter_qs] - data = dict( - regions=region_qs, - #districts=district_qs, - activities=activity_qs, - submitters=submitters, - #processing_status_choices = [i[1] for i in Proposal.PROCESSING_STATUS_CHOICES], - #processing_status_id_choices = [i[0] for i in Proposal.PROCESSING_STATUS_CHOICES], - #customer_status_choices = [i[1] for i in Proposal.CUSTOMER_STATUS_CHOICES], - approval_status_choices = [i[1] for i in Approval.STATUS_CHOICES], - ) - return Response(data) - - @detail_route(methods=['GET',]) - def compare_list(self, request, *args, **kwargs): - """ Returns the reversion-compare urls --> list""" - current_revision_id = Version.objects.get_for_object(self.get_object()).first().revision_id - versions = Version.objects.get_for_object(self.get_object()).select_related("revision__user").filter(Q(revision__comment__icontains='status') | Q(revision_id=current_revision_id)) - version_ids = [i.id for i in versions] - urls = ['?version_id2={}&version_id1={}'.format(version_ids[0], version_ids[i+1]) for i in range(len(version_ids)-1)] - return Response(urls) - - - @detail_route(methods=['POST']) - @renderer_classes((JSONRenderer,)) - def process_document(self, request, *args, **kwargs): - try: - instance = self.get_object() - action = request.POST.get('action') - section = request.POST.get('input_name') - if action == 'list' and 'input_name' in request.POST: - pass - - elif action == 'delete' and 'document_id' in request.POST: - document_id = request.POST.get('document_id') - document = instance.documents.get(id=document_id) - - if document._file and os.path.isfile(document._file.path) and document.can_delete: - os.remove(document._file.path) - - document.delete() - instance.save(version_comment='Approval File Deleted: {}'.format(document.name)) # to allow revision to be added to reversion history - #instance.current_proposal.save(version_comment='File Deleted: {}'.format(document.name)) # to allow revision to be added to reversion history - - elif action == 'save' and 'input_name' in request.POST and 'filename' in request.POST: - proposal_id = request.POST.get('proposal_id') - filename = request.POST.get('filename') - _file = request.POST.get('_file') - if not _file: - _file = request.FILES.get('_file') - - document = instance.documents.get_or_create(input_name=section, name=filename)[0] - path = default_storage.save('{}/proposals/{}/documents/{}'.format(settings.MEDIA_APP_DIR, proposal_id, filename), ContentFile(_file.read())) - - document._file = path - document.save() - instance.save(version_comment='File Added: {}'.format(filename)) # to allow revision to be added to reversion history - #instance.current_proposal.save(version_comment='File Added: {}'.format(filename)) # to allow revision to be added to reversion history - - return Response( [dict(input_name=d.input_name, name=d.name,file=d._file.url, id=d.id, can_delete=d.can_delete) for d in instance.documents.filter(input_name=section) if d._file] ) - - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - if hasattr(e,'error_dict'): - raise serializers.ValidationError(repr(e.error_dict)) - else: - raise serializers.ValidationError(repr(e[0].encode('utf-8'))) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['POST']) - @renderer_classes((JSONRenderer,)) - def process_onhold_document(self, request, *args, **kwargs): - try: - instance = self.get_object() - action = request.POST.get('action') - section = request.POST.get('input_name') - if action == 'list' and 'input_name' in request.POST: - pass - -# elif action == 'delete' and 'document_id' in request.POST: -# document_id = request.POST.get('document_id') -# document = instance.onhold_documents.get(id=document_id) -# -# if document._file and os.path.isfile(document._file.path) and document.can_delete: -# os.remove(document._file.path) -# -# document.delete() -# instance.save(version_comment='OnHold File Deleted: {}'.format(document.name)) # to allow revision to be added to reversion history -# #instance.current_proposal.save(version_comment='File Deleted: {}'.format(document.name)) # to allow revision to be added to reversion history - - elif action == 'delete' and 'document_id' in request.POST: - document_id = request.POST.get('document_id') - document = instance.onhold_documents.get(id=document_id) - - document.visible = False - document.save() - instance.save(version_comment='OnHold File Hidden: {}'.format(document.name)) # to allow revision to be added to reversion history - #instance.current_proposal.save(version_comment='File Deleted: {}'.format(document.name)) # to allow revision to be added to reversion history - - elif action == 'save' and 'input_name' in request.POST and 'filename' in request.POST: - proposal_id = request.POST.get('proposal_id') - filename = request.POST.get('filename') - _file = request.POST.get('_file') - if not _file: - _file = request.FILES.get('_file') - - document = instance.onhold_documents.get_or_create(input_name=section, name=filename)[0] - path = default_storage.save('{}/proposals/{}/onhold/{}'.format(settings.MEDIA_APP_DIR, proposal_id, filename), ContentFile(_file.read())) - - document._file = path - document.save() - instance.save(version_comment='On Hold File Added: {}'.format(filename)) # to allow revision to be added to reversion history - #instance.current_proposal.save(version_comment='File Added: {}'.format(filename)) # to allow revision to be added to reversion history - - return Response( [dict(input_name=d.input_name, name=d.name,file=d._file.url, id=d.id, can_delete=d.can_delete) for d in instance.onhold_documents.filter(input_name=section, visible=True) if d._file] ) - - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - if hasattr(e,'error_dict'): - raise serializers.ValidationError(repr(e.error_dict)) - else: - raise serializers.ValidationError(repr(e[0].encode('utf-8'))) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['POST']) - @renderer_classes((JSONRenderer,)) - def process_qaofficer_document(self, request, *args, **kwargs): - try: - instance = self.get_object() - action = request.POST.get('action') - section = request.POST.get('input_name') - if action == 'list' and 'input_name' in request.POST: - pass - - elif action == 'delete' and 'document_id' in request.POST: - document_id = request.POST.get('document_id') - document = instance.qaofficer_documents.get(id=document_id) - - document.visible = False - document.save() - instance.save(version_comment='QA Officer File Hidden: {}'.format(document.name)) # to allow revision to be added to reversion history - - elif action == 'save' and 'input_name' in request.POST and 'filename' in request.POST: - proposal_id = request.POST.get('proposal_id') - filename = request.POST.get('filename') - _file = request.POST.get('_file') - if not _file: - _file = request.FILES.get('_file') - - document = instance.qaofficer_documents.get_or_create(input_name=section, name=filename)[0] - path = default_storage.save('{}/proposals/{}/qaofficer/{}'.format(settings.MEDIA_APP_DIR, proposal_id, filename), ContentFile(_file.read())) - - document._file = path - document.save() - instance.save(version_comment='QA Officer File Added: {}'.format(filename)) # to allow revision to be added to reversion history - #instance.current_proposal.save(version_comment='File Added: {}'.format(filename)) # to allow revision to be added to reversion history - - return Response( [dict(input_name=d.input_name, name=d.name,file=d._file.url, id=d.id, can_delete=d.can_delete) for d in instance.qaofficer_documents.filter(input_name=section, visible=True) if d._file] ) - - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - if hasattr(e,'error_dict'): - raise serializers.ValidationError(repr(e.error_dict)) - else: - raise serializers.ValidationError(repr(e[0].encode('utf-8'))) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - -# def list(self, request, *args, **kwargs): -# #queryset = self.get_queryset() -# #serializer = DTProposalSerializer(queryset, many=True) -# #serializer = DTProposalSerializer(self.get_queryset(), many=True) -# serializer = ListProposalSerializer(self.get_queryset(), context={'request':request}, many=True) -# return Response(serializer.data) - - @list_route(methods=['GET',]) - def list_paginated(self, request, *args, **kwargs): - """ - https://stackoverflow.com/questions/29128225/django-rest-framework-3-1-breaks-pagination-paginationserializer - """ - proposals = self.get_queryset() - paginator = PageNumberPagination() - #paginator = LimitOffsetPagination() - paginator.page_size = 5 - result_page = paginator.paginate_queryset(proposals, request) - serializer = ListProposalSerializer(result_page, context={'request':request}, many=True) - return paginator.get_paginated_response(serializer.data) - - - @detail_route(methods=['GET',]) - def action_log(self, request, *args, **kwargs): - try: - instance = self.get_object() - qs = instance.action_logs.all() - serializer = ProposalUserActionSerializer(qs,many=True) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['GET',]) - def comms_log(self, request, *args, **kwargs): - try: - instance = self.get_object() - qs = instance.comms_logs.all() - serializer = ProposalLogEntrySerializer(qs,many=True) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['POST',]) - @renderer_classes((JSONRenderer,)) - def add_comms_log(self, request, *args, **kwargs): - try: - with transaction.atomic(): - instance = self.get_object() - request.data['proposal'] = u'{}'.format(instance.id) - request.data['staff'] = u'{}'.format(request.user.id) - serializer = ProposalLogEntrySerializer(data=request.data) - serializer.is_valid(raise_exception=True) - comms = serializer.save() - # Save the files - for f in request.FILES: - document = comms.documents.create() - document.name = str(request.FILES[f]) - document._file = request.FILES[f] - document.save() - # End Save Documents - - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['GET',]) - def requirements(self, request, *args, **kwargs): - try: - instance = self.get_object() - #qs = instance.requirements.all() - qs = instance.requirements.all().exclude(is_deleted=True) - serializer = ProposalRequirementSerializer(qs,many=True, context={'request':request}) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['GET',]) - def amendment_request(self, request, *args, **kwargs): - try: - instance = self.get_object() - qs = instance.amendment_requests - qs = qs.filter(status = 'requested') - serializer = AmendmentRequestDisplaySerializer(qs,many=True) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['GET',]) - def vehicles(self, request, *args, **kwargs): - try: - instance = self.get_object() - qs = instance.vehicles - #qs = qs.filter(status = 'requested') - serializer = VehicleSerializer(qs,many=True) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['GET',]) - def vessels(self, request, *args, **kwargs): - try: - instance = self.get_object() - qs = instance.vessels - #qs = qs.filter(status = 'requested') - serializer = VesselSerializer(qs,many=True) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - - @list_route(methods=['GET',]) - def user_list(self, request, *args, **kwargs): - qs = self.get_queryset().exclude(processing_status='discarded') - #serializer = DTProposalSerializer(qs, many=True) - serializer = ListProposalSerializer(qs,context={'request':request}, many=True) - return Response(serializer.data) - - @list_route(methods=['GET',]) - def user_list_paginated(self, request, *args, **kwargs): - """ - Placing Paginator class here (instead of settings.py) allows specific method for desired behaviour), - otherwise all serializers will use the default pagination class - - https://stackoverflow.com/questions/29128225/django-rest-framework-3-1-breaks-pagination-paginationserializer - """ - proposals = self.get_queryset().exclude(processing_status='discarded') - paginator = DatatablesPageNumberPagination() - paginator.page_size = proposals.count() - result_page = paginator.paginate_queryset(proposals, request) - serializer = ListProposalSerializer(result_page, context={'request':request}, many=True) - return paginator.get_paginated_response(serializer.data) - - @list_route(methods=['GET',]) - def list_paginated(self, request, *args, **kwargs): - """ - Placing Paginator class here (instead of settings.py) allows specific method for desired behaviour), - otherwise all serializers will use the default pagination class - - https://stackoverflow.com/questions/29128225/django-rest-framework-3-1-breaks-pagination-paginationserializer - """ - proposals = self.get_queryset() - paginator = DatatablesPageNumberPagination() - paginator.page_size = proposals.count() - result_page = paginator.paginate_queryset(proposals, request) - serializer = ListProposalSerializer(result_page, context={'request':request}, many=True) - return paginator.get_paginated_response(serializer.data) - - #Documents on Activities(land)and Activities(Marine) tab for T-Class related to required document questions - @detail_route(methods=['POST']) - @renderer_classes((JSONRenderer,)) - def process_required_document(self, request, *args, **kwargs): - try: - instance = self.get_object() - action = request.POST.get('action') - section = request.POST.get('input_name') - required_doc_id=request.POST.get('required_doc_id') - if action == 'list' and 'required_doc_id' in request.POST: - pass - - elif action == 'delete' and 'document_id' in request.POST: - document_id = request.POST.get('document_id') - document = instance.required_documents.get(id=document_id) - - if document._file and os.path.isfile(document._file.path) and document.can_delete: - os.remove(document._file.path) - - document.delete() - instance.save(version_comment='Required document File Deleted: {}'.format(document.name)) # to allow revision to be added to reversion history - #instance.current_proposal.save(version_comment='File Deleted: {}'.format(document.name)) # to allow revision to be added to reversion history - - elif action == 'save' and 'input_name' and 'required_doc_id' in request.POST and 'filename' in request.POST: - proposal_id = request.POST.get('proposal_id') - filename = request.POST.get('filename') - _file = request.POST.get('_file') - if not _file: - _file = request.FILES.get('_file') - - required_doc_instance=RequiredDocument.objects.get(id=required_doc_id) - document = instance.required_documents.get_or_create(input_name=section, name=filename, required_doc=required_doc_instance)[0] - path = default_storage.save('{}/proposals/{}/required_documents/{}'.format(settings.MEDIA_APP_DIR, proposal_id, filename), ContentFile(_file.read())) - - document._file = path - document.save() - instance.save(version_comment='File Added: {}'.format(filename)) # to allow revision to be added to reversion history - #instance.current_proposal.save(version_comment='File Added: {}'.format(filename)) # to allow revision to be added to reversion history - - return Response( [dict(input_name=d.input_name, name=d.name,file=d._file.url, id=d.id, can_delete=d.can_delete) for d in instance.required_documents.filter(required_doc=required_doc_id) if d._file] ) - - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - if hasattr(e,'error_dict'): - raise serializers.ValidationError(repr(e.error_dict)) - else: - raise serializers.ValidationError(repr(e[0].encode('utf-8'))) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - - @detail_route(methods=['GET',]) - def internal_proposal(self, request, *args, **kwargs): - instance = self.get_object() - serializer = InternalProposalSerializer(instance,context={'request':request}) - return Response(serializer.data) - -# @detail_route(methods=['GET',]) -# def proposal_parks(self, request, *args, **kwargs): -# instance = self.get_object() -# serializer = ProposalParkSerializer(instance,context={'request':request}) -# return Response(serializer.data) - - -# @detail_route(methods=['post']) -# @renderer_classes((JSONRenderer,)) -# def _submit(self, request, *args, **kwargs): -# try: -# instance = self.get_object() -# save_proponent_data(instance,request,self) -# missing_fields = missing_required_fields(instance) -# -# if False: #missing_fields: -# #if missing_fields: -# return Response({'missing_fields': missing_fields}) -# else: -# #raise serializers.ValidationError(repr({'abcde': 123, 'missing_fields':True})) -# instance.submit(request,self) -# serializer = self.get_serializer(instance) -# return Response(serializer.data) -# except serializers.ValidationError: -# print(traceback.print_exc()) -# raise -# except ValidationError as e: -# if hasattr(e,'error_dict'): -# raise serializers.ValidationError(repr(e.error_dict)) -# else: -# raise serializers.ValidationError(repr(e[0].encode('utf-8'))) -# except Exception as e: -# print(traceback.print_exc()) -# raise serializers.ValidationError(str(e)) - - - @detail_route(methods=['post']) - @renderer_classes((JSONRenderer,)) - def submit(self, request, *args, **kwargs): - try: - instance = self.get_object() - #instance.submit(request,self) - proposal_submit(instance, request) - instance.save() - serializer = self.get_serializer(instance) - return Response(serializer.data) - #return redirect(reverse('external')) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - if hasattr(e,'error_dict'): - raise serializers.ValidationError(repr(e.error_dict)) - else: - raise serializers.ValidationError(repr(e[0].encode('utf-8'))) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - -# @detail_route(methods=['post']) -# @renderer_classes((JSONRenderer,)) -# def update_files(self, request, *args, **kwargs): -# try: -# instance = self.get_object() -# instance.update(request,self) -# instance.save() -# serializer = self.get_serializer(instance) -# return Response(serializer.data) -# #return redirect(reverse('external')) -# except serializers.ValidationError: -# print(traceback.print_exc()) -# raise -# except ValidationError as e: -# if hasattr(e,'error_dict'): -# raise serializers.ValidationError(repr(e.error_dict)) -# else: -# raise serializers.ValidationError(repr(e[0].encode('utf-8'))) -# except Exception as e: -# print(traceback.print_exc()) -# raise serializers.ValidationError(str(e)) - - - @detail_route(methods=['GET',]) - def assign_request_user(self, request, *args, **kwargs): - try: - instance = self.get_object() - instance.assign_officer(request,request.user) - serializer = InternalProposalSerializer(instance,context={'request':request}) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['POST',]) - def assign_to(self, request, *args, **kwargs): - try: - instance = self.get_object() - user_id = request.data.get('assessor_id',None) - user = None - if not user_id: - raise serializers.ValidationError('An assessor id is required') - try: - user = EmailUser.objects.get(id=user_id) - except EmailUser.DoesNotExist: - raise serializers.ValidationError('A user with the id passed in does not exist') - instance.assign_officer(request,user) - serializer = InternalProposalSerializer(instance,context={'request':request}) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['GET',]) - def unassign(self, request, *args, **kwargs): - try: - instance = self.get_object() - instance.unassign(request) - serializer = InternalProposalSerializer(instance,context={'request':request}) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['POST',]) - def switch_status(self, request, *args, **kwargs): - try: - instance = self.get_object() - status = request.data.get('status') - approver_comment = request.data.get('approver_comment') - if not status: - raise serializers.ValidationError('Status is required') - else: - if not status in ['with_assessor','with_assessor_requirements','with_approver']: - raise serializers.ValidationError('The status provided is not allowed') - instance.move_to_status(request,status, approver_comment) - serializer = InternalProposalSerializer(instance,context={'request':request}) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - if hasattr(e,'error_dict'): - raise serializers.ValidationError(repr(e.error_dict)) - else: - raise serializers.ValidationError(repr(e[0].encode('utf-8'))) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['POST',]) - def reissue_approval(self, request, *args, **kwargs): - try: - instance = self.get_object() - status = request.data.get('status') - if not status: - raise serializers.ValidationError('Status is required') - else: - if not status in ['with_approver']: - raise serializers.ValidationError('The status provided is not allowed') - instance.reissue_approval(request,status) - serializer = InternalProposalSerializer(instance,context={'request':request}) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - if hasattr(e,'error_dict'): - raise serializers.ValidationError(repr(e.error_dict)) - else: - raise serializers.ValidationError(repr(e[0].encode('utf-8'))) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['GET',]) - def renew_approval(self, request, *args, **kwargs): - try: - instance = self.get_object() - instance = instance.renew_approval(request) - serializer = SaveProposalSerializer(instance,context={'request':request}) - return Response(serializer.data) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e[0].encode('utf-8'))) - - @detail_route(methods=['GET',]) - def amend_approval(self, request, *args, **kwargs): - try: - instance = self.get_object() - instance = instance.amend_approval(request) - serializer = SaveProposalSerializer(instance,context={'request':request}) - return Response(serializer.data) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e[0].encode('utf-8'))) - - - @detail_route(methods=['POST',]) - def proposed_approval(self, request, *args, **kwargs): - try: - instance = self.get_object() - serializer = ProposedApprovalSerializer(data=request.data) - serializer.is_valid(raise_exception=True) - instance.proposed_approval(request,serializer.validated_data) - serializer = InternalProposalSerializer(instance,context={'request':request}) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - if hasattr(e,'error_dict'): - raise serializers.ValidationError(repr(e.error_dict)) - else: - raise serializers.ValidationError(repr(e[0].encode('utf-8'))) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['POST',]) - def approval_level_document(self, request, *args, **kwargs): - try: - instance = self.get_object() - instance = instance.assing_approval_level_document(request) - serializer = InternalProposalSerializer(instance,context={'request':request}) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - if hasattr(e,'error_dict'): - raise serializers.ValidationError(repr(e.error_dict)) - else: - raise serializers.ValidationError(repr(e[0].encode('utf-8'))) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['POST',]) - def final_approval(self, request, *args, **kwargs): - try: - instance = self.get_object() - serializer = ProposedApprovalSerializer(data=request.data) - serializer.is_valid(raise_exception=True) - instance.final_approval(request,serializer.validated_data) - serializer = InternalProposalSerializer(instance,context={'request':request}) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - if hasattr(e,'error_dict'): - raise serializers.ValidationError(repr(e.error_dict)) - else: - raise serializers.ValidationError(repr(e[0].encode('utf-8'))) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['POST',]) - def proposed_decline(self, request, *args, **kwargs): - try: - instance = self.get_object() - serializer = PropedDeclineSerializer(data=request.data) - serializer.is_valid(raise_exception=True) - instance.proposed_decline(request,serializer.validated_data) - serializer = InternalProposalSerializer(instance,context={'request':request}) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - if hasattr(e,'error_dict'): - raise serializers.ValidationError(repr(e.error_dict)) - else: - raise serializers.ValidationError(repr(e[0].encode('utf-8'))) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['POST',]) - def final_decline(self, request, *args, **kwargs): - try: - instance = self.get_object() - serializer = PropedDeclineSerializer(data=request.data) - serializer.is_valid(raise_exception=True) - instance.final_decline(request,serializer.validated_data) - serializer = InternalProposalSerializer(instance,context={'request':request}) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - if hasattr(e,'error_dict'): - raise serializers.ValidationError(repr(e.error_dict)) - else: - raise serializers.ValidationError(repr(e[0].encode('utf-8'))) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['POST',]) - @renderer_classes((JSONRenderer,)) - def on_hold(self, request, *args, **kwargs): - try: - with transaction.atomic(): - instance = self.get_object() - is_onhold = eval(request.data.get('onhold')) - data = {} - if is_onhold: - data['type'] = u'onhold' - instance.on_hold(request) - else: - data['type'] = u'onhold_remove' - instance.on_hold_remove(request) - - data['proposal'] = u'{}'.format(instance.id) - data['staff'] = u'{}'.format(request.user.id) - data['text'] = request.user.get_full_name() + u': {}'.format(request.data['text']) - data['subject'] = request.user.get_full_name() + u': {}'.format(request.data['text']) - serializer = ProposalLogEntrySerializer(data=data) - serializer.is_valid(raise_exception=True) - comms = serializer.save() - - # save the files - documents_qs = instance.onhold_documents.filter(input_name='on_hold_file', visible=True) - for f in documents_qs: - document = comms.documents.create(_file=f._file, name=f.name) - #document = comms.documents.create() - #document.name = f.name - #document._file = f._file #.strip('/media') - document.input_name = f.input_name - document.can_delete = True - document.save() - # end save documents - - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['POST',]) - @renderer_classes((JSONRenderer,)) - def with_qaofficer(self, request, *args, **kwargs): - try: - with transaction.atomic(): - instance = self.get_object() - is_with_qaofficer = eval(request.data.get('with_qaofficer')) - data = {} - if is_with_qaofficer: - data['type'] = u'with_qaofficer' - instance.with_qaofficer(request) - else: - data['type'] = u'with_qaofficer_completed' - instance.with_qaofficer_completed(request) - - data['proposal'] = u'{}'.format(instance.id) - data['staff'] = u'{}'.format(request.user.id) - data['text'] = request.user.get_full_name() + u': {}'.format(request.data['text']) - data['subject'] = request.user.get_full_name() + u': {}'.format(request.data['text']) - serializer = ProposalLogEntrySerializer(data=data) - serializer.is_valid(raise_exception=True) - comms = serializer.save() - - # Save the files - document_qs=[] - if is_with_qaofficer: - #Get the list of documents attached by assessor when sending application to QA officer - documents_qs = instance.qaofficer_documents.filter(input_name='assessor_qa_file', visible=True) - else: - #Get the list of documents attached by QA officer when sending application back to assessor - documents_qs = instance.qaofficer_documents.filter(input_name='qaofficer_file', visible=True) - for f in documents_qs: - document = comms.documents.create(_file=f._file, name=f.name) - #document = comms.documents.create() - #document.name = f.name - #document._file = f._file #.strip('/media') - document.input_name = f.input_name - document.can_delete = True - document.save() - # End Save Documents - - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['post']) - def assesor_send_referral(self, request, *args, **kwargs): - try: - instance = self.get_object() - serializer = SendReferralSerializer(data=request.data) - serializer.is_valid(raise_exception=True) - #text=serializer.validated_data['text'] - #instance.send_referral(request,serializer.validated_data['email']) - instance.send_referral(request,serializer.validated_data['email_group'], serializer.validated_data['text']) - serializer = InternalProposalSerializer(instance,context={'request':request}) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - if hasattr(e,'error_dict'): - raise serializers.ValidationError(repr(e.error_dict)) - else: - raise serializers.ValidationError(repr(e[0].encode('utf-8'))) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['post']) - @renderer_classes((JSONRenderer,)) - def draft(self, request, *args, **kwargs): - try: - instance = self.get_object() - save_proponent_data(instance,request,self) - return redirect(reverse('external')) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - if hasattr(e,'error_dict'): - raise serializers.ValidationError(repr(e.error_dict)) - else: - raise serializers.ValidationError(repr(e[0].encode('utf-8'))) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['post']) - def update_training_flag(self, request, *args, **kwargs): - try: - instance = self.get_object() - if request.data.get('training_completed'): - instance.training_completed = True - instance.save() - return Response({'training_completed': True}) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - if hasattr(e,'error_dict'): - raise serializers.ValidationError(repr(e.error_dict)) - else: - raise serializers.ValidationError(repr(e[0].encode('utf-8'))) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['post']) - @renderer_classes((JSONRenderer,)) - def assessor_save(self, request, *args, **kwargs): - try: - instance = self.get_object() - save_assessor_data(instance,request,self) - return redirect(reverse('external')) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - def create(self, request, *args, **kwargs): - try: - http_status = status.HTTP_200_OK - application_type = request.data.get('application') - region = request.data.get('region') - district = request.data.get('district') - #tenure = request.data.get('tenure') - activity = request.data.get('activity') - sub_activity1 = request.data.get('sub_activity1') - sub_activity2 = request.data.get('sub_activity2') - category = request.data.get('category') - approval_level = request.data.get('approval_level') - - application_name = ApplicationType.objects.get(id=application_type).name - # Get most recent versions of the Proposal Types - qs_proposal_type = ProposalType.objects.all().order_by('name', '-version').distinct('name') - proposal_type = qs_proposal_type.get(name=application_name) - - - data = { - #'schema': qs_proposal_type.order_by('-version').first().schema, - 'schema': proposal_type.schema, - 'submitter': request.user.id, - 'org_applicant': request.data.get('org_applicant'), - 'application_type': application_type, - 'region': region, - 'district': district, - 'activity': activity, - 'approval_level': approval_level, - #'other_details': {}, - #'tenure': tenure, - 'data': [ - { - u'regionActivitySection': [{ - 'Region': Region.objects.get(id=region).name if region else None, - 'District': District.objects.get(id=district).name if district else None, - #'Tenure': Tenure.objects.get(id=tenure).name if tenure else None, - #'ApplicationType': ApplicationType.objects.get(id=application_type).name - 'ActivityType': activity, - 'Sub-activity level 1': sub_activity1, - 'Sub-activity level 2': sub_activity2, - 'Management area': category, - }] - } - - ], - } - serializer = SaveProposalSerializer(data=data) - serializer.is_valid(raise_exception=True) - #serializer.save() - instance=serializer.save() - #Create ProposalOtherDetails instance for T Class licence - if application_name=='T Class': - other_details_data={ - 'proposal': instance.id - } - serializer=SaveProposalOtherDetailsSerializer(data=other_details_data) - serializer.is_valid(raise_exception=True) - serializer.save() - serializer = SaveProposalSerializer(instance) - return Response(serializer.data) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - def update(self, request, *args, **kwargs): - try: - http_status = status.HTTP_200_OK - instance = self.get_object() - serializer = SaveProposalSerializer(instance,data=request.data) - serializer.is_valid(raise_exception=True) - self.perform_update(serializer) - return Response(serializer.data) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - def destroy(self, request,*args,**kwargs): - try: - http_status = status.HTTP_200_OK - instance = self.get_object() - serializer = SaveProposalSerializer(instance,{'processing_status':'discarded', 'previous_application': None},partial=True) - serializer.is_valid(raise_exception=True) - self.perform_update(serializer) - return Response(serializer.data,status=http_status) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - -class ReferralViewSet(viewsets.ModelViewSet): - #queryset = Referral.objects.all() - queryset = Referral.objects.none() - serializer_class = ReferralSerializer - - def get_queryset(self): - user = self.request.user - if user.is_authenticated() and is_internal(self.request): - #queryset = Referral.objects.filter(referral=user) - queryset = Referral.objects.all() - return queryset - return Referral.objects.none() - - @list_route(methods=['GET',]) - def filter_list(self, request, *args, **kwargs): - """ Used by the external dashboard filters """ - qs = self.get_queryset().filter(referral=request.user) - region_qs = qs.filter(proposal__region__isnull=False).values_list('proposal__region__name', flat=True).distinct() - #district_qs = qs.filter(proposal__district__isnull=False).values_list('proposal__district__name', flat=True).distinct() - activity_qs = qs.filter(proposal__activity__isnull=False).order_by('proposal__activity').distinct('proposal__activity').values_list('proposal__activity', flat=True).distinct() - submitter_qs = qs.filter(proposal__submitter__isnull=False).order_by('proposal__submitter').distinct('proposal__submitter').values_list('proposal__submitter__first_name','proposal__submitter__last_name','proposal__submitter__email') - submitters = [dict(email=i[2], search_term='{} {} ({})'.format(i[0], i[1], i[2])) for i in submitter_qs] - processing_status_qs = qs.filter(proposal__processing_status__isnull=False).order_by('proposal__processing_status').distinct('proposal__processing_status').values_list('proposal__processing_status', flat=True) - processing_status = [dict(value=i, name='{}'.format(' '.join(i.split('_')).capitalize())) for i in processing_status_qs] - data = dict( - regions=region_qs, - #districts=district_qs, - activities=activity_qs, - submitters=submitters, - processing_status_choices=processing_status, - ) - return Response(data) - - - def retrieve(self, request, *args, **kwargs): - instance = self.get_object() - serializer = self.get_serializer(instance, context={'request':request}) - return Response(serializer.data) - - @list_route(methods=['GET',]) - def user_list(self, request, *args, **kwargs): - qs = self.get_queryset().filter(referral=request.user) - serializer = DTReferralSerializer(qs, many=True) - #serializer = DTReferralSerializer(self.get_queryset(), many=True) - return Response(serializer.data) - - @list_route(methods=['GET',]) - def user_group_list(self, request, *args, **kwargs): - qs = ReferralRecipientGroup.objects.filter().values_list('name', flat=True) - return Response(qs) - - @list_route(methods=['GET',]) - def datatable_list(self, request, *args, **kwargs): - proposal = request.GET.get('proposal',None) - qs = self.get_queryset().all() - if proposal: - qs = qs.filter(proposal_id=int(proposal)) - serializer = DTReferralSerializer(qs, many=True) - return Response(serializer.data) - - - @detail_route(methods=['GET',]) - def referral_list(self, request, *args, **kwargs): - instance = self.get_object() - #qs = self.get_queryset().all() - #qs=qs.filter(sent_by=instance.referral, proposal=instance.proposal) - - qs = Referral.objects.filter(referral_group__in=request.user.referralrecipientgroup_set.all(), proposal=instance.proposal) - serializer = DTReferralSerializer(qs, many=True) - #serializer = ProposalReferralSerializer(qs, many=True) - - return Response(serializer.data) - - @detail_route(methods=['GET', 'POST']) - def complete(self, request, *args, **kwargs): - try: - instance = self.get_object() - instance.complete(request) - serializer = self.get_serializer(instance, context={'request':request}) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['GET',]) - def remind(self, request, *args, **kwargs): - try: - instance = self.get_object() - instance.remind(request) - serializer = InternalProposalSerializer(instance.proposal,context={'request':request}) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['GET',]) - def recall(self, request, *args, **kwargs): - try: - instance = self.get_object() - instance.recall(request) - serializer = InternalProposalSerializer(instance.proposal,context={'request':request}) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['GET',]) - def resend(self, request, *args, **kwargs): - try: - instance = self.get_object() - instance.resend(request) - serializer = InternalProposalSerializer(instance.proposal,context={'request':request}) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['post']) - def send_referral(self, request, *args, **kwargs): - try: - instance = self.get_object() - serializer = SendReferralSerializer(data=request.data) - serializer.is_valid(raise_exception=True) - instance.send_referral(request,serializer.validated_data['email'],serializer.validated_data['text']) - serializer = self.get_serializer(instance, context={'request':request}) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - if hasattr(e,'error_dict'): - raise serializers.ValidationError(repr(e.error_dict)) - else: - raise serializers.ValidationError(repr(e[0].encode('utf-8'))) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - -class ProposalRequirementViewSet(viewsets.ModelViewSet): - #queryset = ProposalRequirement.objects.all() - queryset = ProposalRequirement.objects.none() - serializer_class = ProposalRequirementSerializer - - def get_queryset(self): - qs = ProposalRequirement.objects.all().exclude(is_deleted=True) - return qs - - @detail_route(methods=['GET',]) - def move_up(self, request, *args, **kwargs): - try: - instance = self.get_object() - instance.up() - instance.save() - serializer = self.get_serializer(instance) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['GET',]) - def move_down(self, request, *args, **kwargs): - try: - instance = self.get_object() - instance.down() - instance.save() - serializer = self.get_serializer(instance) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['GET',]) - def discard(self, request, *args, **kwargs): - try: - instance = self.get_object() - instance.is_deleted = True - instance.save() - serializer = self.get_serializer(instance) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['POST',]) - @renderer_classes((JSONRenderer,)) - def delete_document(self, request, *args, **kwargs): - try: - instance = self.get_object() - RequirementDocument.objects.get(id=request.data.get('id')).delete() - return Response([dict(id=i.id, name=i.name,_file=i._file.url) for i in instance.requirement_documents.all()]) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - def update(self, request, *args, **kwargs): - try: - instance = self.get_object() - serializer = self.get_serializer(instance, data=json.loads(request.data.get('data'))) - serializer.is_valid(raise_exception=True) - serializer.save() - instance.add_documents(request) - return Response(serializer.data) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - - def create(self, request, *args, **kwargs): - try: -# data = { -# 'due_date': request.data.get('due_date'), -# 'standard': request.data.get('standard'), -# 'recurrence': reqeust.data.get('recurrence'), -# 'recurrence_pattern': request.data.get('recurrence_pattern'), -# 'proposal': request.data.get('proposal'), -# 'referral_group': request.data.get('referral_group'), -# } - - #serializer = self.get_serializer(data= request.data) - serializer = self.get_serializer(data= json.loads(request.data.get('data'))) - #serializer = self.get_serializer(data=data) - serializer.is_valid(raise_exception = True) - instance = serializer.save() - instance.add_documents(request) - #serializer = self.get_serializer(instance) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - if hasattr(e,'error_dict'): - raise serializers.ValidationError(repr(e.error_dict)) - else: - raise serializers.ValidationError(repr(e[0].encode('utf-8'))) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - -class ProposalStandardRequirementViewSet(viewsets.ReadOnlyModelViewSet): - queryset = ProposalStandardRequirement.objects.all() - serializer_class = ProposalStandardRequirementSerializer - - def list(self, request, *args, **kwargs): - queryset = self.get_queryset() - search = request.GET.get('search') - if search: - queryset = queryset.filter(text__icontains=search) - serializer = self.get_serializer(queryset, many=True) - return Response(serializer.data) - -class AmendmentRequestViewSet(viewsets.ModelViewSet): - queryset = AmendmentRequest.objects.all() - serializer_class = AmendmentRequestSerializer - - def create(self, request, *args, **kwargs): - try: - reason_id=request.data.get('reason') - data = { - #'schema': qs_proposal_type.order_by('-version').first().schema, - 'text': request.data.get('text'), - 'proposal': request.data.get('proposal'), - 'reason': AmendmentReason.objects.get(id=reason_id) if reason_id else None, - } - serializer = self.get_serializer(data= request.data) - #serializer = self.get_serializer(data=data) - serializer.is_valid(raise_exception = True) - instance = serializer.save() - instance.generate_amendment(request) - serializer = self.get_serializer(instance) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - if hasattr(e,'error_dict'): - raise serializers.ValidationError(repr(e.error_dict)) - else: - raise serializers.ValidationError(repr(e[0].encode('utf-8'))) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - -class AccreditationTypeView(views.APIView): - - renderer_classes = [JSONRenderer,] - def get(self,request, format=None): - choices_list = [] - #choices = ProposalOtherDetails.ACCREDITATION_TYPE_CHOICES - choices=ProposalAccreditation.ACCREDITATION_TYPE_CHOICES - if choices: - for c in choices: - choices_list.append({'key': c[0],'value': c[1]}) - return Response(choices_list) - -class LicencePeriodChoicesView(views.APIView): - - renderer_classes = [JSONRenderer,] - def get(self,request, format=None): - choices_list = [] - choices = ProposalOtherDetails.LICENCE_PERIOD_CHOICES - if choices: - for c in choices: - choices_list.append({'key': c[0],'value': c[1]}) - return Response(choices_list) - - -class AmendmentRequestReasonChoicesView(views.APIView): - - renderer_classes = [JSONRenderer,] - def get(self,request, format=None): - choices_list = [] - #choices = AmendmentRequest.REASON_CHOICES - choices=AmendmentReason.objects.all() - if choices: - for c in choices: - #choices_list.append({'key': c[0],'value': c[1]}) - choices_list.append({'key': c.id,'value': c.reason}) - return Response(choices_list) - -class SearchKeywordsView(views.APIView): - renderer_classes = [JSONRenderer,] - def post(self,request, format=None): - qs = [] - searchWords = request.data.get('searchKeywords') - searchProposal = request.data.get('searchProposal') - searchApproval = request.data.get('searchApproval') - searchCompliance = request.data.get('searchCompliance') - if searchWords: - qs= searchKeyWords(searchWords, searchProposal, searchApproval, searchCompliance) - #queryset = list(set(qs)) - serializer = SearchKeywordSerializer(qs, many=True) - return Response(serializer.data) - -class SearchReferenceView(views.APIView): - renderer_classes = [JSONRenderer,] - def post(self,request, format=None): - try: - qs = [] - reference_number = request.data.get('reference_number') - if reference_number: - qs= search_reference(reference_number) - #queryset = list(set(qs)) - serializer = SearchReferenceSerializer(qs) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - if hasattr(e,'error_dict'): - raise serializers.ValidationError(repr(e.error_dict)) - else: - print e - raise serializers.ValidationError(repr(e[0].encode('utf-8'))) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - -class VehicleViewSet(viewsets.ModelViewSet): - queryset = Vehicle.objects.all().order_by('id') - serializer_class = VehicleSerializer - - @detail_route(methods=['post']) - def edit_vehicle(self, request, *args, **kwargs): - try: - instance = self.get_object() - serializer = SaveVehicleSerializer(instance, data=request.data) - serializer.is_valid(raise_exception=True) - serializer.save() - instance.proposal.log_user_action(ProposalUserAction.ACTION_EDIT_VEHICLE.format(instance.id),request) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - if hasattr(e,'error_dict'): - raise serializers.ValidationError(repr(e.error_dict)) - else: - raise serializers.ValidationError(repr(e[0].encode('utf-8'))) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - def create(self, request, *args, **kwargs): - try: - #instance = self.get_object() - serializer = SaveVehicleSerializer(data=request.data) - serializer.is_valid(raise_exception=True) - instance=serializer.save() - instance.proposal.log_user_action(ProposalUserAction.ACTION_CREATE_VEHICLE.format(instance.id),request) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - if hasattr(e,'error_dict'): - raise serializers.ValidationError(repr(e.error_dict)) - else: - raise serializers.ValidationError(repr(e[0].encode('utf-8'))) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - -class VesselViewSet(viewsets.ModelViewSet): - queryset = Vessel.objects.all().order_by('id') - serializer_class = VesselSerializer - - @detail_route(methods=['post']) - def edit_vessel(self, request, *args, **kwargs): - try: - instance = self.get_object() - serializer = VesselSerializer(instance, data=request.data) - serializer.is_valid(raise_exception=True) - serializer.save() - instance.proposal.log_user_action(ProposalUserAction.ACTION_EDIT_VESSEL.format(instance.id),request) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - if hasattr(e,'error_dict'): - raise serializers.ValidationError(repr(e.error_dict)) - else: - raise serializers.ValidationError(repr(e[0].encode('utf-8'))) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - def create(self, request, *args, **kwargs): - try: - #instance = self.get_object() - serializer = VesselSerializer(data=request.data) - serializer.is_valid(raise_exception=True) - instance=serializer.save() - instance.proposal.log_user_action(ProposalUserAction.ACTION_CREATE_VESSEL.format(instance.id),request) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - if hasattr(e,'error_dict'): - raise serializers.ValidationError(repr(e.error_dict)) - else: - raise serializers.ValidationError(repr(e[0].encode('utf-8'))) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - -class AssessorChecklistViewSet(viewsets.ReadOnlyModelViewSet): - queryset = ChecklistQuestion.objects.none() - serializer_class = ChecklistQuestionSerializer - - def get_queryset(self): - qs=ChecklistQuestion.objects.filter(Q(list_type = 'assessor_list')& Q(obsolete=False)) - return qs - -class ProposalAssessmentViewSet(viewsets.ModelViewSet): - #queryset = ProposalRequirement.objects.all() - queryset = ProposalAssessment.objects.all() - serializer_class = ProposalAssessmentSerializer - - @detail_route(methods=['post']) - def update_assessment(self, request, *args, **kwargs): - try: - instance = self.get_object() - request.data['submitter']= request.user.id - serializer = ProposalAssessmentSerializer(instance, data=request.data) - serializer.is_valid(raise_exception=True) - serializer.save() - checklist=request.data['checklist'] - if checklist: - for chk in checklist: - try: - chk_instance=ProposalAssessmentAnswer.objects.get(id=chk['id']) - serializer_chk = ProposalAssessmentAnswerSerializer(chk_instance, data=chk) - serializer_chk.is_valid(raise_exception=True) - serializer_chk.save() - except: - raise - #instance.proposal.log_user_action(ProposalUserAction.ACTION_EDIT_VESSEL.format(instance.id),request) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - if hasattr(e,'error_dict'): - raise serializers.ValidationError(repr(e.error_dict)) - else: - raise serializers.ValidationError(repr(e[0].encode('utf-8'))) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) diff --git a/commercialoperator/components/proposals/email.py b/commercialoperator/components/proposals/email.py deleted file mode 100755 index 8a58ef0bf5..0000000000 --- a/commercialoperator/components/proposals/email.py +++ /dev/null @@ -1,556 +0,0 @@ -import logging - -from django.core.mail import EmailMultiAlternatives, EmailMessage -from django.utils.encoding import smart_text -from django.core.urlresolvers import reverse -from django.conf import settings - -from commercialoperator.components.emails.emails import TemplateEmailBase - -logger = logging.getLogger(__name__) - -SYSTEM_NAME = settings.SYSTEM_NAME_SHORT + ' Automated Message' - -class QAOfficerSendNotificationEmail(TemplateEmailBase): - subject = 'An Application has been sent to you for QA.' - html_template = 'commercialoperator/emails/proposals/send_qaofficer_notification.html' - txt_template = 'commercialoperator/emails/proposals/send_qaofficer_notification.txt' - -class QAOfficerCompleteNotificationEmail(TemplateEmailBase): - subject = 'A QA for an application has been completed.' - html_template = 'commercialoperator/emails/proposals/send_qaofficer_complete_notification.html' - txt_template = 'commercialoperator/emails/proposals/send_qaofficer_complete_notification.txt' - -class ReferralSendNotificationEmail(TemplateEmailBase): - subject = 'A referral for an application has been sent to you.' - html_template = 'commercialoperator/emails/proposals/send_referral_notification.html' - txt_template = 'commercialoperator/emails/proposals/send_referral_notification.txt' - -class ReferralCompleteNotificationEmail(TemplateEmailBase): - subject = 'A referral for an application has been completed.' - html_template = 'commercialoperator/emails/proposals/send_referral_complete_notification.html' - txt_template = 'commercialoperator/emails/proposals/send_referral_complete_notification.txt' - -class ProposalDeclineSendNotificationEmail(TemplateEmailBase): - subject = 'Your Application has been declined.' - html_template = 'commercialoperator/emails/proposals/send_decline_notification.html' - txt_template = 'commercialoperator/emails/proposals/send_decline_notification.txt' - -class ProposalApprovalSendNotificationEmail(TemplateEmailBase): - subject = '{} - Commercial Operations Licence Approved.'.format(settings.DEP_NAME) - html_template = 'commercialoperator/emails/proposals/send_approval_notification.html' - txt_template = 'commercialoperator/emails/proposals/send_approval_notification.txt' - -class AmendmentRequestSendNotificationEmail(TemplateEmailBase): - subject = '{} - Commercial Operations Incomplete application.'.format(settings.DEP_NAME) - html_template = 'commercialoperator/emails/proposals/send_amendment_notification.html' - txt_template = 'commercialoperator/emails/proposals/send_amendment_notification.txt' - -class SubmitSendNotificationEmail(TemplateEmailBase): - subject = 'A new Application has been submitted.' - html_template = 'commercialoperator/emails/proposals/send_submit_notification.html' - txt_template = 'commercialoperator/emails/proposals/send_submit_notification.txt' - -class ExternalSubmitSendNotificationEmail(TemplateEmailBase): - subject = '{} - Confirmation - Application submitted.'.format(settings.DEP_NAME) - html_template = 'commercialoperator/emails/proposals/send_external_submit_notification.html' - txt_template = 'commercialoperator/emails/proposals/send_external_submit_notification.txt' - -class ApproverDeclineSendNotificationEmail(TemplateEmailBase): - subject = 'An Application has been recommended for decline.' - html_template = 'commercialoperator/emails/proposals/send_approver_decline_notification.html' - txt_template = 'commercialoperator/emails/proposals/send_approver_decline_notification.txt' - -class ApproverApproveSendNotificationEmail(TemplateEmailBase): - subject = 'An Application has been recommended for approval.' - html_template = 'commercialoperator/emails/proposals/send_approver_approve_notification.html' - txt_template = 'commercialoperator/emails/proposals/send_approver_approve_notification.txt' - -class ApproverSendBackNotificationEmail(TemplateEmailBase): - subject = 'An Application has been sent back by approver.' - html_template = 'commercialoperator/emails/proposals/send_approver_sendback_notification.html' - txt_template = 'commercialoperator/emails/proposals/send_approver_sendback_notification.txt' - -def send_qaofficer_email_notification(proposal, recipients, request, reminder=False): - email = QAOfficerSendNotificationEmail() - url = request.build_absolute_uri(reverse('internal-proposal-detail',kwargs={'proposal_pk': proposal.id})) - - if 'test-emails' in request.path_info: - comments = 'This is my test comment' - else: - comments = request.data['text'] - - context = { - 'proposal': proposal, - 'url': url, - 'reminder':reminder, - 'completed_by': request.user.get_full_name(), - 'comments': comments - } - - msg = email.send(recipients, context=context) - sender = request.user if request else settings.DEFAULT_FROM_EMAIL - _log_proposal_email(msg, proposal, sender=sender) - if proposal.org_applicant: - _log_org_email(msg, proposal.org_applicant, proposal.submitter, sender=sender) - else: - _log_user_email(msg, proposal.submitter, proposal.submitter, sender=sender) - - -def send_qaofficer_complete_email_notification(proposal, recipients, request, reminder=False): - email = QAOfficerCompleteNotificationEmail() - url = request.build_absolute_uri(reverse('internal-proposal-detail',kwargs={'proposal_pk': proposal.id})) - - #text = proposal.comms_logs.filter(type__icontains='qaofficer').last().text - if 'test-emails' in request.path_info: - comments = 'This is my test comment' - else: - comments = request.data['text'] - - context = { - #'completed_by': text.split(':')[0], - 'proposal': proposal, - 'url': url, - 'completed_by': request.user.get_full_name(), - 'comments': comments - } - - msg = email.send(recipients, context=context) - sender = request.user if request else settings.DEFAULT_FROM_EMAIL - _log_proposal_email(msg, proposal, sender=sender) - if proposal.org_applicant: - _log_org_email(msg, proposal.org_applicant, proposal.submitter, sender=sender) - else: - _log_user_email(msg, proposal.submitter, proposal.submitter, sender=sender) - - -def send_referral_email_notification(referral,recipients,request,reminder=False): - email = ReferralSendNotificationEmail() - url = request.build_absolute_uri(reverse('internal-referral-detail',kwargs={'proposal_pk':referral.proposal.id,'referral_pk':referral.id})) - - context = { - 'proposal': referral.proposal, - 'url': url, - 'reminder':reminder, - 'comments': referral.text - } - - #msg = email.send(referral.referral.email, context=context) - #recipients = list(ReferralRecipientGroup.objects.get(name=referral.email_group).members.all().values_list('email', flat=True)) - msg = email.send(recipients, context=context) - sender = request.user if request else settings.DEFAULT_FROM_EMAIL - _log_proposal_referral_email(msg, referral, sender=sender) - if referral.proposal.org_applicant: - _log_org_email(msg, referral.proposal.org_applicant, referral.referral, sender=sender) - else: - _log_user_email(msg, referral.proposal.submitter, referral.referral, sender=sender) - - -def send_referral_complete_email_notification(referral,request): - email = ReferralCompleteNotificationEmail() - email.subject = referral.sent_by.email + ': ' + email.subject - url = request.build_absolute_uri(reverse('internal-proposal-detail',kwargs={'proposal_pk': referral.proposal.id})) - - context = { - 'completed_by': referral.referral, - 'proposal': referral.proposal, - 'url': url, - 'referral_comments': referral.referral_text - } - - msg = email.send(referral.sent_by.email, context=context) - sender = request.user if request else settings.DEFAULT_FROM_EMAIL - _log_proposal_referral_email(msg, referral, sender=sender) - if referral.proposal.org_applicant: - _log_org_email(msg, referral.proposal.org_applicant, referral.referral, sender=sender) - else: - _log_user_email(msg, referral.proposal.submitter, referral.referral, sender=sender) - -def send_amendment_email_notification(amendment_request, request, proposal): - email = AmendmentRequestSendNotificationEmail() - #reason = amendment_request.get_reason_display() - reason = amendment_request.reason.reason - url = request.build_absolute_uri(reverse('external-proposal-detail',kwargs={'proposal_pk': proposal.id})) - - if "-internal" in url: - # remove '-internal'. This email is for external submitters - url = ''.join(url.split('-internal')) - - context = { - 'proposal': proposal, - 'reason': reason, - 'amendment_request_text': amendment_request.text, - 'url': url - } - - msg = email.send(proposal.submitter.email, context=context) - sender = request.user if request else settings.DEFAULT_FROM_EMAIL - _log_proposal_email(msg, proposal, sender=sender) - if proposal.org_applicant: - _log_org_email(msg, proposal.org_applicant, proposal.submitter, sender=sender) - else: - _log_user_email(msg, proposal.submitter, proposal.submitter, sender=sender) - -def send_submit_email_notification(request, proposal): - email = SubmitSendNotificationEmail() - url = request.build_absolute_uri(reverse('internal-proposal-detail',kwargs={'proposal_pk': proposal.id})) - if "-internal" not in url: - # add it. This email is for internal staff (assessors) - url = '-internal.{}'.format(settings.SITE_DOMAIN).join(url.split('.' + settings.SITE_DOMAIN)) - - context = { - 'proposal': proposal, - 'url': url - } - - msg = email.send(proposal.assessor_recipients, context=context) - sender = request.user if request else settings.DEFAULT_FROM_EMAIL - _log_proposal_email(msg, proposal, sender=sender) - if proposal.org_applicant: - _log_org_email(msg, proposal.org_applicant, proposal.submitter, sender=sender) - else: - _log_user_email(msg, proposal.submitter, proposal.submitter, sender=sender) - return msg - -def send_external_submit_email_notification(request, proposal): - email = ExternalSubmitSendNotificationEmail() - url = request.build_absolute_uri(reverse('external-proposal-detail',kwargs={'proposal_pk': proposal.id})) - - if "-internal" in url: - # remove '-internal'. This email is for external submitters - url = ''.join(url.split('-internal')) - - context = { - 'proposal': proposal, - 'submitter': proposal.submitter.get_full_name(), - 'url': url - } - - msg = email.send(proposal.submitter.email, context=context) - sender = request.user if request else settings.DEFAULT_FROM_EMAIL - _log_proposal_email(msg, proposal, sender=sender) - if proposal.org_applicant: - _log_org_email(msg, proposal.org_applicant, proposal.submitter, sender=sender) - else: - _log_user_email(msg, proposal.submitter, proposal.submitter, sender=sender) - return msg - -#send email when Proposal is 'proposed to decline' by assessor. -def send_approver_decline_email_notification(reason, request, proposal): - email = ApproverDeclineSendNotificationEmail() - url = request.build_absolute_uri(reverse('internal-proposal-detail',kwargs={'proposal_pk': proposal.id})) - context = { - 'proposal': proposal, - 'reason': reason, - 'url': url - } - - msg = email.send(proposal.approver_recipients, context=context) - sender = request.user if request else settings.DEFAULT_FROM_EMAIL - _log_proposal_email(msg, proposal, sender=sender) - if proposal.org_applicant: - _log_org_email(msg, proposal.org_applicant, proposal.submitter, sender=sender) - else: - _log_user_email(msg, proposal.submitter, proposal.submitter, sender=sender) - - -def send_approver_approve_email_notification(request, proposal): - email = ApproverApproveSendNotificationEmail() - url = request.build_absolute_uri(reverse('internal-proposal-detail',kwargs={'proposal_pk': proposal.id})) - context = { - 'start_date' : proposal.proposed_issuance_approval.get('start_date'), - 'expiry_date' : proposal.proposed_issuance_approval.get('expiry_date'), - 'details': proposal.proposed_issuance_approval.get('details'), - 'proposal': proposal, - 'url': url - } - - msg = email.send(proposal.approver_recipients, context=context) - sender = request.user if request else settings.DEFAULT_FROM_EMAIL - _log_proposal_email(msg, proposal, sender=sender) - if proposal.org_applicant: - _log_org_email(msg, proposal.org_applicant, proposal.submitter, sender=sender) - else: - _log_user_email(msg, proposal.submitter, proposal.submitter, sender=sender) - - -def send_proposal_decline_email_notification(proposal,request,proposal_decline): - email = ProposalDeclineSendNotificationEmail() - - context = { - 'proposal': proposal, - - } - cc_list = proposal_decline.cc_email - all_ccs = [] - if cc_list: - all_ccs = cc_list.split(',') - - msg = email.send(proposal.submitter.email, bcc= all_ccs, context=context) - sender = request.user if request else settings.DEFAULT_FROM_EMAIL - _log_proposal_email(msg, proposal, sender=sender) - if proposal.org_applicant: - _log_org_email(msg, proposal.org_applicant, proposal.submitter, sender=sender) - else: - _log_user_email(msg, proposal.submitter, proposal.submitter, sender=sender) - - -def send_proposal_approver_sendback_email_notification(request, proposal): - email = ApproverSendBackNotificationEmail() - url = request.build_absolute_uri(reverse('internal-proposal-detail',kwargs={'proposal_pk': proposal.id})) - - if 'test-emails' in request.path_info: - approver_comment = 'This is my test comment' - else: - approver_comment = proposal.approver_comment - - - context = { - 'proposal': proposal, - 'url': url, - 'approver_comment': approver_comment - } - - msg = email.send(proposal.assessor_recipients, context=context) - sender = request.user if request else settings.DEFAULT_FROM_EMAIL - _log_proposal_email(msg, proposal, sender=sender) - if proposal.org_applicant: - _log_org_email(msg, proposal.org_applicant, proposal.submitter, sender=sender) - else: - _log_user_email(msg, proposal.submitter, proposal.submitter, sender=sender) - - -def send_proposal_approval_email_notification(proposal,request): - email = ProposalApprovalSendNotificationEmail() - - cc_list = proposal.proposed_issuance_approval['cc_email'] - all_ccs = [] - if cc_list: - all_ccs = cc_list.split(',') - - attachments = [] - licence_document= proposal.approval.licence_document._file - if licence_document is not None: - file_name = proposal.approval.licence_document.name - attachment = (file_name, licence_document.file.read(), 'application/pdf') - attachments.append(attachment) - - # add requirement documents - for requirement in proposal.requirements.all(): - for doc in requirement.requirement_documents.all(): - file_name = doc._file.name - #attachment = (file_name, doc._file.file.read(), 'image/*') - attachment = (file_name, doc._file.file.read()) - attachments.append(attachment) - - url = request.build_absolute_uri(reverse('external')) - if "-internal" in url: - # remove '-internal'. This email is for external submitters - url = ''.join(url.split('-internal')) - handbook_url= settings.COLS_HANDBOOK_URL - context = { - 'proposal': proposal, - 'num_requirement_docs': len(attachments) - 1, - 'url': url, - 'handbook_url': handbook_url - } - - msg = email.send(proposal.submitter.email, bcc= all_ccs, attachments=attachments, context=context) - sender = request.user if request else settings.DEFAULT_FROM_EMAIL - _log_proposal_email(msg, proposal, sender=sender) - if proposal.org_applicant: - _log_org_email(msg, proposal.org_applicant, proposal.submitter, sender=sender) - else: - _log_user_email(msg, proposal.submitter, proposal.submitter, sender=sender) - - -def _log_proposal_referral_email(email_message, referral, sender=None): - from commercialoperator.components.proposals.models import ProposalLogEntry - if isinstance(email_message, (EmailMultiAlternatives, EmailMessage,)): - # TODO this will log the plain text body, should we log the html instead - text = email_message.body - subject = email_message.subject - fromm = smart_text(sender) if sender else smart_text(email_message.from_email) - # the to email is normally a list - if isinstance(email_message.to, list): - to = ','.join(email_message.to) - else: - to = smart_text(email_message.to) - # we log the cc and bcc in the same cc field of the log entry as a ',' comma separated string - all_ccs = [] - if email_message.cc: - all_ccs += list(email_message.cc) - if email_message.bcc: - all_ccs += list(email_message.bcc) - all_ccs = ','.join(all_ccs) - - else: - text = smart_text(email_message) - subject = '' - to = proposal.applicant.email - fromm = smart_text(sender) if sender else SYSTEM_NAME - all_ccs = '' - - customer = referral.referral - - staff = sender - - kwargs = { - 'subject': subject, - 'text': text, - 'proposal': referral.proposal, - 'customer': customer, - 'staff': staff, - 'to': to, - 'fromm': fromm, - 'cc': all_ccs - } - - email_entry = ProposalLogEntry.objects.create(**kwargs) - - return email_entry - - - - - -def _log_proposal_email(email_message, proposal, sender=None): - from commercialoperator.components.proposals.models import ProposalLogEntry - if isinstance(email_message, (EmailMultiAlternatives, EmailMessage,)): - # TODO this will log the plain text body, should we log the html instead - text = email_message.body - subject = email_message.subject - fromm = smart_text(sender) if sender else smart_text(email_message.from_email) - # the to email is normally a list - if isinstance(email_message.to, list): - to = ','.join(email_message.to) - else: - to = smart_text(email_message.to) - # we log the cc and bcc in the same cc field of the log entry as a ',' comma separated string - all_ccs = [] - if email_message.cc: - all_ccs += list(email_message.cc) - if email_message.bcc: - all_ccs += list(email_message.bcc) - all_ccs = ','.join(all_ccs) - - else: - text = smart_text(email_message) - subject = '' - to = proposal.submitter.email - fromm = smart_text(sender) if sender else SYSTEM_NAME - all_ccs = '' - - customer = proposal.submitter - - staff = sender - - kwargs = { - 'subject': subject, - 'text': text, - 'proposal': proposal, - 'customer': customer, - 'staff': staff, - 'to': to, - 'fromm': fromm, - 'cc': all_ccs - } - - email_entry = ProposalLogEntry.objects.create(**kwargs) - - return email_entry - - - -def _log_org_email(email_message, organisation, customer ,sender=None): - from commercialoperator.components.organisations.models import OrganisationLogEntry - if isinstance(email_message, (EmailMultiAlternatives, EmailMessage,)): - # TODO this will log the plain text body, should we log the html instead - text = email_message.body - subject = email_message.subject - fromm = smart_text(sender) if sender else smart_text(email_message.from_email) - # the to email is normally a list - if isinstance(email_message.to, list): - to = ','.join(email_message.to) - else: - to = smart_text(email_message.to) - # we log the cc and bcc in the same cc field of the log entry as a ',' comma separated string - all_ccs = [] - if email_message.cc: - all_ccs += list(email_message.cc) - if email_message.bcc: - all_ccs += list(email_message.bcc) - all_ccs = ','.join(all_ccs) - - else: - text = smart_text(email_message) - subject = '' - to = customer - fromm = smart_text(sender) if sender else SYSTEM_NAME - all_ccs = '' - - customer = customer - - staff = sender - - kwargs = { - 'subject': subject, - 'text': text, - 'organisation': organisation, - 'customer': customer, - 'staff': staff, - 'to': to, - 'fromm': fromm, - 'cc': all_ccs - } - - email_entry = OrganisationLogEntry.objects.create(**kwargs) - - return email_entry - -def _log_user_email(email_message, emailuser, customer ,sender=None): - from ledger.accounts.models import EmailUserLogEntry - if isinstance(email_message, (EmailMultiAlternatives, EmailMessage,)): - # TODO this will log the plain text body, should we log the html instead - text = email_message.body - subject = email_message.subject - fromm = smart_text(sender) if sender else smart_text(email_message.from_email) - # the to email is normally a list - if isinstance(email_message.to, list): - to = ','.join(email_message.to) - else: - to = smart_text(email_message.to) - # we log the cc and bcc in the same cc field of the log entry as a ',' comma separated string - all_ccs = [] - if email_message.cc: - all_ccs += list(email_message.cc) - if email_message.bcc: - all_ccs += list(email_message.bcc) - all_ccs = ','.join(all_ccs) - - else: - text = smart_text(email_message) - subject = '' - to = customer - fromm = smart_text(sender) if sender else SYSTEM_NAME - all_ccs = '' - - customer = customer - - staff = sender - - kwargs = { - 'subject': subject, - 'text': text, - 'emailuser': emailuser, - 'customer': customer, - 'staff': staff, - 'to': to, - 'fromm': fromm, - 'cc': all_ccs - } - - email_entry = EmailUserLogEntry.objects.create(**kwargs) - - return email_entry - diff --git a/commercialoperator/components/proposals/fixtures/default_proposal_approver_group.json b/commercialoperator/components/proposals/fixtures/default_proposal_approver_group.json deleted file mode 100755 index a512e2ce9d..0000000000 --- a/commercialoperator/components/proposals/fixtures/default_proposal_approver_group.json +++ /dev/null @@ -1,10 +0,0 @@ -[ - { - "model": "commercialoperator.proposalapprovergroup", - "fields": - { - "name":"Default Group", - "default": true - } - } -] diff --git a/commercialoperator/components/proposals/fixtures/default_proposal_assessor_group.json b/commercialoperator/components/proposals/fixtures/default_proposal_assessor_group.json deleted file mode 100755 index 6e2c277c71..0000000000 --- a/commercialoperator/components/proposals/fixtures/default_proposal_assessor_group.json +++ /dev/null @@ -1,10 +0,0 @@ -[ - { - "model": "commercialoperator.proposalassessorgroup", - "fields": - { - "name":"Default Group", - "default": true - } - } -] diff --git a/commercialoperator/components/proposals/forms.py b/commercialoperator/components/proposals/forms.py deleted file mode 100755 index c8df1d7acb..0000000000 --- a/commercialoperator/components/proposals/forms.py +++ /dev/null @@ -1,107 +0,0 @@ -from django import forms -from django.core.exceptions import ValidationError -from ledger.accounts.models import EmailUser -from commercialoperator.components.proposals.models import ProposalAssessorGroup,ProposalApproverGroup, HelpPage -from commercialoperator.components.main.models import SystemMaintenance -from ckeditor.widgets import CKEditorWidget -from django.conf import settings -import pytz -from datetime import datetime, timedelta - - -class ProposalAssessorGroupAdminForm(forms.ModelForm): - class Meta: - model = ProposalAssessorGroup - fields = '__all__' - - def __init__(self, *args, **kwargs): - super(ProposalAssessorGroupAdminForm, self).__init__(*args, **kwargs) - if self.instance: - #self.fields['members'].queryset = EmailUser.objects.filter(email__icontains='@dbca.wa.gov.au') - self.fields['members'].queryset = EmailUser.objects.filter(is_staff=True) - - def clean(self): - super(ProposalAssessorGroupAdminForm, self).clean() - if self.instance and ProposalAssessorGroup.objects.all().exists(): - try: - original_members = ProposalAssessorGroup.objects.get(id=self.instance.id).members.all() - current_members = self.cleaned_data.get('members') - for o in original_members: - if o not in current_members: - if self.instance.member_is_assigned(o): - raise ValidationError('{} is currently assigned to a proposal(s)'.format(o.email)) - except: - pass - - -class ProposalApproverGroupAdminForm(forms.ModelForm): - class Meta: - model = ProposalApproverGroup - fields = '__all__' - - def __init__(self, *args, **kwargs): - super(ProposalApproverGroupAdminForm, self).__init__(*args, **kwargs) - if self.instance: - #self.fields['members'].queryset = EmailUser.objects.filter(email__icontains='@dbca.wa.gov.au') - self.fields['members'].queryset = EmailUser.objects.filter(is_staff=True) - - def clean(self): - super(ProposalApproverGroupAdminForm, self).clean() - if self.instance: - try: - original_members = ProposalApproverGroup.objects.get(id=self.instance.id).members.all() - current_members = self.cleaned_data.get('members') - for o in original_members: - if o not in current_members: - if self.instance.member_is_assigned(o): - raise ValidationError('{} is currently assigned to a proposal(s)'.format(o.email)) - except: - pass - - -class CommercialOperatorHelpPageAdminForm(forms.ModelForm): - content = forms.CharField(widget=CKEditorWidget()) - class Meta: - model = HelpPage - fields = '__all__' - - -class SystemMaintenanceAdminForm(forms.ModelForm): - class Meta: - model = SystemMaintenance - fields = '__all__' - - def clean(self): - cleaned_data = self.cleaned_data - start_date = cleaned_data.get('start_date') - end_date = cleaned_data.get('end_date') - try: - latest_obj = SystemMaintenance.objects.exclude(id=self.instance.id).latest('start_date') - except: - latest_obj = SystemMaintenance.objects.none() - tz_local = pytz.timezone(settings.TIME_ZONE) #start_date.tzinfo - tz_utc = pytz.timezone('utc') #latest_obj.start_date.tzinfo - - if latest_obj: - latest_end_date = latest_obj.end_date.astimezone(tz=tz_local) - if self.instance.id: - if start_date < latest_end_date and start_date < self.instance.start_date.astimezone(tz_local): - raise forms.ValidationError('Start date cannot be before an existing records latest end_date. Start Date must be after {}'.format(latest_end_date.ctime())) - else: - if start_date < latest_end_date: - raise forms.ValidationError('Start date cannot be before an existing records latest end_date. Start Date must be after {}'.format(latest_end_date.ctime())) - - if self.instance.id: - if start_date < datetime.now(tz=tz_local) - timedelta(minutes=5) and start_date < self.instance.start_date.astimezone(tz_local): - raise forms.ValidationError('Start date cannot be edited to be further in the past') - else: - if start_date < datetime.now(tz=tz_local) - timedelta(minutes=5): - raise forms.ValidationError('Start date cannot be in the past') - - if end_date < start_date: - raise forms.ValidationError('End date cannot be before start date') - - super(SystemMaintenanceAdminForm, self).clean() - return cleaned_data - - diff --git a/commercialoperator/components/proposals/mixins.py b/commercialoperator/components/proposals/mixins.py deleted file mode 100755 index e313c27933..0000000000 --- a/commercialoperator/components/proposals/mixins.py +++ /dev/null @@ -1,11 +0,0 @@ -from django.core.exceptions import PermissionDenied - -class ReferralOwnerMixin(object): - - def check_owner(self, user): - return self.get_object().referral == user - - def dispatch(self, request, *args, **kwargs): - if not self.check_owner(request.user): - raise PermissionDenied - return super(ReferralMixin, self).dispatch(request, *args, **kwargs) diff --git a/commercialoperator/components/proposals/models.py b/commercialoperator/components/proposals/models.py deleted file mode 100755 index 9e395df9b3..0000000000 --- a/commercialoperator/components/proposals/models.py +++ /dev/null @@ -1,3595 +0,0 @@ -from __future__ import unicode_literals - -import json -import os -import datetime -import string -from dateutil.relativedelta import relativedelta -from django.db import models,transaction -from django.dispatch import receiver -from django.db.models.signals import pre_delete -from django.utils.encoding import python_2_unicode_compatible -from django.core.exceptions import ValidationError, MultipleObjectsReturned -from django.contrib.postgres.fields.jsonb import JSONField -from django.utils import timezone -from django.contrib.sites.models import Site -from django.conf import settings -from taggit.managers import TaggableManager -from taggit.models import TaggedItemBase -from ledger.accounts.models import Organisation as ledger_organisation -from ledger.accounts.models import OrganisationAddress -from ledger.accounts.models import EmailUser, RevisionedMixin -from ledger.payments.models import Invoice -#from ledger.accounts.models import EmailUser -from ledger.licence.models import Licence -from ledger.address.models import Country -from commercialoperator import exceptions -from commercialoperator.components.organisations.models import Organisation, OrganisationContact, UserDelegation -from commercialoperator.components.main.models import CommunicationsLogEntry, UserAction, Document, Region, District, Tenure, ApplicationType, Park, Activity, ActivityCategory, AccessType, Trail, Section, Zone, RequiredDocument#, RevisionedMixin -from commercialoperator.components.main.utils import get_department_user -from commercialoperator.components.proposals.email import send_referral_email_notification, send_proposal_decline_email_notification,send_proposal_approval_email_notification, send_amendment_email_notification -from commercialoperator.ordered_model import OrderedModel -from commercialoperator.components.proposals.email import send_submit_email_notification, send_external_submit_email_notification, send_approver_decline_email_notification, send_approver_approve_email_notification, send_referral_complete_email_notification, send_proposal_approver_sendback_email_notification, send_qaofficer_email_notification, send_qaofficer_complete_email_notification -import copy -import subprocess -from django.db.models import Q -from reversion.models import Version -from dirtyfields import DirtyFieldsMixin -from decimal import Decimal as D -import csv - -import logging -logger = logging.getLogger(__name__) - - -def update_proposal_doc_filename(instance, filename): - return '{}/proposals/{}/documents/{}'.format(settings.MEDIA_APP_DIR, instance.proposal.id,filename) - -def update_onhold_doc_filename(instance, filename): - return '{}/proposals/{}/on_hold/{}'.format(settings.MEDIA_APP_DIR, instance.proposal.id,filename) - -def update_qaofficer_doc_filename(instance, filename): - return '{}/proposals/{}/qaofficer/{}'.format(settings.MEDIA_APP_DIR, instance.proposal.id,filename) - -def update_referral_doc_filename(instance, filename): - return '{}/proposals/{}/referral/{}'.format(settings.MEDIA_APP_DIR, instance.referral.proposal.id,filename) - -def update_proposal_required_doc_filename(instance, filename): - return '{}/proposals/{}/required_documents/{}'.format(settings.MEDIA_APP_DIR, instance.proposal.id,filename) - -def update_requirement_doc_filename(instance, filename): - return '{}/proposals/{}/requirement_documents/{}'.format(settings.MEDIA_APP_DIR, instance.requirement.proposal.id,filename) - -def update_proposal_comms_log_filename(instance, filename): - return '{}/proposals/{}/communications/{}'.format(settings.MEDIA_APP_DIR, instance.log_entry.proposal.id,filename) - -def application_type_choicelist(): - try: - return [( (choice.name), (choice.name) ) for choice in ApplicationType.objects.filter(visible=True)] - except: - # required because on first DB tables creation, there are no ApplicationType objects -- setting a default value - return ( ('T Class', 'T Class'), ) - -class ProposalType(models.Model): - #name = models.CharField(verbose_name='Application name (eg. commercialoperator, Apiary)', max_length=24) - #application_type = models.ForeignKey(ApplicationType, related_name='aplication_types') - description = models.CharField(max_length=256, blank=True, null=True) - #name = models.CharField(verbose_name='Application name (eg. commercialoperator, Apiary)', max_length=24, choices=application_type_choicelist(), default=application_type_choicelist()[0][0]) - name = models.CharField(verbose_name='Application name (eg. T Class, Filming, Event, E Class)', max_length=64, choices=application_type_choicelist(), default='T Class') - schema = JSONField(default=[{}]) - #activities = TaggableManager(verbose_name="Activities",help_text="A comma-separated list of activities.") - #site = models.OneToOneField(Site, default='1') - replaced_by = models.ForeignKey('self', on_delete=models.PROTECT, blank=True, null=True) - version = models.SmallIntegerField(default=1, blank=False, null=False) - - def __str__(self): - return '{} - v{}'.format(self.name, self.version) - - class Meta: - app_label = 'commercialoperator' - unique_together = ('name', 'version') - -class TaggedProposalAssessorGroupRegions(TaggedItemBase): - content_object = models.ForeignKey("ProposalAssessorGroup") - - class Meta: - app_label = 'commercialoperator' - -class TaggedProposalAssessorGroupActivities(TaggedItemBase): - content_object = models.ForeignKey("ProposalAssessorGroup") - - class Meta: - app_label = 'commercialoperator' - -class ProposalAssessorGroup(models.Model): - name = models.CharField(max_length=255) - members = models.ManyToManyField(EmailUser) - region = models.ForeignKey(Region, null=True, blank=True) - default = models.BooleanField(default=False) - - class Meta: - app_label = 'commercialoperator' - verbose_name = "Application Assessor Group" - verbose_name_plural = "Application Assessor Group" - - def __str__(self): - return self.name - - def clean(self): - try: - default = ProposalAssessorGroup.objects.get(default=True) - except ProposalAssessorGroup.DoesNotExist: - default = None - - if self.pk: - if not self.default and not self.region: - raise ValidationError('Only default can have no region set for proposal assessor group. Please specifiy region') -# elif default and not self.default: -# raise ValidationError('There can only be one default proposal assessor group') - else: - if default and self.default: - raise ValidationError('There can only be one default proposal assessor group') - - def member_is_assigned(self,member): - for p in self.current_proposals: - if p.assigned_officer == member: - return True - return False - - @property - def current_proposals(self): - assessable_states = ['with_assessor','with_referral','with_assessor_requirements'] - return Proposal.objects.filter(processing_status__in=assessable_states) - - @property - def members_email(self): - return [i.email for i in self.members.all()] - -class TaggedProposalApproverGroupRegions(TaggedItemBase): - content_object = models.ForeignKey("ProposalApproverGroup") - - class Meta: - app_label = 'commercialoperator' - -class TaggedProposalApproverGroupActivities(TaggedItemBase): - content_object = models.ForeignKey("ProposalApproverGroup") - - class Meta: - app_label = 'commercialoperator' - -class ProposalApproverGroup(models.Model): - name = models.CharField(max_length=255) - #members = models.ManyToManyField(EmailUser,blank=True) - #regions = TaggableManager(verbose_name="Regions",help_text="A comma-separated list of regions.",through=TaggedProposalApproverGroupRegions,related_name = "+",blank=True) - #activities = TaggableManager(verbose_name="Activities",help_text="A comma-separated list of activities.",through=TaggedProposalApproverGroupActivities,related_name = "+",blank=True) - members = models.ManyToManyField(EmailUser) - region = models.ForeignKey(Region, null=True, blank=True) - default = models.BooleanField(default=False) - - class Meta: - app_label = 'commercialoperator' - verbose_name = "Application Approver Group" - verbose_name_plural = "Application Approver Group" - - def __str__(self): - return self.name - - def clean(self): - try: - default = ProposalApproverGroup.objects.get(default=True) - except ProposalApproverGroup.DoesNotExist: - default = None - - if self.pk: - if not self.default and not self.region: - raise ValidationError('Only default can have no region set for proposal assessor group. Please specifiy region') - -# if int(self.pk) != int(default.id): -# if default and self.default: -# raise ValidationError('There can only be one default proposal approver group') - else: - if default and self.default: - raise ValidationError('There can only be one default proposal approver group') - - def member_is_assigned(self,member): - for p in self.current_proposals: - if p.assigned_approver == member: - return True - return False - - @property - def current_proposals(self): - assessable_states = ['with_approver'] - return Proposal.objects.filter(processing_status__in=assessable_states) - - @property - def members_email(self): - return [i.email for i in self.members.all()] - - -class DefaultDocument(Document): - input_name = models.CharField(max_length=255,null=True,blank=True) - can_delete = models.BooleanField(default=True) # after initial submit prevent document from being deleted - visible = models.BooleanField(default=True) # to prevent deletion on file system, hidden and still be available in history - - class Meta: - app_label = 'commercialoperator' - abstract =True - - def delete(self): - if self.can_delete: - return super(DefaultDocument, self).delete() - logger.info('Cannot delete existing document object after Application has been submitted (including document submitted before Application pushback to status Draft): {}'.format(self.name)) - - - -class ProposalDocument(Document): - proposal = models.ForeignKey('Proposal',related_name='documents') - _file = models.FileField(upload_to=update_proposal_doc_filename) - input_name = models.CharField(max_length=255,null=True,blank=True) - can_delete = models.BooleanField(default=True) # after initial submit prevent document from being deleted - - class Meta: - app_label = 'commercialoperator' - verbose_name = "Application Document" - -class OnHoldDocument(Document): - proposal = models.ForeignKey('Proposal',related_name='onhold_documents') - _file = models.FileField(upload_to=update_onhold_doc_filename) - input_name = models.CharField(max_length=255,null=True,blank=True) - can_delete = models.BooleanField(default=True) # after initial submit prevent document from being deleted - visible = models.BooleanField(default=True) # to prevent deletion on file system, hidden and still be available in history - - def delete(self): - if self.can_delete: - return super(ProposalDocument, self).delete() - -#Documents on Activities(land)and Activities(Marine) tab for T-Class related to required document questions -class ProposalRequiredDocument(Document): - proposal = models.ForeignKey('Proposal',related_name='required_documents') - _file = models.FileField(upload_to=update_proposal_required_doc_filename) - input_name = models.CharField(max_length=255,null=True,blank=True) - can_delete = models.BooleanField(default=True) # after initial submit prevent document from being deleted - required_doc = models.ForeignKey('RequiredDocument',related_name='proposals') - - def delete(self): - if self.can_delete: - return super(ProposalRequiredDocument, self).delete() - logger.info('Cannot delete existing document object after Application has been submitted (including document submitted before Application pushback to status Draft): {}'.format(self.name)) - - class Meta: - app_label = 'commercialoperator' - -class QAOfficerDocument(Document): - proposal = models.ForeignKey('Proposal',related_name='qaofficer_documents') - _file = models.FileField(upload_to=update_qaofficer_doc_filename) - input_name = models.CharField(max_length=255,null=True,blank=True) - can_delete = models.BooleanField(default=True) # after initial submit prevent document from being deleted - visible = models.BooleanField(default=True) # to prevent deletion on file system, hidden and still be available in history - - def delete(self): - if self.can_delete: - return super(QAOfficerDocument, self).delete() - logger.info('Cannot delete existing document object after Application has been submitted (including document submitted before Application pushback to status Draft): {}'.format(self.name)) - - class Meta: - app_label = 'commercialoperator' - - -class ReferralDocument(Document): - referral = models.ForeignKey('Referral',related_name='referral_documents') - _file = models.FileField(upload_to=update_referral_doc_filename) - input_name = models.CharField(max_length=255,null=True,blank=True) - can_delete = models.BooleanField(default=True) # after initial submit prevent document from being deleted - - def delete(self): - if self.can_delete: - return super(ProposalDocument, self).delete() - logger.info('Cannot delete existing document object after Application has been submitted (including document submitted before Application pushback to status Draft): {}'.format(self.name)) - - class Meta: - app_label = 'commercialoperator' - -class RequirementDocument(Document): - requirement = models.ForeignKey('ProposalRequirement',related_name='requirement_documents') - _file = models.FileField(upload_to=update_requirement_doc_filename) - input_name = models.CharField(max_length=255,null=True,blank=True) - can_delete = models.BooleanField(default=True) # after initial submit prevent document from being deleted - visible = models.BooleanField(default=True) # to prevent deletion on file system, hidden and still be available in history - - def delete(self): - if self.can_delete: - return super(RequirementDocument, self).delete() - - -class ProposalApplicantDetails(models.Model): - first_name = models.CharField(max_length=24, blank=True, default='') - - class Meta: - app_label = 'commercialoperator' - - -class ProposalActivitiesLand(models.Model): - activities_land = models.CharField(max_length=24, blank=True, default='') - - class Meta: - app_label = 'commercialoperator' - verbose_name = "Application Activity (Land)" - verbose_name_plural = "Application Activities (Land)" - - -class ProposalActivitiesMarine(models.Model): - activities_marine = models.CharField(max_length=24, blank=True, default='') - - class Meta: - app_label = 'commercialoperator' - verbose_name = "Application Activity (Marine)" - verbose_name_plural = "Application Activities (Marine)" - - -@python_2_unicode_compatible -class ParkEntry(models.Model): - park = models.ForeignKey('Park', related_name='park_entries') - proposal = models.ForeignKey('Proposal', related_name='park_entries') - arrival_date = models.DateField() - number_adults = models.PositiveSmallIntegerField('No. of Adults', null=True, blank=True) - number_children = models.PositiveSmallIntegerField('No. of Children', null=True, blank=True) - number_seniors = models.PositiveSmallIntegerField('No. of Senior Citizens', null=True, blank=True) - number_free_of_charge = models.PositiveSmallIntegerField('No. of Individuals Free of Charge', null=True, blank=True) - - class Meta: - ordering = ['park__name'] - app_label = 'commercialoperator' - verbose_name = "Park Entry" - verbose_name_plural = "Park Entries" - #unique_together = ('id', 'proposal',) - - def __str__(self): - return self.park.name - - @property - def park_prices(self): - return self.park.park_prices - - @property - def price_adult(self): - return (self.park_prices.adult * self.number_adults) - - @property - def price_child(self): - return (self.park_prices.child * self.number_children) - - @property - def price_senior(self): - return (self.park_prices.senior * self.number_senior) - - @property - def price_net(self): - return (self.price_adult + self.price_child + self.price_senior) - - -class Proposal(DirtyFieldsMixin, RevisionedMixin): -#class Proposal(DirtyFieldsMixin, models.Model): - APPLICANT_TYPE_ORGANISATION = 'ORG' - APPLICANT_TYPE_PROXY = 'PRX' - APPLICANT_TYPE_SUBMITTER = 'SUB' - - CUSTOMER_STATUS_TEMP = 'temp' - CUSTOMER_STATUS_WITH_ASSESSOR = 'with_assessor' - CUSTOMER_STATUS_AMENDMENT_REQUIRED = 'amendment_required' - CUSTOMER_STATUS_APPROVED = 'approved' - CUSTOMER_STATUS_DECLINED = 'declined' - CUSTOMER_STATUS_DISCARDED = 'discarded' - CUSTOMER_STATUS_CHOICES = ((CUSTOMER_STATUS_TEMP, 'Temporary'), ('draft', 'Draft'), - (CUSTOMER_STATUS_WITH_ASSESSOR, 'Under Review'), - (CUSTOMER_STATUS_AMENDMENT_REQUIRED, 'Amendment Required'), - (CUSTOMER_STATUS_APPROVED, 'Approved'), - (CUSTOMER_STATUS_DECLINED, 'Declined'), - (CUSTOMER_STATUS_DISCARDED, 'Discarded'), - ) - - # List of statuses from above that allow a customer to edit an application. - CUSTOMER_EDITABLE_STATE = ['temp', - 'draft', - 'amendment_required', - ] - - # List of statuses from above that allow a customer to view an application (read-only) - CUSTOMER_VIEWABLE_STATE = ['with_assessor', 'under_review', 'id_required', 'returns_required', 'approved', 'declined'] - - PROCESSING_STATUS_TEMP = 'temp' - PROCESSING_STATUS_DRAFT = 'draft' - PROCESSING_STATUS_WITH_ASSESSOR = 'with_assessor' - PROCESSING_STATUS_ONHOLD = 'on_hold' - PROCESSING_STATUS_WITH_QA_OFFICER = 'with_qa_officer' - PROCESSING_STATUS_WITH_REFERRAL = 'with_referral' - PROCESSING_STATUS_WITH_ASSESSOR_REQUIREMENTS = 'with_assessor_requirements' - PROCESSING_STATUS_WITH_APPROVER = 'with_approver' - PROCESSING_STATUS_RENEWAL = 'renewal' - PROCESSING_STATUS_LICENCE_AMENDMENT = 'licence_amendment' - PROCESSING_STATUS_AWAITING_APPLICANT_RESPONSE = 'awaiting_applicant_respone' - PROCESSING_STATUS_AWAITING_ASSESSOR_RESPONSE = 'awaiting_assessor_response' - PROCESSING_STATUS_AWAITING_RESPONSES = 'awaiting_responses' - PROCESSING_STATUS_READY_FOR_CONDITIONS = 'ready_for_conditions' - PROCESSING_STATUS_READY_TO_ISSUE = 'ready_to_issue' - PROCESSING_STATUS_APPROVED = 'approved' - PROCESSING_STATUS_DECLINED = 'declined' - PROCESSING_STATUS_DISCARDED = 'discarded' - PROCESSING_STATUS_CHOICES = ((PROCESSING_STATUS_TEMP, 'Temporary'), - (PROCESSING_STATUS_DRAFT, 'Draft'), - (PROCESSING_STATUS_WITH_ASSESSOR, 'With Assessor'), - (PROCESSING_STATUS_ONHOLD, 'On Hold'), - (PROCESSING_STATUS_WITH_QA_OFFICER, 'With QA Officer'), - (PROCESSING_STATUS_WITH_REFERRAL, 'With Referral'), - (PROCESSING_STATUS_WITH_ASSESSOR_REQUIREMENTS, 'With Assessor (Requirements)'), - (PROCESSING_STATUS_WITH_APPROVER, 'With Approver'), - (PROCESSING_STATUS_RENEWAL, 'Renewal'), - (PROCESSING_STATUS_LICENCE_AMENDMENT, 'Licence Amendment'), - (PROCESSING_STATUS_AWAITING_APPLICANT_RESPONSE, 'Awaiting Applicant Response'), - (PROCESSING_STATUS_AWAITING_ASSESSOR_RESPONSE, 'Awaiting Assessor Response'), - (PROCESSING_STATUS_AWAITING_RESPONSES, 'Awaiting Responses'), - (PROCESSING_STATUS_READY_FOR_CONDITIONS, 'Ready for Conditions'), - (PROCESSING_STATUS_READY_TO_ISSUE, 'Ready to Issue'), - (PROCESSING_STATUS_APPROVED, 'Approved'), - (PROCESSING_STATUS_DECLINED, 'Declined'), - (PROCESSING_STATUS_DISCARDED, 'Discarded'), - ) - - ID_CHECK_STATUS_CHOICES = (('not_checked', 'Not Checked'), ('awaiting_update', 'Awaiting Update'), - ('updated', 'Updated'), ('accepted', 'Accepted')) - - COMPLIANCE_CHECK_STATUS_CHOICES = ( - ('not_checked', 'Not Checked'), ('awaiting_returns', 'Awaiting Returns'), ('completed', 'Completed'), - ('accepted', 'Accepted')) - - CHARACTER_CHECK_STATUS_CHOICES = ( - ('not_checked', 'Not Checked'), ('accepted', 'Accepted')) - - REVIEW_STATUS_CHOICES = ( - ('not_reviewed', 'Not Reviewed'), ('awaiting_amendments', 'Awaiting Amendments'), ('amended', 'Amended'), - ('accepted', 'Accepted')) - -# PROPOSAL_STATE_NEW_LICENCE = 'New Licence' -# PROPOSAL_STATE_AMENDMENT = 'Amendment' -# PROPOSAL_STATE_RENEWAL = 'Renewal' -# PROPOSAL_STATE_CHOICES = ( -# (1, PROPOSAL_STATE_NEW_LICENCE), -# (2, PROPOSAL_STATE_AMENDMENT), -# (3, PROPOSAL_STATE_RENEWAL), -# ) - - APPLICATION_TYPE_CHOICES = ( - ('new_proposal', 'New Application'), - ('amendment', 'Amendment'), - ('renewal', 'Renewal'), - ('external', 'External'), - ) - - proposal_type = models.CharField('Application Status Type', max_length=40, choices=APPLICATION_TYPE_CHOICES, - default=APPLICATION_TYPE_CHOICES[0][0]) - #proposal_state = models.PositiveSmallIntegerField('Proposal state', choices=PROPOSAL_STATE_CHOICES, default=1) - - data = JSONField(blank=True, null=True) - assessor_data = JSONField(blank=True, null=True) - comment_data = JSONField(blank=True, null=True) - schema = JSONField(blank=False, null=False) - proposed_issuance_approval = JSONField(blank=True, null=True) - #hard_copy = models.ForeignKey(Document, blank=True, null=True, related_name='hard_copy') - - customer_status = models.CharField('Customer Status', max_length=40, choices=CUSTOMER_STATUS_CHOICES, - default=CUSTOMER_STATUS_CHOICES[1][0]) - #applicant = models.ForeignKey(Organisation, blank=True, null=True, related_name='proposals') - org_applicant = models.ForeignKey( - Organisation, - blank=True, - null=True, - related_name='org_applications') - lodgement_number = models.CharField(max_length=9, blank=True, default='') - lodgement_sequence = models.IntegerField(blank=True, default=0) - #lodgement_date = models.DateField(blank=True, null=True) - lodgement_date = models.DateTimeField(blank=True, null=True) - - proxy_applicant = models.ForeignKey(EmailUser, blank=True, null=True, related_name='commercialoperator_proxy') - submitter = models.ForeignKey(EmailUser, blank=True, null=True, related_name='commercialoperator_proposals') - - assigned_officer = models.ForeignKey(EmailUser, blank=True, null=True, related_name='commercialoperator_proposals_assigned', on_delete=models.SET_NULL) - assigned_approver = models.ForeignKey(EmailUser, blank=True, null=True, related_name='commercialoperator_proposals_approvals', on_delete=models.SET_NULL) - processing_status = models.CharField('Processing Status', max_length=30, choices=PROCESSING_STATUS_CHOICES, - default=PROCESSING_STATUS_CHOICES[1][0]) - prev_processing_status = models.CharField(max_length=30, blank=True, null=True) - id_check_status = models.CharField('Identification Check Status', max_length=30, choices=ID_CHECK_STATUS_CHOICES, - default=ID_CHECK_STATUS_CHOICES[0][0]) - compliance_check_status = models.CharField('Return Check Status', max_length=30, choices=COMPLIANCE_CHECK_STATUS_CHOICES, - default=COMPLIANCE_CHECK_STATUS_CHOICES[0][0]) - character_check_status = models.CharField('Character Check Status', max_length=30, - choices=CHARACTER_CHECK_STATUS_CHOICES, - default=CHARACTER_CHECK_STATUS_CHOICES[0][0]) - review_status = models.CharField('Review Status', max_length=30, choices=REVIEW_STATUS_CHOICES, - default=REVIEW_STATUS_CHOICES[0][0]) - - approval = models.ForeignKey('commercialoperator.Approval',null=True,blank=True) - - previous_application = models.ForeignKey('self', on_delete=models.PROTECT, blank=True, null=True) - proposed_decline_status = models.BooleanField(default=False) - #qaofficer_referral = models.BooleanField(default=False) - #qaofficer_referral = models.OneToOneField('QAOfficerReferral', blank=True, null=True) - # Special Fields - title = models.CharField(max_length=255,null=True,blank=True) - activity = models.CharField(max_length=255,null=True,blank=True) - #region = models.CharField(max_length=255,null=True,blank=True) - tenure = models.CharField(max_length=255,null=True,blank=True) - #activity = models.ForeignKey(Activity, null=True, blank=True) - region = models.ForeignKey(Region, null=True, blank=True) - district = models.ForeignKey(District, null=True, blank=True) - #tenure = models.ForeignKey(Tenure, null=True, blank=True) - application_type = models.ForeignKey(ApplicationType) - approval_level = models.CharField('Activity matrix approval level', max_length=255,null=True,blank=True) - approval_level_document = models.ForeignKey(ProposalDocument, blank=True, null=True, related_name='approval_level_document') - approval_comment = models.TextField(blank=True) - #If the proposal is created as part of migration of approvals - migrated=models.BooleanField(default=False) - - - # common - #applicant_details = models.OneToOneField(ProposalApplicantDetails, blank=True, null=True) #, related_name='applicant_details') - training_completed = models.BooleanField(default=False) - #payment = models.OneToOneField(ProposalPayment, blank=True, null=True) - #confirmation = models.OneToOneField(ProposalConfirmation, blank=True, null=True) - - # T Class - activities_land = models.OneToOneField(ProposalActivitiesLand, blank=True, null=True) #, related_name='activities_land') - activities_marine = models.OneToOneField(ProposalActivitiesMarine, blank=True, null=True) #, related_name='activities_marine') - #other_details = models.OneToOneField(ProposalOtherDetails, blank=True, null=True, related_name='proposal') - #online_training = models.OneToOneField(ProposalOnlineTraining, blank=True, null=True) - - # Filming - #activity = models.OneToOneField(ProposalActivity, blank=True, null=True) - #access = models.OneToOneField(ProposalAccess, blank=True, null=True) - #equipment = models.OneToOneField(ProposalEquipment, blank=True, null=True) - #other_details = models.OneToOneField(ProposalOtherDetails, blank=True, null=True) - #online_training = models.OneToOneField(ProposalOnlineTraining, blank=True, null=True) - - # Event - #activities = models.OneToOneField(ProposalActivities, blank=True, null=True) - #event_management = models.OneToOneField(ProposalEventManagement, blank=True, null=True) - #vehicles_vessels = models.OneToOneField(ProposalVehiclesVessels, blank=True, null=True) - #other_details = models.OneToOneField(ProposalOtherDetails, blank=True, null=True) - #online_training = models.OneToOneField(ProposalOnlineTraining, blank=True, null=True) - - fee_invoice_reference = models.CharField(max_length=50, null=True, blank=True, default='') - - class Meta: - app_label = 'commercialoperator' - verbose_name = "Application" - verbose_name_plural = "Applications" - - def __str__(self): - return str(self.id) - - #Append 'P' to Proposal id to generate Lodgement number. Lodgement number and lodgement sequence are used to generate Reference. - def save(self, *args, **kwargs): - orig_processing_status = self._original_state['processing_status'] - super(Proposal, self).save(*args,**kwargs) - if self.processing_status != orig_processing_status: - self.save(version_comment='processing_status: {}'.format(self.processing_status)) - - if self.lodgement_number == '' and self.application_type.name != 'E Class': - new_lodgment_id = 'A{0:06d}'.format(self.pk) - self.lodgement_number = new_lodgment_id - self.save(version_comment='processing_status: {}'.format(self.processing_status)) - - @property - def fee_paid(self): - return True if self.fee_invoice_reference else False - - @property - def fee_amount(self): - return Invoice.objects.get(reference=self.fee_invoice_reference).amount if self.fee_paid else None - - @property - def licence_fee_amount(self): - period = self.other_details.preferred_licence_period - if period.split('_')[1].endswith('months'): - return self.application_type.licence_fee_2mth - else: - return int(period.split('_')[0]) * self.application_type.licence_fee_1yr - - @property - def reference(self): - return '{}-{}'.format(self.lodgement_number, self.lodgement_sequence) - - @property - def reversion_ids(self): - current_revision_id = Version.objects.get_for_object(self).first().revision_id - versions = Version.objects.get_for_object(self).select_related("revision__user").filter(Q(revision__comment__icontains='status') | Q(revision_id=current_revision_id)) - version_ids = [[i.id,i.revision.date_created] for i in versions] - return [dict(cur_version_id=version_ids[0][0], prev_version_id=version_ids[i+1][0], created=version_ids[i][1]) for i in range(len(version_ids)-1)] - - @property - def applicant(self): - if self.org_applicant: - return self.org_applicant.organisation.name - elif self.proxy_applicant: - return "{} {}".format( - self.proxy_applicant.first_name, - self.proxy_applicant.last_name) - else: - return "{} {}".format( - self.submitter.first_name, - self.submitter.last_name) - - @property - def applicant_email(self): - if self.org_applicant and hasattr(self.org_applicant.organisation, 'email') and self.org_applicant.organisation.email: - return self.org_applicant.organisation.email - elif self.proxy_applicant: - return self.proxy_applicant.email - else: - return self.submitter.email - - @property - def applicant_details(self): - if self.org_applicant: - return '{} \n{}'.format( - self.org_applicant.organisation.name, - self.org_applicant.address) - elif self.proxy_applicant: - return "{} {}\n{}".format( - self.proxy_applicant.first_name, - self.proxy_applicant.last_name, - self.proxy_applicant.addresses.all().first()) - else: - return "{} {}\n{}".format( - self.submitter.first_name, - self.submitter.last_name, - self.submitter.addresses.all().first()) - - @property - def applicant_address(self): - if self.org_applicant: - return self.org_applicant.address - elif self.proxy_applicant: - #return self.proxy_applicant.addresses.all().first() - return self.proxy_applicant.residential_address - else: - #return self.submitter.addresses.all().first() - return self.submitter.residential_address - - @property - def applicant_id(self): - if self.org_applicant: - return self.org_applicant.id - elif self.proxy_applicant: - return self.proxy_applicant.id - else: - return self.submitter.id - - @property - def applicant_type(self): - if self.org_applicant: - return self.APPLICANT_TYPE_ORGANISATION - elif self.proxy_applicant: - return self.APPLICANT_TYPE_PROXY - else: - return self.APPLICANT_TYPE_SUBMITTER - - @property - def applicant_field(self): - if self.org_applicant: - return 'org_applicant' - elif self.proxy_applicant: - return 'proxy_applicant' - else: - return 'submitter' - - def qa_officers(self, name=None): - if not name: - return QAOfficerGroup.objects.get(default=True).members.all().values_list('email', flat=True) - else: - return QAOfficerGroup.objects.get(name=name).members.all().values_list('email', flat=True) - - @property - def get_history(self): - """ Return the prev proposal versions """ - l = [] - p = copy.deepcopy(self) - while (p.previous_application): - l.append( dict(id=p.previous_application.id, modified=p.previous_application.modified_date) ) - p = p.previous_application - return l - -# def _get_history(self): -# """ Return the prev proposal versions """ -# l = [] -# p = copy.deepcopy(self) -# while (p.previous_application): -# l.append( [p.id, p.previous_application.id] ) -# p = p.previous_application -# return l - - @property - def is_assigned(self): - return self.assigned_officer is not None - - @property - def is_temporary(self): - return self.customer_status == 'temp' and self.processing_status == 'temp' - - @property - def can_user_edit(self): - """ - :return: True if the application is in one of the editable status. - """ - return self.customer_status in self.CUSTOMER_EDITABLE_STATE - - @property - def can_user_view(self): - """ - :return: True if the application is in one of the approved status. - """ - return self.customer_status in self.CUSTOMER_VIEWABLE_STATE - - - - @property - def is_discardable(self): - """ - An application can be discarded by a customer if: - 1 - It is a draft - 2- or if the application has been pushed back to the user - """ - return self.customer_status == 'draft' or self.processing_status == 'awaiting_applicant_response' - - @property - def is_deletable(self): - """ - An application can be deleted only if it is a draft and it hasn't been lodged yet - :return: - """ - return self.customer_status == 'draft' and not self.lodgement_number - - @property - def latest_referrals(self): - return self.referrals.all()[:2] - - @property - def land_parks(self): - return self.parks.filter(park__park_type='land') - - @property - def land_parks_exclude_free(self): - """ exlude parks with free admission """ - return self.parks.filter(park__park_type='land').exclude(park__adult_price=D(0.0), park__child_price=D(0.0)) - - @property - def marine_parks(self): - return self.parks.filter(park__park_type='marine') - - @property - def regions_list(self): - #return self.region.split(',') if self.region else [] - return [self.region.name] if self.region else [] - - @property - def assessor_assessment(self): - qs=self.assessment.filter(referral_assessment=False, referral_group=None) - if qs: - return qs[0] - else: - return None - - @property - def referral_assessments(self): - qs=self.assessment.filter(referral_assessment=True, referral_group__isnull=False) - if qs: - return qs - else: - return None - - - @property - def permit(self): - return self.approval.licence_document._file.url if self.approval else None - - @property - def allowed_assessors(self): - if self.processing_status == 'with_approver': - group = self.__approver_group() - elif self.processing_status =='with_qa_officer': - group = QAOfficerGroup.objects.get(default=True) - else: - group = self.__assessor_group() - return group.members.all() if group else [] - - @property - def compliance_assessors(self): - group = self.__assessor_group() - return group.members.all() if group else [] - - @property - def can_officer_process(self): - """ - :return: True if the application is in one of the processable status for Assessor role. - """ - #officer_view_state = ['draft','approved','declined','temp','discarded'] - officer_view_state = ['draft','approved','declined','temp','discarded', 'with_referral', 'with_qa_officer'] - if self.processing_status in officer_view_state: - return False - else: - return True - - @property - def amendment_requests(self): - qs =AmendmentRequest.objects.filter(proposal = self) - return qs - - #Check if there is an pending amendment request exist for the proposal - @property - def pending_amendment_request(self): - qs =AmendmentRequest.objects.filter(proposal = self, status = "requested") - if qs: - return True - return False - - @property - def is_amendment_proposal(self): - if self.proposal_type=='amendment': - return True - return False - - @property - def search_data(self): - search_data={} - parks=[] - trails=[] - activities=[] - vehicles=[] - vessels=[] - accreditations=[] - for p in self.parks.all(): - parks.append(p.park.name) - if p.park.park_type=='land': - for a in p.activities.all(): - activities.append(a.activity_name) - if p.park.park_type=='marine': - for z in p.zones.all(): - for a in z.park_activities.all(): - activities.append(a.activity_name) - for t in self.trails.all(): - trails.append(t.trail.name) - for s in t.sections.all(): - for ts in s.trail_activities.all(): - activities.append(ts.activity_name) - for v in self.vehicles.all(): - vehicles.append(v.rego) - for vs in self.vessels.all(): - vessels.append(vs.spv_no) - search_data.update({'parks': parks}) - search_data.update({'trails': trails}) - search_data.update({'vehicles': vehicles}) - search_data.update({'vessels': vessels}) - search_data.update({'activities': activities}) - - try: - other_details=ProposalOtherDetails.objects.get(proposal=self) - search_data.update({'other_details': other_details.other_comments}) - search_data.update({'mooring': other_details.mooring}) - for acr in other_details.accreditations.all(): - accreditations.append(acr.get_accreditation_type_display()) - search_data.update({'accreditations': accreditations}) - except ProposalOtherDetails.DoesNotExist: - search_data.update({'other_details': []}) - search_data.update({'mooring': []}) - search_data.update({'accreditations':[]}) - return search_data - - @property - def selected_parks_activities(self): - #list of selected parks and activities (to print on licence pdf) - selected_parks_activities=[] - for p in self.parks.all(): - park_activities=[] - #parks.append(p.park.name) - if p.park.park_type=='land': - for a in p.activities.all(): - park_activities.append(a.activity_name) - selected_parks_activities.append({'park': p.park.name, 'activities': park_activities}) - if p.park.park_type=='marine': - zone_activities=[] - for z in p.zones.all(): - for a in z.park_activities.all(): - zone_activities.append(a.activity_name) - selected_parks_activities.append({'park': '{} - {}'.format(p.park.name, z.zone.name), 'activities': park_activities}) - for t in self.trails.all(): - #trails.append(t.trail.name) - #trail_activities=[] - for s in t.sections.all(): - trail_activities=[] - for ts in s.trail_activities.all(): - trail_activities.append(ts.activity_name) - selected_parks_activities.append({'park': '{} - {}'.format(t.trail.name, s.section.name), 'activities': trail_activities}) - return selected_parks_activities - - @property - def selected_parks_activities_pdf(self): - """ duplicated selected_parks_activities to quickly fix the pdf licence generation of marine zonal activities - which was not previously displayed correctly. This function is called by pdf.py only. """ - #list of selected parks and activities (to print on licence pdf) - selected_parks_activities=[] - for p in self.parks.all(): - park_activities=[] - #parks.append(p.park.name) - if p.park.park_type=='land': - for a in p.activities.all(): - park_activities.append(a.activity_name) - selected_parks_activities.append({'park': p.park.name, 'activities': park_activities}) - if p.park.park_type=='marine': - for z in p.zones.all(): - zone_activities = [] - for a in z.park_activities.all(): - zone_activities.append(a.activity_name) - selected_parks_activities.append({'park': '{} - {}'.format(p.park.name, z.zone.name), 'activities': zone_activities}) - for t in self.trails.all(): - #trails.append(t.trail.name) - #trail_activities=[] - for s in t.sections.all(): - trail_activities=[] - for ts in s.trail_activities.all(): - trail_activities.append(ts.activity_name) - selected_parks_activities.append({'park': '{} - {}'.format(t.trail.name, s.section.name), 'activities': trail_activities}) - return selected_parks_activities - - @property - def selected_parks_access_types_pdf(self): - #list of selected parks and access_types (to print on licence pdf) - selected_park_access_types=[] - for p in self.parks.all(): - park_access_types=[] - if p.park.park_type=='land': - for a in p.access_types.all(): - park_access_types.append(a.access_type.name) - selected_park_access_types.append({'park': p.park.name, 'access_types': park_access_types}) - return selected_park_access_types - - def __assessor_group(self): - # TODO get list of assessor groups based on region and activity - if self.region and self.activity: - try: - check_group = ProposalAssessorGroup.objects.filter( - #activities__name__in=[self.activity], - region__name__in=self.regions_list - ).distinct() - if check_group: - return check_group[0] - except ProposalAssessorGroup.DoesNotExist: - pass - default_group = ProposalAssessorGroup.objects.get(default=True) - - return default_group - - - def __approver_group(self): - # TODO get list of approver groups based on region and activity - if self.region and self.activity: - try: - check_group = ProposalApproverGroup.objects.filter( - #activities__name__in=[self.activity], - region__name__in=self.regions_list - ).distinct() - if check_group: - return check_group[0] - except ProposalApproverGroup.DoesNotExist: - pass - default_group = ProposalApproverGroup.objects.get(default=True) - - return default_group - - def __check_proposal_filled_out(self): - if not self.data: - raise exceptions.ProposalNotComplete() - missing_fields = [] - required_fields = { - # 'region':'Region/District', - # 'title': 'Title', - # 'activity': 'Activity' - } - for k,v in required_fields.items(): - val = getattr(self,k) - if not val: - missing_fields.append(v) - return missing_fields - - @property - def assessor_recipients(self): - recipients = [] - try: - recipients = ProposalAssessorGroup.objects.get(region=self.region).members_email - except: - recipients = ProposalAssessorGroup.objects.get(default=True).members_email - - #if self.submitter.email not in recipients: - # recipients.append(self.submitter.email) - return recipients - - @property - def approver_recipients(self): - recipients = [] - try: - recipients = ProposalApproverGroup.objects.get(region=self.region).members_email - except: - recipients = ProposalApproverGroup.objects.get(default=True).members_email - - #if self.submitter.email not in recipients: - # recipients.append(self.submitter.email) - return recipients - - #Check if the user is member of assessor group for the Proposal - def is_assessor(self,user): - return self.__assessor_group() in user.proposalassessorgroup_set.all() - - #Check if the user is member of assessor group for the Proposal - def is_approver(self,user): - return self.__approver_group() in user.proposalapprovergroup_set.all() - - - def can_assess(self,user): - #if self.processing_status == 'on_hold' or self.processing_status == 'with_assessor' or self.processing_status == 'with_referral' or self.processing_status == 'with_assessor_requirements': - if self.processing_status in ['on_hold', 'with_qa_officer', 'with_assessor', 'with_referral', 'with_assessor_requirements']: - return self.__assessor_group() in user.proposalassessorgroup_set.all() - elif self.processing_status == 'with_approver': - return self.__approver_group() in user.proposalapprovergroup_set.all() - else: - return False - - #To allow/ prevent internal user to edit activities (Land and Marine) for T-class licence - #still need to check to assessor mode in on or not - def can_edit_activities(self,user): - if self.processing_status == 'with_assessor' or self.processing_status == 'with_assessor_requirements': - return self.__assessor_group() in user.proposalassessorgroup_set.all() - elif self.processing_status == 'with_approver': - return self.__approver_group() in user.proposalapprovergroup_set.all() - else: - return False - - def assessor_comments_view(self,user): - - if self.processing_status == 'with_assessor' or self.processing_status == 'with_referral' or self.processing_status == 'with_assessor_requirements' or self.processing_status == 'with_approver': - try: - referral = Referral.objects.get(proposal=self,referral=user) - except: - referral = None - if referral: - return True - elif self.__assessor_group() in user.proposalassessorgroup_set.all(): - return True - elif self.__approver_group() in user.proposalapprovergroup_set.all(): - return True - else: - return False - else: - return False - - def has_assessor_mode(self,user): - status_without_assessor = ['with_approver','approved','declined','draft'] - if self.processing_status in status_without_assessor: - return False - else: - if self.assigned_officer: - if self.assigned_officer == user: - return self.__assessor_group() in user.proposalassessorgroup_set.all() - else: - return False - else: - return self.__assessor_group() in user.proposalassessorgroup_set.all() - - def log_user_action(self, action, request): - return ProposalUserAction.log_action(self, action, request.user) - - def submit(self,request,viewset): - from commercialoperator.components.proposals.utils import save_proponent_data - with transaction.atomic(): - if self.can_user_edit: - # Save the data first - save_proponent_data(self,request,viewset) - # Check if the special fields have been completed - missing_fields = self.__check_proposal_filled_out() - if missing_fields: - error_text = 'The proposal has these missing fields, {}'.format(','.join(missing_fields)) - raise exceptions.ProposalMissingFields(detail=error_text) - self.submitter = request.user - #self.lodgement_date = datetime.datetime.strptime(timezone.now().strftime('%Y-%m-%d'),'%Y-%m-%d').date() - self.lodgement_date = timezone.now() - if (self.amendment_requests): - qs = self.amendment_requests.filter(status = "requested") - if (qs): - for q in qs: - q.status = 'amended' - q.save() - - # Create a log entry for the proposal - self.log_user_action(ProposalUserAction.ACTION_LODGE_APPLICATION.format(self.id),request) - # Create a log entry for the organisation - #self.applicant.log_user_action(ProposalUserAction.ACTION_LODGE_APPLICATION.format(self.id),request) - applicant_field=getattr(self, self.applicant_field) - applicant_field.log_user_action(ProposalUserAction.ACTION_LODGE_APPLICATION.format(self.id),request) - - ret1 = send_submit_email_notification(request, self) - ret2 = send_external_submit_email_notification(request, self) - - #self.save_form_tabs(request) - if ret1 and ret2: - self.processing_status = 'with_assessor' - self.customer_status = 'with_assessor' - self.documents.all().update(can_delete=False) - self.save() - else: - raise ValidationError('An error occurred while submitting proposal (Submit email notifications failed)') - #Create assessor checklist with the current assessor_list type questions - #Assessment instance already exits then skip. - try: - assessor_assessment=ProposalAssessment.objects.get(proposal=self,referral_group=None, referral_assessment=False) - except ProposalAssessment.DoesNotExist: - assessor_assessment=ProposalAssessment.objects.create(proposal=self,referral_group=None, referral_assessment=False) - checklist=ChecklistQuestion.objects.filter(list_type='assessor_list', obsolete=False) - for chk in checklist: - try: - chk_instance=ProposalAssessmentAnswer.objects.get(question=chk, assessment=assessor_assessment) - except ProposalAssessmentAnswer.DoesNotExist: - chk_instance=ProposalAssessmentAnswer.objects.create(question=chk, assessment=assessor_assessment) - - else: - raise ValidationError('You can\'t edit this proposal at this moment') - - #TODO: remove this function as it is not used anywhere. - def save_form_tabs(self,request): - #self.applicant_details = ProposalApplicantDetails.objects.create(first_name=request.data['first_name']) - self.activities_land = ProposalActivitiesLand.objects.create(activities_land=request.data['activities_land']) - self.activities_marine = ProposalActivitiesMarine.objects.create(activities_marine=request.data['activities_marine']) - #self.save() - - def save_parks(self,request,parks): - with transaction.atomic(): - if parks: - try: - current_parks=self.parks.all() - if current_parks: - #print current_parks - for p in current_parks: - p.delete() - for item in parks: - try: - park=Park.objects.get(id=item) - ProposalPark.objects.create(proposal=self, park=park) - except: - raise - except: - raise - - - - def update(self,request,viewset): - from commercialoperator.components.proposals.utils import save_proponent_data - with transaction.atomic(): - if self.can_user_edit: - # Save the data first - save_proponent_data(self,request,viewset) - self.save() - else: - raise ValidationError('You can\'t edit this proposal at this moment') - - - def send_referral(self,request,referral_email,referral_text): - with transaction.atomic(): - try: - if self.processing_status == 'with_assessor' or self.processing_status == 'with_referral': - self.processing_status = 'with_referral' - self.save() - referral = None - - # Check if the user is in ledger - try: - #user = EmailUser.objects.get(email__icontains=referral_email) - referral_group = ReferralRecipientGroup.objects.get(name__icontains=referral_email) - #except EmailUser.DoesNotExist: - except ReferralRecipientGroup.DoesNotExist: - raise exceptions.ProposalReferralCannotBeSent() -# # Validate if it is a deparment user -# department_user = get_department_user(referral_email) -# if not department_user: -# raise ValidationError('The user you want to send the referral to is not a member of the department') -# # Check if the user is in ledger or create -# email = department_user['email'].lower() -# user,created = EmailUser.objects.get_or_create(email=department_user['email'].lower()) -# if created: -# user.first_name = department_user['given_name'] -# user.last_name = department_user['surname'] -# user.save() - try: - #Referral.objects.get(referral=user,proposal=self) - Referral.objects.get(referral_group=referral_group,proposal=self) - raise ValidationError('A referral has already been sent to this group') - except Referral.DoesNotExist: - # Create Referral - referral = Referral.objects.create( - proposal = self, - #referral=user, - referral_group=referral_group, - sent_by=request.user, - text=referral_text - ) - #Create assessor checklist with the current assessor_list type questions - #Assessment instance already exits then skip. - try: - referral_assessment=ProposalAssessment.objects.get(proposal=self,referral_group=referral_group, referral_assessment=True, referral=referral) - except ProposalAssessment.DoesNotExist: - referral_assessment=ProposalAssessment.objects.create(proposal=self,referral_group=referral_group, referral_assessment=True, referral=referral) - checklist=ChecklistQuestion.objects.filter(list_type='referral_list', obsolete=False) - for chk in checklist: - try: - chk_instance=ProposalAssessmentAnswer.objects.get(question=chk, assessment=referral_assessment) - except ProposalAssessmentAnswer.DoesNotExist: - chk_instance=ProposalAssessmentAnswer.objects.create(question=chk, assessment=referral_assessment) - # Create a log entry for the proposal - #self.log_user_action(ProposalUserAction.ACTION_SEND_REFERRAL_TO.format(referral.id,self.id,'{}({})'.format(user.get_full_name(),user.email)),request) - self.log_user_action(ProposalUserAction.ACTION_SEND_REFERRAL_TO.format(referral.id,self.id,'{}'.format(referral_group.name)),request) - # Create a log entry for the organisation - #self.applicant.log_user_action(ProposalUserAction.ACTION_SEND_REFERRAL_TO.format(referral.id,self.id,'{}({})'.format(user.get_full_name(),user.email)),request) - applicant_field=getattr(self, self.applicant_field) - applicant_field.log_user_action(ProposalUserAction.ACTION_SEND_REFERRAL_TO.format(referral.id,self.id,'{}'.format(referral_group.name)),request) - # send email - recipients = referral_group.members_list - send_referral_email_notification(referral,recipients,request) - else: - raise exceptions.ProposalReferralCannotBeSent() - except: - raise - - def assign_officer(self,request,officer): - with transaction.atomic(): - try: - if not self.can_assess(request.user): - raise exceptions.ProposalNotAuthorized() - if not self.can_assess(officer): - raise ValidationError('The selected person is not authorised to be assigned to this proposal') - if self.processing_status == 'with_approver': - if officer != self.assigned_approver: - self.assigned_approver = officer - self.save() - # Create a log entry for the proposal - self.log_user_action(ProposalUserAction.ACTION_ASSIGN_TO_APPROVER.format(self.id,'{}({})'.format(officer.get_full_name(),officer.email)),request) - # Create a log entry for the organisation - applicant_field=getattr(self, self.applicant_field) - applicant_field.log_user_action(ProposalUserAction.ACTION_ASSIGN_TO_APPROVER.format(self.id,'{}({})'.format(officer.get_full_name(),officer.email)),request) - else: - if officer != self.assigned_officer: - self.assigned_officer = officer - self.save() - # Create a log entry for the proposal - self.log_user_action(ProposalUserAction.ACTION_ASSIGN_TO_ASSESSOR.format(self.id,'{}({})'.format(officer.get_full_name(),officer.email)),request) - # Create a log entry for the organisation - applicant_field=getattr(self, self.applicant_field) - applicant_field.log_user_action(ProposalUserAction.ACTION_ASSIGN_TO_ASSESSOR.format(self.id,'{}({})'.format(officer.get_full_name(),officer.email)),request) - except: - raise - - def assing_approval_level_document(self, request): - with transaction.atomic(): - try: - approval_level_document = request.data['approval_level_document'] - if approval_level_document != 'null': - try: - document = self.documents.get(input_name=str(approval_level_document)) - except ProposalDocument.DoesNotExist: - document = self.documents.get_or_create(input_name=str(approval_level_document), name=str(approval_level_document))[0] - document.name = str(approval_level_document) - # commenting out below tow lines - we want to retain all past attachments - reversion can use them - #if document._file and os.path.isfile(document._file.path): - # os.remove(document._file.path) - document._file = approval_level_document - document.save() - d=ProposalDocument.objects.get(id=document.id) - self.approval_level_document = d - comment = 'Approval Level Document Added: {}'.format(document.name) - else: - self.approval_level_document = None - comment = 'Approval Level Document Deleted: {}'.format(request.data['approval_level_document_name']) - #self.save() - self.save(version_comment=comment) # to allow revision to be added to reversion history - self.log_user_action(ProposalUserAction.ACTION_APPROVAL_LEVEL_DOCUMENT.format(self.id),request) - # Create a log entry for the organisation - applicant_field=getattr(self, self.applicant_field) - applicant_field.log_user_action(ProposalUserAction.ACTION_APPROVAL_LEVEL_DOCUMENT.format(self.id),request) - return self - except: - raise - - def unassign(self,request): - with transaction.atomic(): - try: - if not self.can_assess(request.user): - raise exceptions.ProposalNotAuthorized() - if self.processing_status == 'with_approver': - if self.assigned_approver: - self.assigned_approver = None - self.save() - # Create a log entry for the proposal - self.log_user_action(ProposalUserAction.ACTION_UNASSIGN_APPROVER.format(self.id),request) - # Create a log entry for the organisation - applicant_field=getattr(self, self.applicant_field) - applicant_field.log_user_action(ProposalUserAction.ACTION_UNASSIGN_APPROVER.format(self.id),request) - else: - if self.assigned_officer: - self.assigned_officer = None - self.save() - # Create a log entry for the proposal - self.log_user_action(ProposalUserAction.ACTION_UNASSIGN_ASSESSOR.format(self.id),request) - # Create a log entry for the organisation - applicant_field=getattr(self, self.applicant_field) - applicant_field.log_user_action(ProposalUserAction.ACTION_UNASSIGN_ASSESSOR.format(self.id),request) - except: - raise - - def move_to_status(self,request,status, approver_comment): - if not self.can_assess(request.user): - raise exceptions.ProposalNotAuthorized() - if status in ['with_assessor','with_assessor_requirements','with_approver']: - if self.processing_status == 'with_referral' or self.can_user_edit: - raise ValidationError('You cannot change the current status at this time') - if self.processing_status != status: - if self.processing_status =='with_approver': - if approver_comment: - self.approver_comment = approver_comment - self.save() - send_proposal_approver_sendback_email_notification(request, self) - self.processing_status = status - self.save() - - # Create a log entry for the proposal - if self.processing_status == self.PROCESSING_STATUS_WITH_ASSESSOR: - self.log_user_action(ProposalUserAction.ACTION_BACK_TO_PROCESSING.format(self.id),request) - elif self.processing_status == self.PROCESSING_STATUS_WITH_ASSESSOR_REQUIREMENTS: - self.log_user_action(ProposalUserAction.ACTION_ENTER_REQUIREMENTS.format(self.id),request) - else: - raise ValidationError('The provided status cannot be found.') - - - def reissue_approval(self,request,status): - if not self.processing_status=='approved' : - raise ValidationError('You cannot change the current status at this time') - elif self.approval and self.approval.can_reissue: - if self.__approver_group() in request.user.proposalapprovergroup_set.all(): - self.processing_status = status - self.save() - # Create a log entry for the proposal - self.log_user_action(ProposalUserAction.ACTION_REISSUE_APPROVAL.format(self.id),request) - else: - raise ValidationError('Cannot reissue Approval. User not permitted.') - else: - raise ValidationError('Cannot reissue Approval') - - - def proposed_decline(self,request,details): - with transaction.atomic(): - try: - if not self.can_assess(request.user): - raise exceptions.ProposalNotAuthorized() - if self.processing_status != 'with_assessor': - raise ValidationError('You cannot propose to decline if it is not with assessor') - - reason = details.get('reason') - ProposalDeclinedDetails.objects.update_or_create( - proposal = self, - defaults={'officer': request.user, 'reason': reason, 'cc_email': details.get('cc_email',None)} - ) - self.proposed_decline_status = True - approver_comment = '' - self.move_to_status(request,'with_approver', approver_comment) - # Log proposal action - self.log_user_action(ProposalUserAction.ACTION_PROPOSED_DECLINE.format(self.id),request) - # Log entry for organisation - applicant_field=getattr(self, self.applicant_field) - applicant_field.log_user_action(ProposalUserAction.ACTION_PROPOSED_DECLINE.format(self.id),request) - - send_approver_decline_email_notification(reason, request, self) - except: - raise - - def final_decline(self,request,details): - with transaction.atomic(): - try: - if not self.can_assess(request.user): - raise exceptions.ProposalNotAuthorized() - if self.processing_status != 'with_approver': - raise ValidationError('You cannot decline if it is not with approver') - - proposal_decline, success = ProposalDeclinedDetails.objects.update_or_create( - proposal = self, - defaults={'officer':request.user,'reason':details.get('reason'),'cc_email':details.get('cc_email',None)} - ) - self.proposed_decline_status = True - self.processing_status = 'declined' - self.customer_status = 'declined' - self.save() - # Log proposal action - self.log_user_action(ProposalUserAction.ACTION_DECLINE.format(self.id),request) - # Log entry for organisation - applicant_field=getattr(self, self.applicant_field) - applicant_field.log_user_action(ProposalUserAction.ACTION_DECLINE.format(self.id),request) - send_proposal_decline_email_notification(self,request, proposal_decline) - except: - raise - - def on_hold(self,request): - with transaction.atomic(): - try: - if not self.can_assess(request.user): - raise exceptions.ProposalNotAuthorized() - if not (self.processing_status == 'with_assessor' or self.processing_status == 'with_referral'): - raise ValidationError('You cannot put on hold if it is not with assessor or with referral') - - self.prev_processing_status = self.processing_status - self.processing_status = self.PROCESSING_STATUS_ONHOLD - self.save() - # Log proposal action - self.log_user_action(ProposalUserAction.ACTION_PUT_ONHOLD.format(self.id),request) - # Log entry for organisation - applicant_field=getattr(self, self.applicant_field) - applicant_field.log_user_action(ProposalUserAction.ACTION_PUT_ONHOLD.format(self.id),request) - - #send_approver_decline_email_notification(reason, request, self) - except: - raise - - def on_hold_remove(self,request): - with transaction.atomic(): - try: - if not self.can_assess(request.user): - raise exceptions.ProposalNotAuthorized() - if self.processing_status != 'on_hold': - raise ValidationError('You cannot remove on hold if it is not currently on hold') - - self.processing_status = self.prev_processing_status - self.prev_processing_status = self.PROCESSING_STATUS_ONHOLD - self.save() - # Log proposal action - self.log_user_action(ProposalUserAction.ACTION_REMOVE_ONHOLD.format(self.id),request) - # Log entry for organisation - applicant_field=getattr(self, self.applicant_field) - applicant_field.log_user_action(ProposalUserAction.ACTION_REMOVE_ONHOLD.format(self.id),request) - - #send_approver_decline_email_notification(reason, request, self) - except: - raise - - def with_qaofficer(self,request): - with transaction.atomic(): - try: - if not self.can_assess(request.user): - raise exceptions.ProposalNotAuthorized() - if not (self.processing_status == 'with_assessor' or self.processing_status == 'with_referral'): - raise ValidationError('You cannot send to QA Officer if it is not with assessor or with referral') - - self.prev_processing_status = self.processing_status - self.processing_status = self.PROCESSING_STATUS_WITH_QA_OFFICER - self.qaofficer_referral = True - if self.qaofficer_referrals.exists(): - qaofficer_referral = self.qaofficer_referrals.first() - qaofficer_referral.sent_by = request.user - qaofficer_referral.processing_status = 'with_qaofficer' - else: - qaofficer_referral = self.qaofficer_referrals.create(sent_by=request.user) - - qaofficer_referral.save() - self.save() - - # Log proposal action - self.log_user_action(ProposalUserAction.ACTION_WITH_QA_OFFICER.format(self.id),request) - # Log entry for organisation - applicant_field=getattr(self, self.applicant_field) - applicant_field.log_user_action(ProposalUserAction.ACTION_WITH_QA_OFFICER.format(self.id),request) - - #send_approver_decline_email_notification(reason, request, self) - recipients = self.qa_officers() - send_qaofficer_email_notification(self, recipients, request) - - except: - raise - - def with_qaofficer_completed(self,request): - with transaction.atomic(): - try: - if not self.can_assess(request.user): - raise exceptions.ProposalNotAuthorized() - if self.processing_status != 'with_qa_officer': - raise ValidationError('You cannot Complete QA Officer Assessment if processing status not currently With Assessor') - - self.processing_status = self.prev_processing_status - self.prev_processing_status = self.PROCESSING_STATUS_WITH_QA_OFFICER - - qaofficer_referral = self.qaofficer_referrals.first() - qaofficer_referral.qaofficer = request.user - qaofficer_referral.qaofficer_group = QAOfficerGroup.objects.get(default=True) - qaofficer_referral.qaofficer_text = request.data['text'] - qaofficer_referral.processing_status = 'completed' - - qaofficer_referral.save() - self.assigned_officer = None - self.save() - - # Log proposal action - self.log_user_action(ProposalUserAction.ACTION_QA_OFFICER_COMPLETED.format(self.id),request) - # Log entry for organisation - applicant_field=getattr(self, self.applicant_field) - applicant_field.log_user_action(ProposalUserAction.ACTION_QA_OFFICER_COMPLETED.format(self.id),request) - - #send_approver_decline_email_notification(reason, request, self) - recipients = self.qa_officers() - send_qaofficer_complete_email_notification(self, recipients, request) - except: - raise - - - def proposed_approval(self,request,details): - with transaction.atomic(): - try: - if not self.can_assess(request.user): - raise exceptions.ProposalNotAuthorized() - if self.processing_status != 'with_assessor_requirements': - raise ValidationError('You cannot propose for approval if it is not with assessor for requirements') - self.proposed_issuance_approval = { - 'start_date' : details.get('start_date').strftime('%d/%m/%Y'), - 'expiry_date' : details.get('expiry_date').strftime('%d/%m/%Y'), - 'details': details.get('details'), - 'cc_email':details.get('cc_email') - } - self.proposed_decline_status = False - approver_comment = '' - self.move_to_status(request,'with_approver', approver_comment) - self.assigned_officer = None - self.save() - # Log proposal action - self.log_user_action(ProposalUserAction.ACTION_PROPOSED_APPROVAL.format(self.id),request) - # Log entry for organisation - applicant_field=getattr(self, self.applicant_field) - applicant_field.log_user_action(ProposalUserAction.ACTION_PROPOSED_APPROVAL.format(self.id),request) - - send_approver_approve_email_notification(request, self) - except: - raise - - def eclass_approval(self,request,details): - from commercialoperator.components.approvals.models import Approval - with transaction.atomic(): - try: - if not self.can_assess(request.user): - raise exceptions.ProposalNotAuthorized() - if self.processing_status != 'with_approver': - raise ValidationError('You cannot issue the approval if it is not with an approver') - if not self.applicant.organisation.postal_address: - raise ValidationError('The applicant needs to have set their postal address before approving this proposal.') - - self.proposed_issuance_approval = { - 'start_date' : details.get('start_date').strftime('%d/%m/%Y'), - 'expiry_date' : details.get('expiry_date').strftime('%d/%m/%Y'), - 'details': details.get('details'), - 'cc_email':details.get('cc_email') - } - self.proposed_decline_status = False - self.processing_status = 'approved' - self.customer_status = 'approved' - # Log proposal action - self.log_user_action(ProposalUserAction.ACTION_ISSUE_APPROVAL_.format(self.id),request) - # Log entry for organisation - applicant_field=getattr(self, self.applicant_field) - applicant_field.log_user_action(ProposalUserAction.ACTION_ISSUE_APPROVAL_.format(self.id),request) - - if self.proposal_type == 'renewal': - pass - else: - approval,created = Approval.objects.update_or_create( - current_proposal = self, - defaults = { - #'title' : self.title, - #'issue_date' : timezone.now(), - 'issue_date' : details.get('issue_date'), - 'expiry_date' : details.get('expiry_date'), - 'start_date' : details.get('start_date'), - 'applicant' : self.applicant - } - ) - self.approval = approval - - #send Proposal approval email with attachment - #send_proposal_approval_email_notification(self,request) - self.save(version_comment='Final Approval: {}'.format(self.approval.lodgement_number)) - self.approval.documents.all().update(can_delete=False) - - except: - raise - - def preview_approval(self,request,details): - from commercialoperator.components.approvals.models import PreviewTempApproval - with transaction.atomic(): - try: - if self.processing_status != 'with_approver': - raise ValidationError('Licence preview only available when processing status is with_approver. Current status {}'.format(self.processing_status)) - if not self.can_assess(request.user): - raise exceptions.ProposalNotAuthorized() - #if not self.applicant.organisation.postal_address: - if not self.applicant_address: - raise ValidationError('The applicant needs to have set their postal address before approving this proposal.') - - preview_approval = PreviewTempApproval.objects.create( - current_proposal = self, - issue_date = timezone.now(), - expiry_date = datetime.datetime.strptime(details.get('due_date'), '%d/%m/%Y').date(), - start_date = datetime.datetime.strptime(details.get('start_date'), '%d/%m/%Y').date(), - submitter = self.submitter, - #org_applicant = self.applicant if isinstance(self.applicant, Organisation) else None, - #proxy_applicant = self.applicant if isinstance(self.applicant, EmailUser) else None, - org_applicant = self.org_applicant, - proxy_applicant = self.proxy_applicant, - ) - - # Generate the preview document - get the value of the BytesIO buffer - licence_buffer = preview_approval.generate_doc(request.user, preview=True) - - # clean temp preview licence object - transaction.set_rollback(True) - - return licence_buffer - except: - raise - - - def final_approval(self,request,details): - from commercialoperator.components.approvals.models import Approval - with transaction.atomic(): - try: - if not self.can_assess(request.user): - raise exceptions.ProposalNotAuthorized() - if self.processing_status != 'with_approver': - raise ValidationError('You cannot issue the approval if it is not with an approver') - #if not self.applicant.organisation.postal_address: - if not self.applicant_address: - raise ValidationError('The applicant needs to have set their postal address before approving this proposal.') - - self.proposed_issuance_approval = { - 'start_date' : details.get('start_date').strftime('%d/%m/%Y'), - 'expiry_date' : details.get('expiry_date').strftime('%d/%m/%Y'), - 'details': details.get('details'), - 'cc_email':details.get('cc_email') - } - self.proposed_decline_status = False - self.processing_status = 'approved' - self.customer_status = 'approved' - # Log proposal action - self.log_user_action(ProposalUserAction.ACTION_ISSUE_APPROVAL_.format(self.id),request) - # Log entry for organisation - applicant_field=getattr(self, self.applicant_field) - applicant_field.log_user_action(ProposalUserAction.ACTION_ISSUE_APPROVAL_.format(self.id),request) - - if self.processing_status == 'approved': - # TODO if it is an ammendment proposal then check appropriately - checking_proposal = self - if self.proposal_type == 'renewal': - if self.previous_application: - previous_approval = self.previous_application.approval - approval,created = Approval.objects.update_or_create( - current_proposal = checking_proposal, - defaults = { - 'issue_date' : timezone.now(), - 'expiry_date' : details.get('expiry_date'), - 'start_date' : details.get('start_date'), - 'submitter': self.submitter, - #'org_applicant' : self.applicant if isinstance(self.applicant, Organisation) else None, - #'proxy_applicant' : self.applicant if isinstance(self.applicant, EmailUser) else None, - 'org_applicant' : self.org_applicant, - 'proxy_applicant' : self.proxy_applicant, - 'lodgement_number': previous_approval.lodgement_number - } - ) - if created: - previous_approval.replaced_by = approval - previous_approval.save() - - elif self.proposal_type == 'amendment': - if self.previous_application: - previous_approval = self.previous_application.approval - approval,created = Approval.objects.update_or_create( - current_proposal = checking_proposal, - defaults = { - 'issue_date' : timezone.now(), - 'expiry_date' : details.get('expiry_date'), - 'start_date' : details.get('start_date'), - 'submitter': self.submitter, - #'org_applicant' : self.applicant if isinstance(self.applicant, Organisation) else None, - #'proxy_applicant' : self.applicant if isinstance(self.applicant, EmailUser) else None, - 'org_applicant' : self.org_applicant, - 'proxy_applicant' : self.proxy_applicant, - 'lodgement_number': previous_approval.lodgement_number - } - ) - if created: - previous_approval.replaced_by = approval - previous_approval.save() - else: - approval,created = Approval.objects.update_or_create( - current_proposal = checking_proposal, - defaults = { - 'issue_date' : timezone.now(), - 'expiry_date' : details.get('expiry_date'), - 'start_date' : details.get('start_date'), - 'submitter': self.submitter, - #'org_applicant' : self.applicant if isinstance(self.applicant, Organisation) else None, - #'proxy_applicant' : self.applicant if isinstance(self.applicant, EmailUser) else None, - 'org_applicant' : self.org_applicant, - 'proxy_applicant' : self.proxy_applicant, - #'extracted_fields' = JSONField(blank=True, null=True) - } - ) - # Generate compliances - from commercialoperator.components.compliances.models import Compliance, ComplianceUserAction - if created: - if self.proposal_type == 'amendment': - approval_compliances = Compliance.objects.filter(approval= previous_approval, proposal = self.previous_application, processing_status='future') - if approval_compliances: - for c in approval_compliances: - c.delete() - # Log creation - # Generate the document - approval.generate_doc(request.user) - self.generate_compliances(approval, request) - # send the doc and log in approval and org - else: - #approval.replaced_by = request.user - #approval.replaced_by = self.approval - # Generate the document - approval.generate_doc(request.user) - #Delete the future compliances if Approval is reissued and generate the compliances again. - approval_compliances = Compliance.objects.filter(approval= approval, proposal = self, processing_status='future') - if approval_compliances: - for c in approval_compliances: - c.delete() - self.generate_compliances(approval, request) - # Log proposal action - self.log_user_action(ProposalUserAction.ACTION_UPDATE_APPROVAL_.format(self.id),request) - # Log entry for organisation - applicant_field=getattr(self, self.applicant_field) - applicant_field.log_user_action(ProposalUserAction.ACTION_UPDATE_APPROVAL_.format(self.id),request) - self.approval = approval - #send Proposal approval email with attachment - send_proposal_approval_email_notification(self,request) - self.save(version_comment='Final Approval: {}'.format(self.approval.lodgement_number)) - self.approval.documents.all().update(can_delete=False) - - except: - raise - - def generate_compliances(self,approval, request): - today = timezone.now().date() - timedelta = datetime.timedelta - from commercialoperator.components.compliances.models import Compliance, ComplianceUserAction - #For amendment type of Proposal, check for copied requirements from previous proposal - if self.proposal_type == 'amendment': - try: - for r in self.requirements.filter(copied_from__isnull=False): - cs=[] - cs=Compliance.objects.filter(requirement=r.copied_from, proposal=self.previous_application, processing_status='due') - if cs: - if r.is_deleted == True: - for c in cs: - c.processing_status='discarded' - c.customer_status = 'discarded' - c.reminder_sent=True - c.post_reminder_sent=True - c.save() - if r.is_deleted == False: - for c in cs: - c.proposal= self - c.approval=approval - c.requirement=r - c.save() - except: - raise - #requirement_set= self.requirements.filter(copied_from__isnull=True).exclude(is_deleted=True) - requirement_set= self.requirements.all().exclude(is_deleted=True) - - #for req in self.requirements.all(): - for req in requirement_set: - try: - if req.due_date and req.due_date >= today: - current_date = req.due_date - #create a first Compliance - try: - compliance= Compliance.objects.get(requirement = req, due_date = current_date) - except Compliance.DoesNotExist: - compliance =Compliance.objects.create( - proposal=self, - due_date=current_date, - processing_status='future', - approval=approval, - requirement=req, - ) - compliance.log_user_action(ComplianceUserAction.ACTION_CREATE.format(compliance.id),request) - if req.recurrence: - while current_date < approval.expiry_date: - for x in range(req.recurrence_schedule): - #Weekly - if req.recurrence_pattern == 1: - current_date += timedelta(weeks=1) - #Monthly - elif req.recurrence_pattern == 2: - current_date += timedelta(weeks=4) - pass - #Yearly - elif req.recurrence_pattern == 3: - current_date += timedelta(days=365) - # Create the compliance - if current_date <= approval.expiry_date: - try: - compliance= Compliance.objects.get(requirement = req, due_date = current_date) - except Compliance.DoesNotExist: - compliance =Compliance.objects.create( - proposal=self, - due_date=current_date, - processing_status='future', - approval=approval, - requirement=req, - ) - compliance.log_user_action(ComplianceUserAction.ACTION_CREATE.format(compliance.id),request) - except: - raise - - - - def renew_approval(self,request): - with transaction.atomic(): - previous_proposal = self - try: - proposal=Proposal.objects.get(previous_application = previous_proposal) - if proposal.customer_status=='with_assessor': - raise ValidationError('A renewal for this licence has already been lodged and is awaiting review.') - except Proposal.DoesNotExist: - previous_proposal = Proposal.objects.get(id=self.id) - proposal = clone_proposal_with_status_reset(previous_proposal) - proposal.proposal_type = 'renewal' - #proposal.schema = ProposalType.objects.first().schema - ptype = ProposalType.objects.filter(name=proposal.application_type).latest('version') - proposal.schema = ptype.schema - proposal.submitter = request.user - proposal.previous_application = self - proposal.proposed_issuance_approval= None - try: - ProposalOtherDetails.objects.get(proposal=proposal) - except ProposalOtherDetails.DoesNotExist: - ProposalOtherDetails.objects.create(proposal=proposal) - # Create a log entry for the proposal - proposal.other_details.nominated_start_date=self.approval.expiry_date+ datetime.timedelta(days=1) - proposal.other_details.save() - self.log_user_action(ProposalUserAction.ACTION_RENEW_PROPOSAL.format(self.id),request) - # Create a log entry for the organisation - applicant_field=getattr(self, self.applicant_field) - applicant_field.log_user_action(ProposalUserAction.ACTION_RENEW_PROPOSAL.format(self.id),request) - #Log entry for approval - from commercialoperator.components.approvals.models import ApprovalUserAction - self.approval.log_user_action(ApprovalUserAction.ACTION_RENEW_APPROVAL.format(self.approval.id),request) - proposal.save(version_comment='New Amendment/Renewal Application created, from origin {}'.format(proposal.previous_application_id)) - #proposal.save() - return proposal - - def amend_approval(self,request): - with transaction.atomic(): - previous_proposal = self - try: - amend_conditions = { - 'previous_application': previous_proposal, - 'proposal_type': 'amendment' - - } - proposal=Proposal.objects.get(**amend_conditions) - if proposal.customer_status=='under_review': - raise ValidationError('An amendment for this licence has already been lodged and is awaiting review.') - except Proposal.DoesNotExist: - previous_proposal = Proposal.objects.get(id=self.id) - proposal = clone_proposal_with_status_reset(previous_proposal) - proposal.proposal_type = 'amendment' - #proposal.schema = ProposalType.objects.first().schema - ptype = ProposalType.objects.filter(name=proposal.application_type).latest('version') - proposal.schema = ptype.schema - proposal.submitter = request.user - proposal.previous_application = self - try: - ProposalOtherDetails.objects.get(proposal=proposal) - except ProposalOtherDetails.DoesNotExist: - ProposalOtherDetails.objects.create(proposal=proposal) - #copy all the requirements from the previous proposal - #req=self.requirements.all() - req=self.requirements.all().exclude(is_deleted=True) - from copy import deepcopy - if req: - for r in req: - old_r = deepcopy(r) - r.proposal = proposal - r.copied_from=old_r - r.id = None - r.save() - #copy all the requirement documents from previous proposal - for requirement in proposal.requirements.all(): - for requirement_document in RequirementDocument.objects.filter(requirement=requirement.copied_from): - requirement_document.requirement = requirement - requirement_document.id = None - requirement_document._file.name = u'{}/proposals/{}/requirement_documents/{}'.format(settings.MEDIA_APP_DIR, proposal.id, requirement_document.name) - requirement_document.can_delete = True - requirement_document.save() - # Create a log entry for the proposal - self.log_user_action(ProposalUserAction.ACTION_AMEND_PROPOSAL.format(self.id),request) - # Create a log entry for the organisation - applicant_field=getattr(self, self.applicant_field) - applicant_field.log_user_action(ProposalUserAction.ACTION_AMEND_PROPOSAL.format(self.id),request) - #Log entry for approval - from commercialoperator.components.approvals.models import ApprovalUserAction - self.approval.log_user_action(ApprovalUserAction.ACTION_AMEND_APPROVAL.format(self.approval.id),request) - proposal.save(version_comment='New Amendment/Renewal Application created, from origin {}'.format(proposal.previous_application_id)) - #proposal.save() - return proposal - -class ProposalLogDocument(Document): - log_entry = models.ForeignKey('ProposalLogEntry',related_name='documents') - _file = models.FileField(upload_to=update_proposal_comms_log_filename) - - class Meta: - app_label = 'commercialoperator' - -class ProposalLogEntry(CommunicationsLogEntry): - proposal = models.ForeignKey(Proposal, related_name='comms_logs') - - def __str__(self): - return '{} - {}'.format(self.reference, self.subject) - - class Meta: - app_label = 'commercialoperator' - - def save(self, **kwargs): - # save the application reference if the reference not provided - if not self.reference: - self.reference = self.proposal.reference - super(ProposalLogEntry, self).save(**kwargs) - -class ProposalOtherDetails(models.Model): - #activities_land = models.CharField(max_length=24, blank=True, default='') - # ACCREDITATION_TYPE_CHOICES = ( - # ('no', 'No'), - # ('atap', 'ATAP'), - # ('eco_certification', 'Eco Certification'), - # ('narta', 'NARTA'), - # ) - # LICENSE_PERIOD_CHOICES=( - # ('2_months','2 months'), - # ('1_year','1 Year'), - # ('3_year', '3 Years'), - # ('5_year', '5 Years'), - # ('7_year', '7 Years'), - # ('10_year', '10 Years'), - # ) - LICENCE_PERIOD_CHOICES=( - ('2_months','2 months'), - ('1_year','1 Year'), - ('3_year', '3 Years'), - ('5_year', '5 Years'), - ('7_year', '7 Years'), - ('10_year', '10 Years'), - ) - #accreditation_type = models.CharField('Accreditation', max_length=40, choices=ACCREDITATION_TYPE_CHOICES, - # default=ACCREDITATION_TYPE_CHOICES[0][0]) - #accreditation_expiry= models.DateTimeField(blank=True, null=True) - #accreditation_expiry= models.DateField(blank=True, null=True) - - #preferred_license_period=models.CharField('Preferred license period', max_length=40, choices=LICENSE_PERIOD_CHOICES,default=LICENSE_PERIOD_CHOICES[0][0]) - preferred_licence_period=models.CharField('Preferred licence period', max_length=40, choices=LICENCE_PERIOD_CHOICES, null=True, blank=True) - #nominated_start_date= models.DateTimeField(blank=True, null=True) - #insurance_expiry= models.DateTimeField(blank=True, null=True) - nominated_start_date= models.DateField(blank=True, null=True) - insurance_expiry= models.DateField(blank=True, null=True) - other_comments=models.TextField(blank=True) - mooring = JSONField(default=['']) - #if credit facilities for payment of fees is required - credit_fees=models.BooleanField(default=False) - #if credit/ cash payment docket books are required - credit_docket_books=models.BooleanField(default=False) - docket_books_number=models.CharField('Docket books number', max_length=20, blank=True ) - proposal = models.OneToOneField(Proposal, related_name='other_details', null=True) - - class Meta: - app_label = 'commercialoperator' - - @property - def proposed_end_date(self): - end_date=None - if self.preferred_licence_period and self.nominated_start_date: - if self.preferred_licence_period=='2_months': - end_date=self.nominated_start_date + relativedelta(months=+2) - relativedelta(days=1) - if self.preferred_licence_period=='1_year': - end_date=self.nominated_start_date + relativedelta(months=+12)- relativedelta(days=1) - if self.preferred_licence_period=='3_year': - end_date=self.nominated_start_date + relativedelta(months=+36)- relativedelta(days=1) - if self.preferred_licence_period=='5_year': - end_date=self.nominated_start_date + relativedelta(months=+60)- relativedelta(days=1) - if self.preferred_licence_period=='7_year': - end_date=self.nominated_start_date + relativedelta(months=+84)- relativedelta(days=1) - if self.preferred_licence_period=='10_year': - end_date=self.nominated_start_date + relativedelta(months=+120)- relativedelta(days=1) - return end_date - - - - -class ProposalAccreditation(models.Model): - #activities_land = models.CharField(max_length=24, blank=True, default='') - ACCREDITATION_TYPE_CHOICES = ( - ('no', 'No'), - ('atap', 'ATAP'), - ('eco_certification', 'Eco Certification'), - ('narta', 'NARTA'), - ('other', 'Other') - ) - - accreditation_type = models.CharField('Accreditation', max_length=40, choices=ACCREDITATION_TYPE_CHOICES, - default=ACCREDITATION_TYPE_CHOICES[0][0]) - accreditation_expiry= models.DateField(blank=True, null=True) - comments=models.TextField(blank=True) - proposal_other_details = models.ForeignKey(ProposalOtherDetails, related_name='accreditations', null=True) - - def __str__(self): - return '{} - {}'.format(self.accreditation_type, self.comments) - - class Meta: - app_label = 'commercialoperator' - - -class ProposalPark(models.Model): - park = models.ForeignKey(Park, blank=True, null=True, related_name='proposals') - proposal = models.ForeignKey(Proposal, blank=True, null=True, related_name='parks') - - def __str__(self): - return self.park.name - - class Meta: - app_label = 'commercialoperator' - unique_together = ('park', 'proposal') - - @property - def land_activities(self): - qs=self.activities.all() - categories=ActivityCategory.objects.filter(activity_type='land') - activities=qs.filter(Q(activity__activity_category__in = categories)& Q(activity__visible=True)) - return activities - - @property - def marine_activities(self): - qs=self.activities.all() - categories=ActivityCategory.objects.filter(activity_type='marine') - activities=qs.filter(Q(activity__activity_category__in = categories)& Q(activity__visible=True)) - return activities - -#To store Park activities related to Proposal T class land parks -class ProposalParkActivity(models.Model): - proposal_park = models.ForeignKey(ProposalPark, blank=True, null=True, related_name='activities') - activity = models.ForeignKey(Activity, blank=True, null=True) - - def __str__(self): - return self.activity.name - - class Meta: - app_label = 'commercialoperator' - unique_together = ('proposal_park', 'activity') - - @property - def activity_name(self): - return self.activity.name - - -#To store Park access_types related to Proposal T class land parks -class ProposalParkAccess(models.Model): - proposal_park = models.ForeignKey(ProposalPark, blank=True, null=True, related_name='access_types') - access_type = models.ForeignKey(AccessType, blank=True, null=True) - - def __str__(self): - return self.access_type.name - - class Meta: - app_label = 'commercialoperator' - unique_together = ('proposal_park', 'access_type') - -#To store Park zones related to Proposal T class marine parks -class ProposalParkZone(models.Model): - proposal_park = models.ForeignKey(ProposalPark, blank=True, null=True, related_name='zones') - zone = models.ForeignKey(Zone, blank=True, null=True, related_name='proposal_zones') - access_point = models.CharField(max_length=200, blank=True) - - def __str__(self): - return self.zone.name - - class Meta: - app_label = 'commercialoperator' - unique_together = ('zone', 'proposal_park') - -class ProposalParkZoneActivity(models.Model): - park_zone = models.ForeignKey(ProposalParkZone, blank=True, null=True, related_name='park_activities') - activity = models.ForeignKey(Activity, blank=True, null=True) - #section=models.ForeignKey(Section, blank=True, null= True) - - def __str__(self): - return '{} - {}'.format(self.activity.name, self.park_zone.zone.name) - - class Meta: - app_label = 'commercialoperator' - unique_together = ('park_zone', 'activity') - - @property - def activity_name(self): - return self.activity.name - - -class ProposalTrail(models.Model): - trail = models.ForeignKey(Trail, blank=True, null=True, related_name='proposals') - proposal = models.ForeignKey(Proposal, blank=True, null=True, related_name='trails') - - def __str__(self): - return self.trail.name - - class Meta: - app_label = 'commercialoperator' - unique_together = ('trail', 'proposal') - - -class ProposalTrailSection(models.Model): - proposal_trail = models.ForeignKey(ProposalTrail, blank=True, null=True, related_name='sections') - section = models.ForeignKey(Section, blank=True, null=True, related_name='proposal_trails') - - def __str__(self): - return '{} - {}'.format(self.proposal_trail, self.section.name) - - class Meta: - app_label = 'commercialoperator' - unique_together = ('section', 'proposal_trail') - - -class ProposalTrailSectionActivity(models.Model): - trail_section = models.ForeignKey(ProposalTrailSection, blank=True, null=True, related_name='trail_activities') - activity = models.ForeignKey(Activity, blank=True, null=True) - #section=models.ForeignKey(Section, blank=True, null= True) - - def __str__(self): - return '{} - {}'.format(self.trail_section, self.activity.name) - - class Meta: - app_label = 'commercialoperator' - unique_together = ('trail_section', 'activity') - - @property - def activity_name(self): - return self.activity.name - -@python_2_unicode_compatible -class Vehicle(models.Model): - capacity = models.CharField(max_length=200, blank=True) - rego = models.CharField(max_length=200, blank=True) - license = models.CharField(max_length=200, blank=True) - access_type= models.ForeignKey(AccessType,null=True, related_name='vehicles') - rego_expiry= models.DateField(blank=True, null=True) - proposal = models.ForeignKey(Proposal, related_name='vehicles') - - def __str__(self): - return '{} - {}'.format(self.rego, self.access_type) - - class Meta: - app_label = 'commercialoperator' - - def __str__(self): - return self.rego - - -@python_2_unicode_compatible -class Vessel(models.Model): - nominated_vessel = models.CharField(max_length=200, blank=True) - spv_no = models.CharField(max_length=200, blank=True) - hire_rego = models.CharField(max_length=200, blank=True) - craft_no = models.CharField(max_length=200, blank=True) - size = models.CharField(max_length=200, blank=True) - #rego_expiry= models.DateField(blank=True, null=True) - proposal = models.ForeignKey(Proposal, related_name='vessels') - - def __str__(self): - return '{} - {}'.format(self.spv_no, self.nominated_vessel) - - class Meta: - app_label = 'commercialoperator' - - def __str__(self): - return self.nominated_vessel - -class ProposalRequest(models.Model): - proposal = models.ForeignKey(Proposal, related_name='proposalrequest_set') - subject = models.CharField(max_length=200, blank=True) - text = models.TextField(blank=True) - officer = models.ForeignKey(EmailUser, null=True) - - def __str__(self): - return '{} - {}'.format(self.subject, self.text) - - class Meta: - app_label = 'commercialoperator' - -class ComplianceRequest(ProposalRequest): - REASON_CHOICES = (('outstanding', 'There are currently outstanding returns for the previous licence'), - ('other', 'Other')) - reason = models.CharField('Reason', max_length=30, choices=REASON_CHOICES, default=REASON_CHOICES[0][0]) - - class Meta: - app_label = 'commercialoperator' - - -class AmendmentReason(models.Model): - reason = models.CharField('Reason', max_length=125) - - class Meta: - app_label = 'commercialoperator' - verbose_name = "Application Amendment Reason" # display name in Admin - verbose_name_plural = "Application Amendment Reasons" - - def __str__(self): - return self.reason - - -class AmendmentRequest(ProposalRequest): - STATUS_CHOICES = (('requested', 'Requested'), ('amended', 'Amended')) - #REASON_CHOICES = (('insufficient_detail', 'The information provided was insufficient'), - # ('missing_information', 'There was missing information'), - # ('other', 'Other')) - # try: - # # model requires some choices if AmendmentReason does not yet exist or is empty - # REASON_CHOICES = list(AmendmentReason.objects.values_list('id', 'reason')) - # if not REASON_CHOICES: - # REASON_CHOICES = ((0, 'The information provided was insufficient'), - # (1, 'There was missing information'), - # (2, 'Other')) - # except: - # REASON_CHOICES = ((0, 'The information provided was insufficient'), - # (1, 'There was missing information'), - # (2, 'Other')) - - - status = models.CharField('Status', max_length=30, choices=STATUS_CHOICES, default=STATUS_CHOICES[0][0]) - #reason = models.CharField('Reason', max_length=30, choices=REASON_CHOICES, default=REASON_CHOICES[0][0]) - reason = models.ForeignKey(AmendmentReason, blank=True, null=True) - #reason = models.ForeignKey(AmendmentReason) - - class Meta: - app_label = 'commercialoperator' - - - def generate_amendment(self,request): - with transaction.atomic(): - try: - if not self.proposal.can_assess(request.user): - raise exceptions.ProposalNotAuthorized() - if self.status == 'requested': - proposal = self.proposal - if proposal.processing_status != 'draft': - proposal.processing_status = 'draft' - proposal.customer_status = 'draft' - proposal.save() - - # Create a log entry for the proposal - proposal.log_user_action(ProposalUserAction.ACTION_ID_REQUEST_AMENDMENTS,request) - # Create a log entry for the organisation - applicant_field=getattr(proposal, proposal.applicant_field) - applicant_field.log_user_action(ProposalUserAction.ACTION_ID_REQUEST_AMENDMENTS,request) - - # send email - - send_amendment_email_notification(self,request, proposal) - - self.save() - except: - raise - -class Assessment(ProposalRequest): - STATUS_CHOICES = (('awaiting_assessment', 'Awaiting Assessment'), ('assessed', 'Assessed'), - ('assessment_expired', 'Assessment Period Expired')) - assigned_assessor = models.ForeignKey(EmailUser, blank=True, null=True) - status = models.CharField('Status', max_length=20, choices=STATUS_CHOICES, default=STATUS_CHOICES[0][0]) - date_last_reminded = models.DateField(null=True, blank=True) - #requirements = models.ManyToManyField('Requirement', through='AssessmentRequirement') - comment = models.TextField(blank=True) - purpose = models.TextField(blank=True) - - class Meta: - app_label = 'commercialoperator' - -class ProposalDeclinedDetails(models.Model): - #proposal = models.OneToOneField(Proposal, related_name='declined_details') - proposal = models.OneToOneField(Proposal) - officer = models.ForeignKey(EmailUser, null=False) - reason = models.TextField(blank=True) - cc_email = models.TextField(null=True) - - class Meta: - app_label = 'commercialoperator' - -class ProposalOnHold(models.Model): - #proposal = models.OneToOneField(Proposal, related_name='onhold') - proposal = models.OneToOneField(Proposal) - officer = models.ForeignKey(EmailUser, null=False) - comment = models.TextField(blank=True) - documents = models.ForeignKey(ProposalDocument, blank=True, null=True, related_name='onhold_documents') - - class Meta: - app_label = 'commercialoperator' - - -@python_2_unicode_compatible -#class ProposalStandardRequirement(models.Model): -class ProposalStandardRequirement(RevisionedMixin): - text = models.TextField() - code = models.CharField(max_length=10, unique=True) - obsolete = models.BooleanField(default=False) - - def __str__(self): - return self.code - - class Meta: - app_label = 'commercialoperator' - verbose_name = "Application Standard Requirement" - verbose_name_plural = "Application Standard Requirements" - - -class ProposalUserAction(UserAction): - ACTION_CREATE_CUSTOMER_ = "Create customer {}" - ACTION_CREATE_PROFILE_ = "Create profile {}" - ACTION_LODGE_APPLICATION = "Lodge application {}" - ACTION_ASSIGN_TO_ASSESSOR = "Assign application {} to {} as the assessor" - ACTION_UNASSIGN_ASSESSOR = "Unassign assessor from application {}" - ACTION_ASSIGN_TO_APPROVER = "Assign application {} to {} as the approver" - ACTION_UNASSIGN_APPROVER = "Unassign approver from application {}" - ACTION_ACCEPT_ID = "Accept ID" - ACTION_RESET_ID = "Reset ID" - ACTION_ID_REQUEST_UPDATE = 'Request ID update' - ACTION_ACCEPT_CHARACTER = 'Accept character' - ACTION_RESET_CHARACTER = "Reset character" - ACTION_ACCEPT_REVIEW = 'Accept review' - ACTION_RESET_REVIEW = "Reset review" - ACTION_ID_REQUEST_AMENDMENTS = "Request amendments" - ACTION_SEND_FOR_ASSESSMENT_TO_ = "Send for assessment to {}" - ACTION_SEND_ASSESSMENT_REMINDER_TO_ = "Send assessment reminder to {}" - ACTION_DECLINE = "Decline application {}" - ACTION_ENTER_CONDITIONS = "Enter requirement" - ACTION_CREATE_CONDITION_ = "Create requirement {}" - ACTION_ISSUE_APPROVAL_ = "Issue Licence for application {}" - ACTION_UPDATE_APPROVAL_ = "Update Licence for application {}" - ACTION_EXPIRED_APPROVAL_ = "Expire Approval for proposal {}" - ACTION_DISCARD_PROPOSAL = "Discard application {}" - ACTION_APPROVAL_LEVEL_DOCUMENT = "Assign Approval level document {}" - #T-Class licence - ACTION_LINK_PARK = "Link park {} to application {}" - ACTION_UNLINK_PARK = "Unlink park {} from application {}" - ACTION_LINK_ACCESS = "Link access {} to park {}" - ACTION_UNLINK_ACCESS = "Unlink access {} from park {}" - ACTION_LINK_ACTIVITY = "Link activity {} to park {}" - ACTION_UNLINK_ACTIVITY = "Unlink activity {} from park {}" - ACTION_LINK_ACTIVITY_SECTION = "Link activity {} to section {} of trail {}" - ACTION_UNLINK_ACTIVITY_SECTION = "Unlink activity {} from section {} of trail {}" - ACTION_LINK_ACTIVITY_ZONE = "Link activity {} to zone {} of park {}" - ACTION_UNLINK_ACTIVITY_ZONE = "Unlink activity {} from zone {} of park {}" - ACTION_LINK_TRAIL = "Link trail {} to application {}" - ACTION_UNLINK_TRAIL = "Unlink trail {} from application {}" - ACTION_LINK_SECTION = "Link section {} to trail {}" - ACTION_UNLINK_SECTION = "Unlink section {} from trail {}" - ACTION_LINK_ZONE = "Link zone {} to park {}" - ACTION_UNLINK_ZONE = "Unlink zone {} from park {}" - # Assessors - ACTION_SAVE_ASSESSMENT_ = "Save assessment {}" - ACTION_CONCLUDE_ASSESSMENT_ = "Conclude assessment {}" - ACTION_PROPOSED_APPROVAL = "Application {} has been proposed for approval" - ACTION_PROPOSED_DECLINE = "Application {} has been proposed for decline" - # Referrals - ACTION_SEND_REFERRAL_TO = "Send referral {} for application {} to {}" - ACTION_RESEND_REFERRAL_TO = "Resend referral {} for application {} to {}" - ACTION_REMIND_REFERRAL = "Send reminder for referral {} for application {} to {}" - ACTION_ENTER_REQUIREMENTS = "Enter Requirements for application {}" - ACTION_BACK_TO_PROCESSING = "Back to processing for application {}" - RECALL_REFERRAL = "Referral {} for application {} has been recalled" - CONCLUDE_REFERRAL = "{}: Referral {} for application {} has been concluded by group {}" - ACTION_REFERRAL_DOCUMENT = "Assign Referral document {}" - #Approval - ACTION_REISSUE_APPROVAL = "Reissue licence for application {}" - ACTION_CANCEL_APPROVAL = "Cancel licence for application {}" - ACTION_EXTEND_APPROVAL = "Extend licence" - ACTION_SUSPEND_APPROVAL = "Suspend licence for application {}" - ACTION_REINSTATE_APPROVAL = "Reinstate licence for application {}" - ACTION_SURRENDER_APPROVAL = "Surrender licence for application {}" - ACTION_RENEW_PROPOSAL = "Create Renewal application for application {}" - ACTION_AMEND_PROPOSAL = "Create Amendment application for application {}" - #Vehicle - ACTION_CREATE_VEHICLE = "Create Vehicle {}" - ACTION_EDIT_VEHICLE = "Edit Vehicle {}" - #Vessel - ACTION_CREATE_VESSEL = "Create Vessel {}" - ACTION_EDIT_VESSEL= "Edit Vessel {}" - ACTION_PUT_ONHOLD = "Put Application On-hold {}" - ACTION_REMOVE_ONHOLD = "Remove Application On-hold {}" - ACTION_WITH_QA_OFFICER = "Send Application QA Officer {}" - ACTION_QA_OFFICER_COMPLETED = "QA Officer Assessment Completed {}" - - # monthly invoicing by cron - ACTION_SEND_MONTHLY_INVOICE = "Send monthly invoice {} for application {} to {}" - ACTION_SEND_PAYMENT_DUE_NOTIFICATION = "Send monthly invoice/BPAY payment due notification {} for application {} to {}" - - class Meta: - app_label = 'commercialoperator' - ordering = ('-when',) - - @classmethod - def log_action(cls, proposal, action, user): - return cls.objects.create( - proposal=proposal, - who=user, - what=str(action) - ) - - proposal = models.ForeignKey(Proposal, related_name='action_logs') - - -class ReferralRecipientGroup(models.Model): - #site = models.OneToOneField(Site, default='1') - name = models.CharField(max_length=30, unique=True) - members = models.ManyToManyField(EmailUser) - - def __str__(self): - #return 'Referral Recipient Group' - return self.name - - @property - def all_members(self): - all_members = [] - all_members.extend(self.members.all()) - member_ids = [m.id for m in self.members.all()] - #all_members.extend(EmailUser.objects.filter(is_superuser=True,is_staff=True,is_active=True).exclude(id__in=member_ids)) - return all_members - - @property - def filtered_members(self): - return self.members.all() - - @property - def members_list(self): - return list(self.members.all().values_list('email', flat=True)) - - class Meta: - app_label = 'commercialoperator' - verbose_name = "Referral group" - verbose_name_plural = "Referral groups" - -class QAOfficerGroup(models.Model): - #site = models.OneToOneField(Site, default='1') - name = models.CharField(max_length=30, unique=True) - members = models.ManyToManyField(EmailUser) - default = models.BooleanField(default=False) - - def __str__(self): - return 'QA Officer Group' - - @property - def all_members(self): - all_members = [] - all_members.extend(self.members.all()) - member_ids = [m.id for m in self.members.all()] - #all_members.extend(EmailUser.objects.filter(is_superuser=True,is_staff=True,is_active=True).exclude(id__in=member_ids)) - return all_members - - @property - def filtered_members(self): - return self.members.all() - - @property - def members_list(self): - return list(self.members.all().values_list('email', flat=True)) - - class Meta: - app_label = 'commercialoperator' - verbose_name = "QA group" - verbose_name_plural = "QA group" - - - def _clean(self): - try: - default = QAOfficerGroup.objects.get(default=True) - except ProposalAssessorGroup.DoesNotExist: - default = None - - if default and self.default: - raise ValidationError('There can only be one default proposal QA Officer group') - - @property - def current_proposals(self): - assessable_states = ['with_qa_officer'] - return Proposal.objects.filter(processing_status__in=assessable_states) - -# -#class ReferralRequestUserAction(UserAction): -# ACTION_LODGE_REQUEST = "Lodge request {}" -# ACTION_ASSIGN_TO = "Assign to {}" -# ACTION_UNASSIGN = "Unassign" -# ACTION_DECLINE_REQUEST = "Decline request" -# # Assessors -# -# ACTION_CONCLUDE_REQUEST = "Conclude request {}" -# -# @classmethod -# def log_action(cls, request, action, user): -# return cls.objects.create( -# request=request, -# who=user, -# what=str(action) -# ) -# -# request = models.ForeignKey(ReferralRequest,related_name='action_logs') -# -# class Meta: -# app_label = 'commercialoperator' - - -#class Referral(models.Model): -class Referral(RevisionedMixin): - SENT_CHOICES = ( - (1,'Sent From Assessor'), - (2,'Sent From Referral') - ) - PROCESSING_STATUS_CHOICES = ( - ('with_referral', 'Awaiting'), - ('recalled', 'Recalled'), - ('completed', 'Completed'), - ) - lodged_on = models.DateTimeField(auto_now_add=True) - proposal = models.ForeignKey(Proposal,related_name='referrals') - sent_by = models.ForeignKey(EmailUser,related_name='commercialoperator_assessor_referrals') - referral = models.ForeignKey(EmailUser,null=True,blank=True,related_name='commercialoperator_referalls') - referral_group = models.ForeignKey(ReferralRecipientGroup,null=True,blank=True,related_name='commercialoperator_referral_groups') - linked = models.BooleanField(default=False) - sent_from = models.SmallIntegerField(choices=SENT_CHOICES,default=SENT_CHOICES[0][0]) - processing_status = models.CharField('Processing Status', max_length=30, choices=PROCESSING_STATUS_CHOICES, - default=PROCESSING_STATUS_CHOICES[0][0]) - text = models.TextField(blank=True) #Assessor text - referral_text = models.TextField(blank=True) - document = models.ForeignKey(ReferralDocument, blank=True, null=True, related_name='referral_document') - - - class Meta: - app_label = 'commercialoperator' - ordering = ('-lodged_on',) - - def __str__(self): - return 'Application {} - Referral {}'.format(self.proposal.id,self.id) - - # Methods - @property - def latest_referrals(self): - return Referral.objects.filter(sent_by=self.referral, proposal=self.proposal)[:2] - - @property - def referral_assessment(self): - qs=self.assessment.filter(referral_assessment=True, referral_group=self.referral_group) - if qs: - return qs[0] - else: - return None - - - @property - def can_be_completed(self): - return True - #Referral cannot be completed until second level referral sent by referral has been completed/recalled - qs=Referral.objects.filter(sent_by=self.referral, proposal=self.proposal, processing_status='with_referral') - if qs: - return False - else: - return True - - def can_process(self, user): - if self.processing_status=='with_referral': - group = ReferralRecipientGroup.objects.filter(id=self.referral_group.id) - #user=request.user - if group and group[0] in user.referralrecipientgroup_set.all(): - return True - else: - return False - return False - - - def recall(self,request): - with transaction.atomic(): - if not self.proposal.can_assess(request.user): - raise exceptions.ProposalNotAuthorized() - self.processing_status = 'recalled' - self.save() - # TODO Log proposal action - self.proposal.log_user_action(ProposalUserAction.RECALL_REFERRAL.format(self.id,self.proposal.id),request) - # TODO log organisation action - applicant_field=getattr(self.proposal, self.proposal.applicant_field) - applicant_field.log_user_action(ProposalUserAction.RECALL_REFERRAL.format(self.id,self.proposal.id),request) - - def remind(self,request): - with transaction.atomic(): - if not self.proposal.can_assess(request.user): - raise exceptions.ProposalNotAuthorized() - # Create a log entry for the proposal - #self.proposal.log_user_action(ProposalUserAction.ACTION_REMIND_REFERRAL.format(self.id,self.proposal.id,'{}({})'.format(self.referral.get_full_name(),self.referral.email)),request) - self.proposal.log_user_action(ProposalUserAction.ACTION_REMIND_REFERRAL.format(self.id,self.proposal.id,'{}'.format(self.referral_group.name)),request) - # Create a log entry for the organisation - applicant_field=getattr(self.proposal, self.proposal.applicant_field) - applicant_field.log_user_action(ProposalUserAction.ACTION_REMIND_REFERRAL.format(self.id,self.proposal.id,'{}'.format(self.referral_group.name)),request) - # send email - recipients = self.referral_group.members_list - send_referral_email_notification(self,recipients,request,reminder=True) - - def resend(self,request): - with transaction.atomic(): - if not self.proposal.can_assess(request.user): - raise exceptions.ProposalNotAuthorized() - self.processing_status = 'with_referral' - self.proposal.processing_status = 'with_referral' - self.proposal.save() - self.sent_from = 1 - self.save() - # Create a log entry for the proposal - #self.proposal.log_user_action(ProposalUserAction.ACTION_RESEND_REFERRAL_TO.format(self.id,self.proposal.id,'{}({})'.format(self.referral.get_full_name(),self.referral.email)),request) - self.proposal.log_user_action(ProposalUserAction.ACTION_RESEND_REFERRAL_TO.format(self.id,self.proposal.id,'{}'.format(self.referral_group.name)),request) - # Create a log entry for the organisation - #self.proposal.applicant.log_user_action(ProposalUserAction.ACTION_RESEND_REFERRAL_TO.format(self.id,self.proposal.id,'{}({})'.format(self.referral.get_full_name(),self.referral.email)),request) - applicant_field=getattr(self.proposal, self.proposal.applicant_field) - applicant_field.log_user_action(ProposalUserAction.ACTION_RESEND_REFERRAL_TO.format(self.id,self.proposal.id,'{}'.format(self.referral_group.name)),request) - # send email - recipients = self.referral_group.members_list - send_referral_email_notification(self,recipients,request) - - def complete(self,request): - with transaction.atomic(): - try: - #if request.user != self.referral: - group = ReferralRecipientGroup.objects.filter(id=self.referral_group.id) - #print u.referralrecipientgroup_set.all() - user=request.user - if group and group[0] not in user.referralrecipientgroup_set.all(): - raise exceptions.ReferralNotAuthorized() - self.processing_status = 'completed' - self.referral = request.user - self.referral_text = request.user.get_full_name() + ': ' + request.data.get('referral_comment') - self.add_referral_document(request) - self.save() - # TODO Log proposal action - #self.proposal.log_user_action(ProposalUserAction.CONCLUDE_REFERRAL.format(self.id,self.proposal.id,'{}({})'.format(self.referral.get_full_name(),self.referral.email)),request) - self.proposal.log_user_action(ProposalUserAction.CONCLUDE_REFERRAL.format(request.user.get_full_name(), self.id,self.proposal.id,'{}'.format(self.referral_group.name)),request) - # TODO log organisation action - #self.proposal.applicant.log_user_action(ProposalUserAction.CONCLUDE_REFERRAL.format(self.id,self.proposal.id,'{}({})'.format(self.referral.get_full_name(),self.referral.email)),request) - applicant_field=getattr(self.proposal, self.proposal.applicant_field) - applicant_field.log_user_action(ProposalUserAction.CONCLUDE_REFERRAL.format(request.user.get_full_name(), self.id,self.proposal.id,'{}'.format(self.referral_group.name)),request) - send_referral_complete_email_notification(self,request) - except: - raise - - def add_referral_document(self, request): - with transaction.atomic(): - try: - if request.data.has_key('referral_document'): - referral_document = request.data['referral_document'] - if referral_document != 'null': - try: - document = self.referral_documents.get(input_name=str(referral_document)) - except ReferralDocument.DoesNotExist: - document = self.referral_documents.get_or_create(input_name=str(referral_document), name=str(referral_document))[0] - document.name = str(referral_document) - # commenting out below tow lines - we want to retain all past attachments - reversion can use them - #if document._file and os.path.isfile(document._file.path): - # os.remove(document._file.path) - document._file = referral_document - document.save() - d=ReferralDocument.objects.get(id=document.id) - self.referral_document = d - comment = 'Referral Document Added: {}'.format(document.name) - else: - self.referral_document = None - #comment = 'Referral Document Deleted: {}'.format(request.data['referral_document_name']) - comment = 'Referral Document Deleted' - #self.save() - self.save(version_comment=comment) # to allow revision to be added to reversion history - self.proposal.log_user_action(ProposalUserAction.ACTION_REFERRAL_DOCUMENT.format(self.id),request) - # Create a log entry for the organisation - applicant_field=getattr(self.proposal, self.proposal.applicant_field) - applicant_field.log_user_action(ProposalUserAction.ACTION_REFERRAL_DOCUMENT.format(self.id),request) - return self - except: - raise - - - def send_referral(self,request,referral_email,referral_text): - with transaction.atomic(): - try: - if self.proposal.processing_status == 'with_referral': - if request.user != self.referral: - raise exceptions.ReferralNotAuthorized() - if self.sent_from != 1: - raise exceptions.ReferralCanNotSend() - self.proposal.processing_status = 'with_referral' - self.proposal.save() - referral = None - # Check if the user is in ledger - try: - user = EmailUser.objects.get(email__icontains=referral_email) - except EmailUser.DoesNotExist: - # Validate if it is a deparment user - department_user = get_department_user(referral_email) - if not department_user: - raise ValidationError('The user you want to send the referral to is not a member of the department') - # Check if the user is in ledger or create - - user,created = EmailUser.objects.get_or_create(email=department_user['email'].lower()) - if created: - user.first_name = department_user['given_name'] - user.last_name = department_user['surname'] - user.save() - qs=Referral.objects.filter(sent_by=user, proposal=self.proposal) - if qs: - raise ValidationError('You cannot send referral to this user') - try: - Referral.objects.get(referral=user,proposal=self.proposal) - raise ValidationError('A referral has already been sent to this user') - except Referral.DoesNotExist: - # Create Referral - referral = Referral.objects.create( - proposal = self.proposal, - referral=user, - sent_by=request.user, - sent_from=2, - text=referral_text - ) - # try: - # referral_assessment=ProposalAssessment.objects.get(proposal=self,referral_group=referral_group, referral_assessment=True, referral=referral) - # except ProposalAssessment.DoesNotExist: - # referral_assessment=ProposalAssessment.objects.create(proposal=self,referral_group=referral_group, referral_assessment=True, referral=referral) - # checklist=ChecklistQuestion.objects.filter(list_type='referral_list', obsolete=False) - # for chk in checklist: - # try: - # chk_instance=ProposalAssessmentAnswer.objects.get(question=chk, assessment=referral_assessment) - # except ProposalAssessmentAnswer.DoesNotExist: - # chk_instance=ProposalAssessmentAnswer.objects.create(question=chk, assessment=referral_assessment) - # Create a log entry for the proposal - self.proposal.log_user_action(ProposalUserAction.ACTION_SEND_REFERRAL_TO.format(referral.id,self.proposal.id,'{}({})'.format(user.get_full_name(),user.email)),request) - # Create a log entry for the organisation - applicant_field=getattr(self.proposal, self.proposal.applicant_field) - applicant_field.log_user_action(ProposalUserAction.ACTION_SEND_REFERRAL_TO.format(referral.id,self.proposal.id,'{}({})'.format(user.get_full_name(),user.email)),request) - # send email - recipients = self.email_group.members_list - send_referral_email_notification(referral,recipients,request) - else: - raise exceptions.ProposalReferralCannotBeSent() - except: - raise - - - # Properties - @property - def region(self): - return self.proposal.region - - @property - def activity(self): - return self.proposal.activity - - @property - def title(self): - return self.proposal.title - - # @property - # def applicant(self): - # return self.proposal.applicant.name - - @property - def applicant(self): - return self.proposal.applicant - - @property - def can_be_processed(self): - return self.processing_status == 'with_referral' - - def can_assess_referral(self,user): - return self.processing_status == 'with_referral' - -class ProposalRequirement(OrderedModel): - RECURRENCE_PATTERNS = [(1, 'Weekly'), (2, 'Monthly'), (3, 'Yearly')] - standard_requirement = models.ForeignKey(ProposalStandardRequirement,null=True,blank=True) - free_requirement = models.TextField(null=True,blank=True) - standard = models.BooleanField(default=True) - proposal = models.ForeignKey(Proposal,related_name='requirements') - due_date = models.DateField(null=True,blank=True) - recurrence = models.BooleanField(default=False) - recurrence_pattern = models.SmallIntegerField(choices=RECURRENCE_PATTERNS,default=1) - recurrence_schedule = models.IntegerField(null=True,blank=True) - copied_from = models.ForeignKey('self', on_delete=models.SET_NULL, blank=True, null=True) - is_deleted = models.BooleanField(default=False) - #To determine if requirement has been added by referral and the group of referral who added it - #Null if added by an assessor - referral_group = models.ForeignKey(ReferralRecipientGroup,null=True,blank=True,related_name='requirement_referral_groups') - #order = models.IntegerField(default=1) - - class Meta: - app_label = 'commercialoperator' - - - @property - def requirement(self): - return self.standard_requirement.text if self.standard else self.free_requirement - - def can_referral_edit(self,user): - if self.proposal.processing_status=='with_referral': - if self.referral_group: - group = ReferralRecipientGroup.objects.filter(id=self.referral_group.id) - #user=request.user - if group and group[0] in user.referralrecipientgroup_set.all(): - return True - else: - return False - return False - - def add_documents(self, request): - with transaction.atomic(): - try: - # save the files - data = json.loads(request.data.get('data')) - if not data.get('update'): - documents_qs = self.requirement_documents.filter(input_name='requirement_doc', visible=True) - documents_qs.delete() - for idx in range(data['num_files']): - _file = request.data.get('file-'+str(idx)) - document = self.requirement_documents.create(_file=_file, name=_file.name) - document.input_name = data['input_name'] - document.can_delete = True - document.save() - # end save documents - self.save() - except: - raise - return - - - -@python_2_unicode_compatible -#class ProposalStandardRequirement(models.Model): -class ChecklistQuestion(RevisionedMixin): - TYPE_CHOICES = ( - ('assessor_list','Assessor Checklist'), - ('referral_list','Referral Checklist') - ) - ANSWER_TYPE_CHOICES = ( - ('yes_no','Yes/No type'), - ('free_text','Free text type') - ) - text = models.TextField() - list_type = models.CharField('Checklist type', max_length=30, choices=TYPE_CHOICES, - default=TYPE_CHOICES[0][0]) - answer_type = models.CharField('Answer type', max_length=30, choices=ANSWER_TYPE_CHOICES, - default=ANSWER_TYPE_CHOICES[0][0]) - #correct_answer= models.BooleanField(default=False) - obsolete = models.BooleanField(default=False) - - def __str__(self): - return self.text - - class Meta: - app_label = 'commercialoperator' - - -class ProposalAssessment(RevisionedMixin): - proposal=models.ForeignKey(Proposal, related_name='assessment') - completed = models.BooleanField(default=False) - submitter = models.ForeignKey(EmailUser, blank=True, null=True, related_name='proposal_assessment') - referral_assessment=models.BooleanField(default=False) - referral_group = models.ForeignKey(ReferralRecipientGroup,null=True,blank=True,related_name='referral_assessment') - referral=models.ForeignKey(Referral, related_name='assessment',blank=True, null=True ) - # def __str__(self): - # return self.proposal - - class Meta: - app_label = 'commercialoperator' - unique_together = ('proposal', 'referral_group',) - - @property - def checklist(self): - return self.answers.all() - - @property - def referral_group_name(self): - if self.referral_group: - return self.referral_group.name - else: - return '' - - -class ProposalAssessmentAnswer(RevisionedMixin): - question=models.ForeignKey(ChecklistQuestion, related_name='answers') - answer = models.NullBooleanField() - assessment=models.ForeignKey(ProposalAssessment, related_name='answers', null=True, blank=True) - text_answer= models.CharField(max_length=256, blank=True, null=True) - - def __str__(self): - return self.question.text - - class Meta: - app_label = 'commercialoperator' - verbose_name = "Assessment answer" - verbose_name_plural = "Assessment answers" - - -class QAOfficerReferral(RevisionedMixin): - SENT_CHOICES = ( - (1,'Sent From Assessor'), - (2,'Sent From Referral') - ) - PROCESSING_STATUS_CHOICES = ( - ('with_qaofficer', 'Awaiting'), - ('recalled', 'Recalled'), - ('completed', 'Completed'), - ) - lodged_on = models.DateTimeField(auto_now_add=True) - proposal = models.ForeignKey(Proposal,related_name='qaofficer_referrals') - sent_by = models.ForeignKey(EmailUser,related_name='assessor_qaofficer_referrals') - qaofficer = models.ForeignKey(EmailUser, null=True, blank=True, related_name='qaofficers') - qaofficer_group = models.ForeignKey(QAOfficerGroup,null=True,blank=True,related_name='qaofficer_groups') - linked = models.BooleanField(default=False) - sent_from = models.SmallIntegerField(choices=SENT_CHOICES,default=SENT_CHOICES[0][0]) - processing_status = models.CharField('Processing Status', max_length=30, choices=PROCESSING_STATUS_CHOICES, - default=PROCESSING_STATUS_CHOICES[0][0]) - text = models.TextField(blank=True) #Assessor text - qaofficer_text = models.TextField(blank=True) - document = models.ForeignKey(QAOfficerDocument, blank=True, null=True, related_name='qaofficer_referral_document') - - - class Meta: - app_label = 'commercialoperator' - ordering = ('-lodged_on',) - - def __str__(self): - return 'Application {} - QA Officer referral {}'.format(self.proposal.id,self.id) - - # Methods - @property - def latest_qaofficer_referrals(self): - return QAOfficer.objects.filter(sent_by=self.qaofficer, proposal=self.proposal)[:2] - -# @property -# def can_be_completed(self): -# #Referral cannot be completed until second level referral sent by referral has been completed/recalled -# qs=Referral.objects.filter(sent_by=self.referral, proposal=self.proposal, processing_status='with_referral') -# if qs: -# return False -# else: -# return True -# -# def recall(self,request): -# with transaction.atomic(): -# if not self.proposal.can_assess(request.user): -# raise exceptions.ProposalNotAuthorized() -# self.processing_status = 'recalled' -# self.save() -# # TODO Log proposal action -# self.proposal.log_user_action(ProposalUserAction.RECALL_REFERRAL.format(self.id,self.proposal.id),request) -# # TODO log organisation action -# self.proposal.applicant.log_user_action(ProposalUserAction.RECALL_REFERRAL.format(self.id,self.proposal.id),request) -# -# def remind(self,request): -# with transaction.atomic(): -# if not self.proposal.can_assess(request.user): -# raise exceptions.ProposalNotAuthorized() -# # Create a log entry for the proposal -# #self.proposal.log_user_action(ProposalUserAction.ACTION_REMIND_REFERRAL.format(self.id,self.proposal.id,'{}({})'.format(self.referral.get_full_name(),self.referral.email)),request) -# self.proposal.log_user_action(ProposalUserAction.ACTION_REMIND_REFERRAL.format(self.id,self.proposal.id,'{}'.format(self.referral_group.name)),request) -# # Create a log entry for the organisation -# self.proposal.applicant.log_user_action(ProposalUserAction.ACTION_REMIND_REFERRAL.format(self.id,self.proposal.id,'{}'.format(self.referral_group.name)),request) -# # send email -# recipients = self.referral_group.members_list -# send_referral_email_notification(self,recipients,request,reminder=True) -# -# def resend(self,request): -# with transaction.atomic(): -# if not self.proposal.can_assess(request.user): -# raise exceptions.ProposalNotAuthorized() -# self.processing_status = 'with_referral' -# self.proposal.processing_status = 'with_referral' -# self.proposal.save() -# self.sent_from = 1 -# self.save() -# # Create a log entry for the proposal -# #self.proposal.log_user_action(ProposalUserAction.ACTION_RESEND_REFERRAL_TO.format(self.id,self.proposal.id,'{}({})'.format(self.referral.get_full_name(),self.referral.email)),request) -# self.proposal.log_user_action(ProposalUserAction.ACTION_RESEND_REFERRAL_TO.format(self.id,self.proposal.id,'{}'.format(self.referral_group.name)),request) -# # Create a log entry for the organisation -# #self.proposal.applicant.log_user_action(ProposalUserAction.ACTION_RESEND_REFERRAL_TO.format(self.id,self.proposal.id,'{}({})'.format(self.referral.get_full_name(),self.referral.email)),request) -# self.proposal.applicant.log_user_action(ProposalUserAction.ACTION_RESEND_REFERRAL_TO.format(self.id,self.proposal.id,'{}'.format(self.referral_group.name)),request) -# # send email -# recipients = self.referral_group.members_list -# send_referral_email_notification(self,recipients,request) -# -# def complete(self,request): -# with transaction.atomic(): -# try: -# #if request.user != self.referral: -# group = ReferralRecipientGroup.objects.filter(name=self.referral_group) -# if group and group[0] in u.referralrecipientgroup_set.all(): -# raise exceptions.ReferralNotAuthorized() -# self.processing_status = 'completed' -# self.referral = request.user -# self.referral_text = request.user.get_full_name() + ': ' + request.data.get('referral_comment') -# self.add_referral_document(request) -# self.save() -# # TODO Log proposal action -# #self.proposal.log_user_action(ProposalUserAction.CONCLUDE_REFERRAL.format(self.id,self.proposal.id,'{}({})'.format(self.referral.get_full_name(),self.referral.email)),request) -# self.proposal.log_user_action(ProposalUserAction.CONCLUDE_REFERRAL.format(request.user.get_full_name(), self.id,self.proposal.id,'{}'.format(self.referral_group.name)),request) -# # TODO log organisation action -# #self.proposal.applicant.log_user_action(ProposalUserAction.CONCLUDE_REFERRAL.format(self.id,self.proposal.id,'{}({})'.format(self.referral.get_full_name(),self.referral.email)),request) -# self.proposal.applicant.log_user_action(ProposalUserAction.CONCLUDE_REFERRAL.format(request.user.get_full_name(), self.id,self.proposal.id,'{}'.format(self.referral_group.name)),request) -# send_referral_complete_email_notification(self,request) -# except: -# raise -# -# def add_referral_document(self, request): -# with transaction.atomic(): -# try: -# referral_document = request.data['referral_document'] -# if referral_document != 'null': -# try: -# document = self.referral_documents.get(input_name=str(referral_document)) -# except ReferralDocument.DoesNotExist: -# document = self.referral_documents.get_or_create(input_name=str(referral_document), name=str(referral_document))[0] -# document.name = str(referral_document) -# # commenting out below tow lines - we want to retain all past attachments - reversion can use them -# #if document._file and os.path.isfile(document._file.path): -# # os.remove(document._file.path) -# document._file = referral_document -# document.save() -# d=ReferralDocument.objects.get(id=document.id) -# self.referral_document = d -# comment = 'Referral Document Added: {}'.format(document.name) -# else: -# self.referral_document = None -# comment = 'Referral Document Deleted: {}'.format(request.data['referral_document_name']) -# #self.save() -# self.save(version_comment=comment) # to allow revision to be added to reversion history -# self.proposal.log_user_action(ProposalUserAction.ACTION_REFERRAL_DOCUMENT.format(self.id),request) -# # Create a log entry for the organisation -# self.proposal.applicant.log_user_action(ProposalUserAction.ACTION_REFERRAL_DOCUMENT.format(self.id),request) -# return self -# except: -# raise -# -# -# def send_referral(self,request,referral_email,referral_text): -# with transaction.atomic(): -# try: -# if self.proposal.processing_status == 'with_referral': -# if request.user != self.referral: -# raise exceptions.ReferralNotAuthorized() -# if self.sent_from != 1: -# raise exceptions.ReferralCanNotSend() -# self.proposal.processing_status = 'with_referral' -# self.proposal.save() -# referral = None -# # Check if the user is in ledger -# try: -# user = EmailUser.objects.get(email__icontains=referral_email) -# except EmailUser.DoesNotExist: -# # Validate if it is a deparment user -# department_user = get_department_user(referral_email) -# if not department_user: -# raise ValidationError('The user you want to send the referral to is not a member of the department') -# # Check if the user is in ledger or create -# -# user,created = EmailUser.objects.get_or_create(email=department_user['email'].lower()) -# if created: -# user.first_name = department_user['given_name'] -# user.last_name = department_user['surname'] -# user.save() -# qs=Referral.objects.filter(sent_by=user, proposal=self.proposal) -# if qs: -# raise ValidationError('You cannot send referral to this user') -# try: -# Referral.objects.get(referral=user,proposal=self.proposal) -# raise ValidationError('A referral has already been sent to this user') -# except Referral.DoesNotExist: -# # Create Referral -# referral = Referral.objects.create( -# proposal = self.proposal, -# referral=user, -# sent_by=request.user, -# sent_from=2, -# text=referral_text -# ) -# # Create a log entry for the proposal -# self.proposal.log_user_action(ProposalUserAction.ACTION_SEND_REFERRAL_TO.format(referral.id,self.proposal.id,'{}({})'.format(user.get_full_name(),user.email)),request) -# # Create a log entry for the organisation -# self.proposal.applicant.log_user_action(ProposalUserAction.ACTION_SEND_REFERRAL_TO.format(referral.id,self.proposal.id,'{}({})'.format(user.get_full_name(),user.email)),request) -# # send email -# recipients = self.email_group.members_list -# send_referral_email_notification(referral,recipients,request) -# else: -# raise exceptions.ProposalReferralCannotBeSent() -# except: -# raise - - - # Properties - @property - def region(self): - return self.proposal.region - - @property - def activity(self): - return self.proposal.activity - - @property - def title(self): - return self.proposal.title - - @property - def applicant(self): - return self.proposal.applicant.name - - @property - def can_be_processed(self): - return self.processing_status == 'with_qa_officer' - - def can_asses(self): - return self.can_be_processed and self.proposal.is_qa_officer() - - -@receiver(pre_delete, sender=Proposal) -def delete_documents(sender, instance, *args, **kwargs): - for document in instance.documents.all(): - document.delete() - -def clone_proposal_with_status_reset(proposal): - """ - To Test: - from commercialoperator.components.proposals.models import clone_proposal_with_status_reset - p=Proposal.objects.get(id=57) - p0=clone_proposal_with_status_reset(p) - """ - with transaction.atomic(): - try: - original_proposal = copy.deepcopy(proposal) - #proposal = duplicate_object(proposal) # clone object and related objects - proposal=duplicate_tclass(proposal) - # manually duplicate the comms logs -- hck, not hndled by duplicate object (maybe due to inheritance?) - # proposal.comms_logs.create(text='cloning proposal reset (original proposal {}, new proposal {})'.format(original_proposal.id, proposal.id)) - # for comms_log in proposal.comms_logs.all(): - # comms_log.id=None - # comms_log.communicationslogentry_ptr_id=None - # comms_log.proposal_id=original_proposal.id - # comms_log.save() - - # reset some properties - proposal.customer_status = 'draft' - proposal.processing_status = 'draft' - proposal.assessor_data = None - proposal.comment_data = None - - proposal.lodgement_number = '' - proposal.lodgement_sequence = 0 - proposal.lodgement_date = None - - proposal.assigned_officer = None - proposal.assigned_approver = None - - proposal.approval = None - proposal.approval_level_document = None - proposal.migrated=False - - proposal.save(no_revision=True) - - #clone_documents(proposal, original_proposal, media_prefix='media') - _clone_documents(proposal, original_proposal, media_prefix='media') - return proposal - except: - raise - -def clone_documents(proposal, original_proposal, media_prefix): - for proposal_document in ProposalDocument.objects.filter(proposal_id=proposal.id): - proposal_document._file.name = u'{}/proposals/{}/documents/{}'.format(settings.MEDIA_APP_DIR, proposal.id, proposal_document.name) - proposal_document.can_delete = True - proposal_document.save() - - for proposal_required_document in ProposalRequiredDocument.objects.filter(proposal_id=proposal.id): - proposal_required_document._file.name = u'{}/proposals/{}/required_documents/{}'.format(settings.MEDIA_APP_DIR, proposal.id, proposal_required_document.name) - proposal_required_document.can_delete = True - proposal_required_document.save() - - for referral in proposal.referrals.all(): - for referral_document in ReferralDocument.objects.filter(referral=referral): - referral_document._file.name = u'{}/proposals/{}/referral/{}'.format(settings.MEDIA_APP_DIR, proposal.id, referral_document.name) - referral_document.can_delete = True - referral_document.save() - - for qa_officer_document in QAOfficerDocument.objects.filter(proposal_id=proposal.id): - qa_officer_document._file.name = u'{}/proposals/{}/qaofficer/{}'.format(settings.MEDIA_APP_DIR, proposal.id, qa_officer_document.name) - qa_officer_document.can_delete = True - qa_officer_document.save() - - for onhold_document in OnHoldDocument.objects.filter(proposal_id=proposal.id): - onhold_document._file.name = u'{}/proposals/{}/on_hold/{}'.format(settings.MEDIA_APP_DIR, proposal.id, onhold_document.name) - onhold_document.can_delete = True - onhold_document.save() - - for requirement in proposal.requirements.all(): - for requirement_document in RequirementDocument.objects.filter(requirement=requirement): - requirement_document._file.name = u'{}/proposals/{}/requirement_documents/{}'.format(settings.MEDIA_APP_DIR, proposal.id, requirement_document.name) - requirement_document.can_delete = True - requirement_document.save() - - for log_entry_document in ProposalLogDocument.objects.filter(log_entry__proposal_id=proposal.id): - log_entry_document._file.name = log_entry_document._file.name.replace(str(original_proposal.id), str(proposal.id)) - log_entry_document.can_delete = True - log_entry_document.save() - - # copy documents on file system and reset can_delete flag - media_dir = '{}/{}'.format(media_prefix, settings.MEDIA_APP_DIR) - subprocess.call('cp -pr {0}/proposals/{1} {0}/proposals/{2}'.format(media_dir, original_proposal.id, proposal.id), shell=True) - - -def _clone_documents(proposal, original_proposal, media_prefix): - for proposal_document in ProposalDocument.objects.filter(proposal=original_proposal.id): - proposal_document.proposal = proposal - proposal_document.id = None - proposal_document._file.name = u'{}/proposals/{}/documents/{}'.format(settings.MEDIA_APP_DIR, proposal.id, proposal_document.name) - proposal_document.can_delete = True - proposal_document.save() - - for proposal_required_document in ProposalRequiredDocument.objects.filter(proposal=original_proposal.id): - proposal_required_document.proposal = proposal - proposal_required_document.id = None - proposal_required_document._file.name = u'{}/proposals/{}/required_documents/{}'.format(settings.MEDIA_APP_DIR, proposal.id, proposal_required_document.name) - proposal_required_document.can_delete = True - proposal_required_document.save() - - # copy documents on file system and reset can_delete flag - media_dir = '{}/{}'.format(media_prefix, settings.MEDIA_APP_DIR) - subprocess.call('cp -pr {0}/proposals/{1} {0}/proposals/{2}'.format(media_dir, original_proposal.id, proposal.id), shell=True) - -def duplicate_object(self): - """ - Duplicate a model instance, making copies of all foreign keys pointing to it. - There are 3 steps that need to occur in order: - - 1. Enumerate the related child objects and m2m relations, saving in lists/dicts - 2. Copy the parent object per django docs (doesn't copy relations) - 3a. Copy the child objects, relating to the copied parent object - 3b. Re-create the m2m relations on the copied parent object - - """ - related_objects_to_copy = [] - relations_to_set = {} - # Iterate through all the fields in the parent object looking for related fields - for field in self._meta.get_fields(): - if field.name in ['proposal', 'approval']: - print 'Continuing ...' - pass - elif field.one_to_many: - # One to many fields are backward relationships where many child objects are related to the - # parent (i.e. SelectedPhrases). Enumerate them and save a list so we can copy them after - # duplicating our parent object. - print('Found a one-to-many field: {}'.format(field.name)) - - # 'field' is a ManyToOneRel which is not iterable, we need to get the object attribute itself - related_object_manager = getattr(self, field.name) - related_objects = list(related_object_manager.all()) - if related_objects: - print(' - {len(related_objects)} related objects to copy') - related_objects_to_copy += related_objects - - elif field.many_to_one: - # In testing so far, these relationships are preserved when the parent object is copied, - # so they don't need to be copied separately. - print('Found a many-to-one field: {}'.format(field.name)) - - elif field.many_to_many: - # Many to many fields are relationships where many parent objects can be related to many - # child objects. Because of this the child objects don't need to be copied when we copy - # the parent, we just need to re-create the relationship to them on the copied parent. - print('Found a many-to-many field: {}'.format(field.name)) - related_object_manager = getattr(self, field.name) - relations = list(related_object_manager.all()) - if relations: - print(' - {} relations to set'.format(len(relations))) - relations_to_set[field.name] = relations - - # Duplicate the parent object - self.pk = None - self.lodgement_number = '' - self.save() - print('Copied parent object {}'.format(str(self))) - - # Copy the one-to-many child objects and relate them to the copied parent - for related_object in related_objects_to_copy: - # Iterate through the fields in the related object to find the one that relates to the - # parent model (I feel like there might be an easier way to get at this). - for related_object_field in related_object._meta.fields: - if related_object_field.related_model == self.__class__: - # If the related_model on this field matches the parent object's class, perform the - # copy of the child object and set this field to the parent object, creating the - # new child -> parent relationship. - related_object.pk = None - #if related_object_field.name=='approvals': - # related_object.lodgement_number = None - ##if isinstance(related_object, Approval): - ## related_object.lodgement_number = '' - - setattr(related_object, related_object_field.name, self) - print related_object_field - try: - related_object.save() - except Exception, e: - logger.warn(e) - - text = str(related_object) - text = (text[:40] + '..') if len(text) > 40 else text - print('|- Copied child object {}'.format(text)) - - # Set the many-to-many relations on the copied parent - for field_name, relations in relations_to_set.items(): - # Get the field by name and set the relations, creating the new relationships - field = getattr(self, field_name) - field.set(relations) - text_relations = [] - for relation in relations: - text_relations.append(str(relation)) - print('|- Set {} many-to-many relations on {} {}'.format(len(relations), field_name, text_relations)) - - return self - -def duplicate_tclass(p): - original_proposal=copy.deepcopy(p) - p.id=None - p.save() - print ('new proposal',p) - - for park in original_proposal.parks.all(): - - original_park=copy.deepcopy(park) - park.id=None - park.proposal=p - park.save() - print('new park', park,park.id, original_park, original_park.id, park.proposal) - for activity in original_park.activities.all(): - activity.id=None - activity.proposal_park=park - activity.save() - print('new activity', activity, activity.id, park) - #new_activities_list.append(new_ac) - for access in original_park.access_types.all(): - access.id=None - access.proposal_park=park - access.save() - print('new access', access, park) - #new_access_list.append(new_ac) - for zone in original_park.zones.all(): - original_zone=copy.deepcopy(zone) - zone.id=None - zone.proposal_park=park - zone.save() - print('new zone',zone) - for acz in original_zone.park_activities.all(): - acz.id=None - acz.park_zone=zone - acz.save() - print('new zone activity', acz, zone) - - for trail in original_proposal.trails.all(): - original_trail=copy.deepcopy(trail) - trail.id=None - trail.proposal=p - trail.save() - - for section in original_trail.sections.all(): - original_section=copy.deepcopy(section) - section.id=None - section.proposal_trail=trail - section.save() - print('new section', section, trail) - for act in original_section.trail_activities.all(): - act.id=None - act.trail_section=section - act.save() - print('new trail activity', act, section) - - try: - other_details=ProposalOtherDetails.objects.get(proposal=original_proposal) - new_accreditations=[] - print('proposal:',original_proposal, original_proposal.other_details.id, other_details.id) - print('accreditations', other_details.accreditations.all()) - for acc in other_details.accreditations.all(): - acc.id=None - acc.save() - new_accreditations.append(acc) - other_details.id=None - other_details.proposal=p - other_details.save() - for new_acc in new_accreditations: - new_acc.proposal_other_details=other_details - new_acc.save() - except ProposalOtherDetails.DoesNotExist: - other_details=ProposalOtherDetails.objects.create(proposal=p) - - for vehicle in original_proposal.vehicles.all(): - vehicle.id=None - vehicle.proposal=p - vehicle.save() - for vessel in original_proposal.vessels.all(): - vessel.id=None - vessel.proposal=p - vessel.save() - - return p - - - -def searchKeyWords(searchWords, searchProposal, searchApproval, searchCompliance, is_internal= True): - from commercialoperator.utils import search, search_approval, search_compliance - from commercialoperator.components.approvals.models import Approval - from commercialoperator.components.compliances.models import Compliance - qs = [] - if is_internal: - proposal_list = Proposal.objects.filter(application_type__name='T Class').exclude(processing_status__in=['discarded','draft']) - approval_list = Approval.objects.all().order_by('lodgement_number', '-issue_date').distinct('lodgement_number') - compliance_list = Compliance.objects.all() - if searchWords: - if searchProposal: - for p in proposal_list: - #if p.data: - if p.search_data: - try: - #results = search(p.data[0], searchWords) - results = search(p.search_data, searchWords) - final_results = {} - if results: - for r in results: - for key, value in r.iteritems(): - final_results.update({'key': key, 'value': value}) - res = { - 'number': p.lodgement_number, - 'id': p.id, - 'type': 'Proposal', - 'applicant': p.applicant, - 'text': final_results, - } - qs.append(res) - except: - raise - if searchApproval: - for a in approval_list: - try: - results = search_approval(a, searchWords) - qs.extend(results) - except: - raise - if searchCompliance: - for c in compliance_list: - try: - results = search_compliance(c, searchWords) - qs.extend(results) - except: - raise - return qs - -def search_reference(reference_number): - from commercialoperator.components.approvals.models import Approval - from commercialoperator.components.compliances.models import Compliance - proposal_list = Proposal.objects.all().exclude(processing_status__in=['discarded']) - approval_list = Approval.objects.all().order_by('lodgement_number', '-issue_date').distinct('lodgement_number') - compliance_list = Compliance.objects.all().exclude(processing_status__in=['future']) - record = {} - try: - result = proposal_list.get(lodgement_number = reference_number) - record = { 'id': result.id, - 'type': 'proposal' } - except Proposal.DoesNotExist: - try: - result = approval_list.get(lodgement_number = reference_number) - record = { 'id': result.id, - 'type': 'approval' } - except Approval.DoesNotExist: - try: - for c in compliance_list: - if c.reference == reference_number: - record = { 'id': c.id, - 'type': 'compliance' } - except: - raise ValidationError('Record with provided reference number does not exist') - if record: - return record - else: - raise ValidationError('Record with provided reference number does not exist') - -from ckeditor.fields import RichTextField -class HelpPage(models.Model): - HELP_TEXT_EXTERNAL = 1 - HELP_TEXT_INTERNAL = 2 - HELP_TYPE_CHOICES = ( - (HELP_TEXT_EXTERNAL, 'External'), - (HELP_TEXT_INTERNAL, 'Internal'), - ) - - application_type = models.ForeignKey(ApplicationType) - content = RichTextField() - description = models.CharField(max_length=256, blank=True, null=True) - help_type = models.SmallIntegerField('Help Type', choices=HELP_TYPE_CHOICES, default=HELP_TEXT_EXTERNAL) - version = models.SmallIntegerField(default=1, blank=False, null=False) - - class Meta: - app_label = 'commercialoperator' - unique_together = ('application_type', 'help_type', 'version') - - -import reversion -reversion.register(Referral, follow=['referral_documents', 'assessment']) -reversion.register(ReferralDocument, follow=['referral_document']) - -#reversion.register(Proposal, follow=['documents', 'onhold_documents','required_documents','qaofficer_documents','comms_logs','other_details', 'parks', 'trails', 'vehicles', 'vessels', 'proposalrequest_set','proposaldeclineddetails', 'proposalonhold', 'requirements', 'referrals', 'qaofficer_referrals', 'compliances', 'referrals', 'approvals', 'park_entries', 'assessment', 'bookings', 'application_fees']) -reversion.register(Proposal, follow=['documents', 'onhold_documents','required_documents','qaofficer_documents','comms_logs','other_details', 'parks', 'trails', 'vehicles', 'vessels', 'proposalrequest_set','proposaldeclineddetails', 'proposalonhold', 'requirements', 'referrals', 'qaofficer_referrals', 'compliances', 'referrals', 'approvals', 'park_entries', 'assessment']) -reversion.register(ProposalDocument, follow=['onhold_documents']) -reversion.register(OnHoldDocument) -reversion.register(ProposalRequest) -reversion.register(ProposalRequiredDocument) -reversion.register(ProposalApplicantDetails) -reversion.register(ProposalActivitiesLand) -reversion.register(ProposalActivitiesMarine) -reversion.register(ProposalOtherDetails, follow=['accreditations']) - -reversion.register(ProposalLogEntry, follow=['documents',]) -reversion.register(ProposalLogDocument) - -#reversion.register(Park, follow=['proposals',]) -reversion.register(ProposalPark, follow=['activities','access_types', 'zones']) -reversion.register(ProposalParkAccess) - -#reversion.register(AccessType, follow=['proposals','proposalparkaccess_set', 'vehicles']) - -#reversion.register(Activity, follow=['proposalparkactivity_set','proposalparkzoneactivity_set', 'proposaltrailsectionactivity_set']) -reversion.register(ProposalParkActivity) - -reversion.register(ProposalParkZone, follow=['park_activities']) -reversion.register(ProposalParkZoneActivity) -reversion.register(ParkEntry) - -reversion.register(ProposalTrail, follow=['sections']) -reversion.register(Vehicle) -reversion.register(Vessel) -reversion.register(ProposalUserAction) - -reversion.register(ProposalTrailSection, follow=['trail_activities']) - -reversion.register(ProposalTrailSectionActivity) -reversion.register(AmendmentReason, follow=['amendmentrequest_set']) -reversion.register(AmendmentRequest) -reversion.register(Assessment) -reversion.register(ProposalDeclinedDetails) -reversion.register(ProposalOnHold) -reversion.register(ProposalStandardRequirement, follow=['proposalrequirement_set']) -reversion.register(ProposalRequirement, follow=['compliance_requirement']) -reversion.register(ReferralRecipientGroup, follow=['commercialoperator_referral_groups', 'referral_assessment']) -reversion.register(QAOfficerGroup, follow=['qaofficer_groups']) -reversion.register(QAOfficerReferral) -reversion.register(QAOfficerDocument, follow=['qaofficer_referral_document']) -reversion.register(ProposalAccreditation) -reversion.register(HelpPage) -reversion.register(ChecklistQuestion, follow=['answers']) -reversion.register(ProposalAssessment, follow=['answers']) -reversion.register(ProposalAssessmentAnswer) - - diff --git a/commercialoperator/components/proposals/reversion.txt b/commercialoperator/components/proposals/reversion.txt deleted file mode 100644 index 844b27879b..0000000000 --- a/commercialoperator/components/proposals/reversion.txt +++ /dev/null @@ -1,118 +0,0 @@ -#--------------------------------------------------------------------------------------------------- -# proposals/models.py - -import reversion -reversion.register(Referral, follow=['referral_documents',]) -reversion.register(ReferralDocument, follow=['referral_document']) - -reversion.register(Proposal, follow=['documents', 'onhold_documents','required_documents','qaofficer_documents','comms_log','other_details', 'parks', 'trails', 'vehicles', 'vessels', 'proposalrequest_set','proposaldeclineddetails_set', 'proposedonhold_set', 'requirements', 'referrals', 'qaofficer_referrals', 'compliances', 'referrals', 'approvals']) -reversion.register(ProposalDocument, follow=['onhold_documents']) -reversion.register(OnHoldDocument) -reversion.register(ProposalRequiredDocument) -reversion.register(QAOfficerDocument) -reversion.register(ProposalApplicantDetails) -reversion.register(ProposalActivitiesLand) -reversion.register(ProposalActivitiesMarine) -reversion.register(ProposalOtherDetails, follow=['accreditations']) - -reversion.register(ProposalLogEntry, follow=['documents',]) -reversion.register(ProposalLogDocument) - -reversion.register(Park, follow=['proposals',]) -reversion.register(ProposalPark, follow=['activities','access_types', 'zones']) - -reversion.register(Park, follow=['proposals',]) -reversion.register(AccessType, follow=['proposals','proposalparkaccess_set', 'vehicles']) - -reversion.register(Activity, follow=['proposalparkactivity_set','proposalparkzoneactivity_set', 'proposaltrailsectionactivity_set']) -reversion.register(ProposalParkActivity) - -reversion.register(Zone, follow=['proposal_zones']) -reversion.register(ProposalParkZone, follow=['park_activities']) -reversion.register(ProposalParkZoneActivity, follow=['proposalparkzoneactivity_set']) - -reversion.register(Trail, follow=['proposals']) -reversion.register(ProposalTrail, follow=['sections']) - -reversion.register(ProposalTrailSection, follow=['trail_activities']) -reversion.register(Section, follow=['proposal_trails']) - -reversion.register(ProposalTrailSectionActivity) -reversion.register(AmendmentReason, follow=['amendmentrequest_set']) -reversion.register(AmendmentRequest) -reversion.register(Assessment) -reversion.register(ProposalDeclinedDetails) -reversion.register(ProposalOnHold) -reversion.register(ProposalStandardRequirement, follow=['proposalrequirement_set']) -reversion.register(ProposalRequirement, follow=['compliance_requirement']) -reversion.register(ReferralRecipientGroups, follow=['commercialoperator_referral_groups']) -reversion.register(QAOfficerGroup, follow=['qaofficer_groups']) -reversion.register(QAOfficerReferral) -reversion.register(QAOfficerDocument, follow=['qaofficer_referral_document']) -reversion.register(ApplicationType, follow=['helppage_set']) -reversion.register(HelpPage) - -#--------------------------------------------------------------------------------------------------- -# compliances/models.py - -import reversion -reversion.register(Compliance, follow=['documents', 'action_logs', 'comms_logs', 'comprequest_set']) -reversion.register(ComplianceDocument) -reversion.register(ComplianceUserAction) -reversion.register(ComplianceLogEntry, follow=['documents']) -reversion.register(ComplianceLogDocument) -reversion.register(CompRequest) -reversion.register(ComplianceAmendmentReason, follow=['complianceamendmentrequest_set']) -reversion.register(ComplianceAmendmentRequest) - -#--------------------------------------------------------------------------------------------------- -# approvals/models.py - -import reversion -reversion.register(Approval, follow=['compliances', 'documents', 'comms_logs', 'action_logs']) -reversion.register(ApprovalDocument, follow=['licence_document', 'cover_letter_document', 'renewal_document']) -reversion.register(ApprovalLogEntry, follow=['documents']) -reversion.register(ApprovalLogDocument) -reversion.register(ApprovalUserAction) - -#--------------------------------------------------------------------------------------------------- -# organisations/models.py - -import reversion -reversion.register(ledger_organisation, follow=['organisation_set']) -reversion.register(Organisation, follow=['org_approvals', 'contacts', 'userdelegation_set', 'action_logs', 'comms_logs']) -reversion.register(OrganisationContact) -reversion.register(OrganisationAction) -reversion.register(OrganisationLogEntry, follow=['documents']) -reversion.register(OrganisationLogDocument) -reversion.register(OrganisationRequest, follow=['action_logs', 'organisationrequestdeclineddetails_set', 'comms_logs']) -reversion.register(OrganisationAccessGroup) -reversion.register(OrganisationRequestUserAction) -reversion.register(OrganisationRequestDeclinedDetails) -reversion.register(OrganisationRequestLogDocument) -reversion.register(OrganisationRequestLogEntry, follow=['documents']) -reversion.register(UserDelegation) - -#--------------------------------------------------------------------------------------------------- -# main/models.py - -import reversion -reversion.register(Region) -reversion.register(District, follow=['districts', 'parks']) -reversion.register(AccessType) -reversion.register(ActivityType) -reversion.register(ActivityCategory, follow=['activities']) -reversion.register(Activity, follow=['park_set', 'zone_set', 'trail_set', 'requireddocument_set']) -reversion.register(Park, follow=['zones', 'requireddocument_set']) -reversion.register(Zone) -reversion.register(Trail, follow=['sections']) -reversion.register(Section) -reversion.register(RequiredDocument) -reversion.register(ApplicationType, follow=['tenure_app_types]) -reversion.register(ActivityMatrix) -reversion.register(Tenure) -reversion.register(Question) -reversion.register(UserAction) -reversion.register(CommunicationsLogEntry) -reversion.register(Document) -reversion.register(SystemMaintenance) diff --git a/commercialoperator/components/proposals/serializers.py b/commercialoperator/components/proposals/serializers.py deleted file mode 100755 index ee85cfb931..0000000000 --- a/commercialoperator/components/proposals/serializers.py +++ /dev/null @@ -1,1075 +0,0 @@ -from django.conf import settings -from ledger.accounts.models import EmailUser,Address -from commercialoperator.components.proposals.models import ( - ProposalType, - Proposal, - ProposalUserAction, - ProposalLogEntry, - Referral, - ProposalRequirement, - ProposalStandardRequirement, - ProposalDeclinedDetails, - AmendmentRequest, - AmendmentReason, - ProposalApplicantDetails, - ProposalActivitiesLand, - ProposalActivitiesMarine, - ProposalPark, - ProposalParkActivity, - Vehicle, - Vessel, - ProposalTrail, - QAOfficerReferral, - ProposalParkAccess, - ProposalTrailSection, - ProposalTrailSectionActivity, - ProposalParkZoneActivity, - ProposalParkZone, - ProposalOtherDetails, - ProposalAccreditation, - ChecklistQuestion, - ProposalAssessmentAnswer, - ProposalAssessment, - RequirementDocument, - ) -from commercialoperator.components.organisations.models import ( - Organisation - ) -from commercialoperator.components.main.serializers import CommunicationLogEntrySerializer, ParkSerializer, ActivitySerializer, AccessTypeSerializer, TrailSerializer -from commercialoperator.components.organisations.serializers import OrganisationSerializer -from commercialoperator.components.users.serializers import UserAddressSerializer, DocumentSerializer -from rest_framework import serializers -from django.db.models import Q -from reversion.models import Version - -class ProposalTypeSerializer(serializers.ModelSerializer): - activities = serializers.SerializerMethodField() - class Meta: - model = ProposalType - fields = ( - 'id', - 'schema', - 'activities' - ) - - - def get_activities(self,obj): - return obj.activities.names() - -class EmailUserSerializer(serializers.ModelSerializer): - class Meta: - model = EmailUser - fields = ('id','email','first_name','last_name','title','organisation') - -class EmailUserAppViewSerializer(serializers.ModelSerializer): - residential_address = UserAddressSerializer() - identification = DocumentSerializer() - - class Meta: - model = EmailUser - fields = ('id', - 'email', - 'first_name', - 'last_name', - 'dob', - 'title', - 'organisation', - 'residential_address', - 'identification', - 'email', - 'phone_number', - 'mobile_number',) - -class ProposalApplicantDetailsSerializer(serializers.ModelSerializer): - class Meta: - model = ProposalApplicantDetails - fields = ('id','first_name') - -class ProposalActivitiesLandSerializer(serializers.ModelSerializer): - class Meta: - model = ProposalActivitiesLand - fields = ('id','activities_land') - -class ProposalActivitiesMarineSerializer(serializers.ModelSerializer): - class Meta: - model = ProposalActivitiesMarine - fields = ('id','activities_marine') - -#class ParkEntrySerializer(serializers.ModelSerializer): -# class Meta: -# model = ParkEntry -# fields = '__all__' - -class ProposalParkActivitySerializer(serializers.ModelSerializer): - activity=ActivitySerializer() - #park_entry=ParkEntrySerializer() - class Meta: - model = ProposalParkActivity - fields = '__all__' - -class ProposalParkAccessSerializer(serializers.ModelSerializer): - access_type=AccessTypeSerializer() - class Meta: - model = ProposalParkAccess - fields = '__all__' - -class ProposalParkZoneActivitySerializer(serializers.ModelSerializer): - #activities=ProposalTrailSectionActivitySerializer(many=True) - class Meta: - model = ProposalParkZoneActivity - fields = ('activity',) - #fields = '__all__' - -class ProposalParkZoneSerializer(serializers.ModelSerializer): - # trail=TrailSerializer() - # sections=ProposalTrailSectionSerializer() - park_activities=ProposalParkZoneActivitySerializer(many=True) - class Meta: - model = ProposalParkZone - fields = ('zone','access_point','park_activities') - #fields = '__all__' - -class ProposalParkSerializer(serializers.ModelSerializer): - park=ParkSerializer() - land_activities=ProposalParkActivitySerializer(many=True) - #marine_activities=ProposalParkActivitySerializer(many=True) - zones=ProposalParkZoneSerializer(many=True) - access_types=ProposalParkAccessSerializer(many=True) - class Meta: - model = ProposalPark - fields = '__all__' - -class SaveProposalParkSerializer(serializers.ModelSerializer): - #park=ParkSerializer() - class Meta: - model = ProposalPark - fields = '__all__' - -class ProposalTrailSectionActivitySerializer(serializers.ModelSerializer): - #activities=ProposalTrailSectionActivitySerializer(many=True) - class Meta: - model = ProposalTrailSectionActivity - fields = ('activity',) - #fields = '__all__' - -class ProposalTrailSectionSerializer(serializers.ModelSerializer): - # trail=TrailSerializer() - # sections=ProposalTrailSectionSerializer() - trail_activities=ProposalTrailSectionActivitySerializer(many=True) - class Meta: - model = ProposalTrailSection - fields = ('section','trail_activities') - #fields = '__all__' - -class ProposalTrailSerializer(serializers.ModelSerializer): - trail=TrailSerializer() - sections=ProposalTrailSectionSerializer(many=True) - #land_activities=ProposalParkActivitySerializer(many=True) - class Meta: - model = ProposalTrail - fields = '__all__' - -class SaveProposalTrailSerializer(serializers.ModelSerializer): - #park=ParkSerializer() - class Meta: - model = ProposalTrail - fields = '__all__' - -class QAOfficerReferralSerializer(serializers.ModelSerializer): - processing_status = serializers.SerializerMethodField(read_only=True) - sent_by = serializers.SerializerMethodField(read_only=True) - qaofficer = serializers.SerializerMethodField(read_only=True) - class Meta: - model = QAOfficerReferral - fields = '__all__' - - def get_processing_status(self,obj): - return obj.get_processing_status_display() - - def get_sent_by(self,obj): - return obj.sent_by.get_full_name() if obj.sent_by else '' - - def get_qaofficer(self,obj): - return obj.qaofficer.get_full_name() if obj.qaofficer else '' - -class ProposalAccreditationSerializer(serializers.ModelSerializer): - accreditation_type_value= serializers.SerializerMethodField() - accreditation_expiry = serializers.DateField(format="%d/%m/%Y",input_formats=['%d/%m/%Y'],required=False,allow_null=True) - - class Meta: - model = ProposalAccreditation - #fields = '__all__' - fields=('id', - 'accreditation_type', - 'accreditation_expiry', - 'comments', - 'proposal_other_details', - 'accreditation_type_value' - ) - - def get_accreditation_type_value(self,obj): - return obj.get_accreditation_type_display() - - -class ProposalOtherDetailsSerializer(serializers.ModelSerializer): - #park=ParkSerializer() - #accreditation_type= serializers.SerializerMethodField() - #accreditation_expiry = serializers.DateField(format="%d/%m/%Y",input_formats=['%d/%m/%Y'],required=False,allow_null=True) - nominated_start_date = serializers.DateField(format="%d/%m/%Y",input_formats=['%d/%m/%Y'],required=False,allow_null=True) - insurance_expiry = serializers.DateField(format="%d/%m/%Y",input_formats=['%d/%m/%Y'],required=False,allow_null=True) - accreditations = ProposalAccreditationSerializer(many=True, read_only=True) - preferred_licence_period = serializers.CharField(allow_blank=True, allow_null=True) - proposed_end_date = serializers.DateField(format="%d/%m/%Y",read_only=True) - - class Meta: - model = ProposalOtherDetails - #fields = '__all__' - fields=( - #'accreditation_type', - #'accreditation_expiry', - 'id', - 'accreditations', - 'preferred_licence_period', - 'nominated_start_date', - 'insurance_expiry', - 'other_comments', - 'credit_fees', - 'credit_docket_books', - 'docket_books_number', - 'mooring', - 'proposed_end_date', - ) - # def get_accreditation_type(self,obj): - # return obj.get_accreditation_type_display() - -class SaveProposalOtherDetailsSerializer(serializers.ModelSerializer): - #park=ParkSerializer() - class Meta: - model = ProposalOtherDetails - #fields = '__all__' - fields=( - # 'accreditation_type', - # 'accreditation_expiry', - 'preferred_licence_period', - 'nominated_start_date', - 'insurance_expiry', - 'other_comments', - 'credit_fees', - 'credit_docket_books', - 'proposal', - ) -class ChecklistQuestionSerializer(serializers.ModelSerializer): - - class Meta: - model = ChecklistQuestion - #fields = '__all__' - fields=('id', - 'text', - 'answer_type', - ) -class ProposalAssessmentAnswerSerializer(serializers.ModelSerializer): - question=ChecklistQuestionSerializer(read_only=True) - class Meta: - model = ProposalAssessmentAnswer - fields = ('id', - 'question', - 'answer', - 'text_answer', - ) - -class ProposalAssessmentSerializer(serializers.ModelSerializer): - checklist=ProposalAssessmentAnswerSerializer(many=True, read_only=True) - - class Meta: - model = ProposalAssessment - fields = ('id', - 'completed', - 'submitter', - 'referral_assessment', - 'referral_group', - 'referral_group_name', - 'checklist' - ) - - -class BaseProposalSerializer(serializers.ModelSerializer): - #org_applicant = OrganisationSerializer() - readonly = serializers.SerializerMethodField(read_only=True) - documents_url = serializers.SerializerMethodField() - proposal_type = serializers.SerializerMethodField() - allowed_assessors = EmailUserSerializer(many=True) - #qaofficer_referral = QAOfficerReferralSerializer(required=False) - qaofficer_referrals = QAOfficerReferralSerializer(many=True) - - #applicant_details = ProposalApplicantDetailsSerializer(required=False) - activities_land = ProposalActivitiesLandSerializer(required=False) - activities_marine = ProposalActivitiesMarineSerializer(required=False) - land_parks=ProposalParkSerializer(many=True) - marine_parks=ProposalParkSerializer(many=True) - trails=ProposalTrailSerializer(many=True) - other_details=ProposalOtherDetailsSerializer() - - get_history = serializers.ReadOnlyField() - is_qa_officer = serializers.SerializerMethodField() - fee_invoice_url = serializers.SerializerMethodField() - land_access = serializers.SerializerMethodField() - land_activities = serializers.SerializerMethodField() - trail_activities = serializers.SerializerMethodField() - trail_section_activities = serializers.SerializerMethodField() - -# def __init__(self, *args, **kwargs): -# user = kwargs['context']['request'].user -# -# super(BaseProposalSerializer, self).__init__(*args, **kwargs) -# self.fields['parent'].queryset = self.get_request(user) - - class Meta: - model = Proposal - fields = ( - 'id', - 'application_type', - 'activity', - 'approval_level', - 'title', - 'region', - 'district', - 'tenure', - #'assessor_data', - 'data', - 'schema', - 'customer_status', - 'processing_status', - 'review_status', - #'hard_copy', - 'applicant_type', - 'applicant', - 'org_applicant', - 'proxy_applicant', - 'submitter', - 'assigned_officer', - 'previous_application', - 'get_history', - 'lodgement_date', - 'modified_date', - 'documents', - 'requirements', - 'readonly', - 'can_user_edit', - 'can_user_view', - 'documents_url', - 'reference', - 'lodgement_number', - 'lodgement_sequence', - 'can_officer_process', - 'allowed_assessors', - 'proposal_type', - 'is_qa_officer', - 'qaofficer_referrals', - 'pending_amendment_request', - 'is_amendment_proposal', - - # tab field models - 'applicant_details', - 'other_details', - 'activities_land', - 'activities_marine', - 'land_access', - 'land_activities', - 'trail_activities', - 'trail_section_activities', - 'land_parks', - 'marine_parks', - 'trails', - 'training_completed', - 'fee_invoice_url', - 'fee_paid', - - ) - read_only_fields=('documents',) - - def get_documents_url(self,obj): - return '/media/{}/proposals/{}/documents/'.format(settings.MEDIA_APP_DIR, obj.id) - - def get_readonly(self,obj): - return False - - def get_processing_status(self,obj): - return obj.get_processing_status_display() - - def get_review_status(self,obj): - return obj.get_review_status_display() - - def get_customer_status(self,obj): - return obj.get_customer_status_display() - - def get_proposal_type(self,obj): - return obj.get_proposal_type_display() - - def get_is_qa_officer(self,obj): - request = self.context['request'] - return request.user.email in obj.qa_officers() - - def get_fee_invoice_url(self,obj): - return '/cols/payments/invoice-pdf/{}'.format(obj.fee_invoice_reference) if obj.fee_paid else None - - def get_land_access(self,obj): - return obj.land_parks.filter(access_types__isnull=False).values_list('access_types__access_type_id', flat=True).distinct() - - def get_land_activities(self,obj): - return obj.land_parks.filter(activities__isnull=False).values_list('activities__activity_id', flat=True).distinct() - - def get_trail_activities(self,obj): - return ProposalTrailSectionActivity.objects.filter(trail_section__proposal_trail__proposal=obj.id).values_list('activity',flat=True).distinct() - - def get_trail_section_activities(self,obj): - return obj.trails.all().values_list('trail_id', flat=True) - -#Not used anymore -class DTProposalSerializer(BaseProposalSerializer): - submitter = EmailUserSerializer() - applicant = serializers.CharField(source='applicant.organisation.name') - processing_status = serializers.SerializerMethodField(read_only=True) - review_status = serializers.SerializerMethodField(read_only=True) - customer_status = serializers.SerializerMethodField(read_only=True) - assigned_officer = serializers.CharField(source='assigned_officer.get_full_name', allow_null=True) - - application_type = serializers.CharField(source='application_type.name', read_only=True) - region = serializers.CharField(source='region.name', read_only=True) - district = serializers.CharField(source='district.name', read_only=True) - #tenure = serializers.CharField(source='tenure.name', read_only=True) - - -class ListProposalSerializer(BaseProposalSerializer): - submitter = EmailUserSerializer() - applicant = serializers.CharField(read_only=True) - processing_status = serializers.SerializerMethodField(read_only=True) - review_status = serializers.SerializerMethodField(read_only=True) - customer_status = serializers.SerializerMethodField(read_only=True) - #assigned_officer = serializers.CharField(source='assigned_officer.get_full_name') - assigned_officer = serializers.SerializerMethodField(read_only=True) - - application_type = serializers.CharField(source='application_type.name', read_only=True) - #region = serializers.CharField(source='region.name', read_only=True) - #district = serializers.CharField(source='district.name', read_only=True) - region = serializers.SerializerMethodField(read_only=True) - district = serializers.SerializerMethodField(read_only=True) - - #tenure = serializers.CharField(source='tenure.name', read_only=True) - assessor_process = serializers.SerializerMethodField(read_only=True) - qaofficer_referrals = QAOfficerReferralSerializer(many=True) - fee_invoice_url = serializers.SerializerMethodField() - - class Meta: - model = Proposal - fields = ( - 'id', - 'application_type', - 'activity', - 'approval_level', - 'title', - 'region', - 'district', - 'tenure', - 'customer_status', - 'processing_status', - 'review_status', - 'applicant', - 'proxy_applicant', - 'submitter', - 'assigned_officer', - 'previous_application', - 'get_history', - 'lodgement_date', - 'modified_date', - 'readonly', - 'can_user_edit', - 'can_user_view', - 'reference', - 'lodgement_number', - 'lodgement_sequence', - 'can_officer_process', - 'assessor_process', - 'allowed_assessors', - 'proposal_type', - 'qaofficer_referrals', - 'is_qa_officer', - 'fee_invoice_url', - 'fee_invoice_reference', - 'fee_paid', - ) - # the serverSide functionality of datatables is such that only columns that have field 'data' defined are requested from the serializer. We - # also require the following additional fields for some of the mRender functions - datatables_always_serialize = ( - 'id', - 'activity', - 'title', - 'region', - 'customer_status', - 'processing_status', - 'applicant', - 'submitter', - 'assigned_officer', - 'lodgement_date', - 'can_user_edit', - 'can_user_view', - 'reference', - 'lodgement_number', - 'can_officer_process', - 'assessor_process', - 'allowed_assessors', - 'fee_invoice_url', - 'fee_invoice_reference', - 'fee_paid', - ) - - def get_assigned_officer(self,obj): - if obj.assigned_officer: - return obj.assigned_officer.get_full_name() - return None - - def get_region(self,obj): - if obj.region: - return obj.region.name - return None - - def get_district(self,obj): - if obj.district: - return obj.district.name - return None - - def get_assessor_process(self,obj): - # Check if currently logged in user has access to process the proposal - request = self.context['request'] - user = request.user - if obj.can_officer_process: - '''if (obj.assigned_officer and obj.assigned_officer == user) or (user in obj.allowed_assessors): - return True''' - if obj.assigned_officer: - if obj.assigned_officer == user: - return True - elif user in obj.allowed_assessors: - return True - return False - - def get_is_qa_officer(self,obj): - request = self.context['request'] - return request.user.email in obj.qa_officers() - - def get_fee_invoice_url(self,obj): - return '/cols/payments/invoice-pdf/{}'.format(obj.fee_invoice_reference) if obj.fee_paid else None - -class ProposalSerializer(BaseProposalSerializer): - submitter = serializers.CharField(source='submitter.get_full_name') - processing_status = serializers.SerializerMethodField(read_only=True) - review_status = serializers.SerializerMethodField(read_only=True) - customer_status = serializers.SerializerMethodField(read_only=True) - - application_type = serializers.CharField(source='application_type.name', read_only=True) - region = serializers.CharField(source='region.name', read_only=True) - district = serializers.CharField(source='district.name', read_only=True) - - #tenure = serializers.CharField(source='tenure.name', read_only=True) - - def get_readonly(self,obj): - return obj.can_user_view - -#class ProposalApplicantDetailsSerializer(serializers.ModelSerializer): -# -# class Meta: -# model = ProposalApplicantDetails -# fields = ( -# 'id', -# 'first_name', -# ) - -class SaveProposalSerializer(BaseProposalSerializer): - assessor_data = serializers.JSONField(required=False) - #applicant_details = ProposalApplicantDetailsSerializer(required=False) - #other_details= SaveProposalOtherDetailsSerializer() - - class Meta: - model = Proposal - fields = ( - 'id', - 'application_type', - 'activity', - 'approval_level', - 'title', - 'region', - 'district', - 'tenure', - 'data', - 'assessor_data', - 'comment_data', - 'schema', - 'customer_status', - 'processing_status', - 'review_status', - #'hard_copy', - 'applicant_type', - 'applicant', - 'org_applicant', - 'proxy_applicant', - 'submitter', - 'assigned_officer', - 'previous_application', - 'lodgement_date', - 'documents', - 'requirements', - 'readonly', - 'can_user_edit', - 'can_user_view', - 'reference', - 'lodgement_number', - 'lodgement_sequence', - 'can_officer_process', - 'applicant_details', - #'activities_land', - #'activities_marine', - #'other_details', - ) - read_only_fields=('documents','requirements',) - - - -class ApplicantSerializer(serializers.ModelSerializer): - from commercialoperator.components.organisations.serializers import OrganisationAddressSerializer - address = OrganisationAddressSerializer(read_only=True) - #address = OrganisationAddressSerializer() - class Meta: - model = Organisation - fields = ( - 'id', - 'name', - 'abn', - 'address', - 'email', - 'phone_number', - ) - - -class ProposalReferralSerializer(serializers.ModelSerializer): - #referral = serializers.CharField(source='referral.get_full_name') - referral = serializers.CharField(source='referral_group.name') - processing_status = serializers.CharField(source='get_processing_status_display') - class Meta: - model = Referral - fields = '__all__' - -class ProposalDeclinedDetailsSerializer(serializers.ModelSerializer): - class Meta: - model = ProposalDeclinedDetails - fields = '__all__' - -class ProposalParkSerializer(BaseProposalSerializer): - applicant = ApplicantSerializer() - processing_status = serializers.SerializerMethodField(read_only=True) - customer_status = serializers.SerializerMethodField(read_only=True) - submitter = serializers.CharField(source='submitter.get_full_name') - application_type = serializers.CharField(source='application_type.name', read_only=True) - licence_number = serializers.SerializerMethodField(read_only=True) - licence_number_id = serializers.SerializerMethodField(read_only=True) - land_parks=ProposalParkSerializer(source='land_parks_exclude_free', many=True) - - class Meta: - model = Proposal - fields = ( - 'id', - 'licence_number', - 'licence_number_id', - 'application_type', - 'approval_level', - 'title', - 'customer_status', - 'processing_status', - 'applicant', - 'proxy_applicant', - 'submitter', - 'lodgement_number', - #'activities_land', - #'activities_marine', - #'land_parks_exclude_free', - 'land_parks', - #'marine_parks', - #'trails', - ) - #read_only_fields=('documents','requirements') - #read_only_fields = '__all__' - - def get_licence_number(self,obj): - return obj.approval.lodgement_number - - def get_licence_number_id(self,obj): - return obj.approval.id - - def get_land_parks(self,obj): - """ exlude parks with free admission """ - return obj.land_parks_exclude_free - -class InternalProposalSerializer(BaseProposalSerializer): - #applicant = ApplicantSerializer() - applicant = serializers.CharField(read_only=True) - org_applicant = OrganisationSerializer() - processing_status = serializers.SerializerMethodField(read_only=True) - review_status = serializers.SerializerMethodField(read_only=True) - customer_status = serializers.SerializerMethodField(read_only=True) - #submitter = serializers.CharField(source='submitter.get_full_name') - submitter = EmailUserAppViewSerializer() - proposaldeclineddetails = ProposalDeclinedDetailsSerializer() - # - assessor_mode = serializers.SerializerMethodField() - can_edit_activities = serializers.SerializerMethodField() - current_assessor = serializers.SerializerMethodField() - assessor_data = serializers.SerializerMethodField() - latest_referrals = ProposalReferralSerializer(many=True) - allowed_assessors = EmailUserSerializer(many=True) - approval_level_document = serializers.SerializerMethodField() - application_type = serializers.CharField(source='application_type.name', read_only=True) - region = serializers.CharField(source='region.name', read_only=True) - district = serializers.CharField(source='district.name', read_only=True) - #tenure = serializers.CharField(source='tenure.name', read_only=True) - qaofficer_referrals = QAOfficerReferralSerializer(many=True) - reversion_ids = serializers.SerializerMethodField() - assessor_assessment=ProposalAssessmentSerializer(read_only=True) - referral_assessments=ProposalAssessmentSerializer(read_only=True, many=True) - fee_invoice_url = serializers.SerializerMethodField() - #selected_trails_activities=serializers.SerializerMethodField() - #selected_parks_activities=serializers.SerializerMethodField() - #marine_parks_activities=serializers.SerializerMethodField() - - class Meta: - model = Proposal - fields = ( - 'id', - 'application_type', - 'activity', - 'approval_level', - 'approval_level_document', - 'region', - 'district', - 'tenure', - 'title', - 'data', - 'schema', - 'customer_status', - 'processing_status', - 'review_status', - #'hard_copy', - 'applicant', - 'org_applicant', - 'proxy_applicant', - 'submitter', - 'applicant_type', - 'assigned_officer', - 'assigned_approver', - 'previous_application', - 'get_history', - 'lodgement_date', - 'modified_date', - 'documents', - 'requirements', - 'readonly', - 'can_user_edit', - 'can_user_view', - 'documents_url', - 'assessor_mode', - 'current_assessor', - 'assessor_data', - 'comment_data', - 'latest_referrals', - 'allowed_assessors', - 'proposed_issuance_approval', - 'proposed_decline_status', - 'proposaldeclineddetails', - 'permit', - 'reference', - 'lodgement_number', - 'lodgement_sequence', - 'can_officer_process', - 'proposal_type', - 'qaofficer_referrals', - # tab field models - 'applicant_details', - 'other_details', - 'activities_land', - 'land_access', - 'land_access', - 'trail_activities', - 'trail_section_activities', - 'activities_marine', - 'land_parks', - 'marine_parks', - 'trails', - 'training_completed', - 'can_edit_activities', - #Following 3 are variable to store selected parks and activities at frontend - #'selected_parks_activities', - #'selected_trails_activities', - #'marine_parks_activities', - 'reversion_ids', - 'assessor_assessment', - 'referral_assessments', - 'fee_invoice_url', - 'fee_paid' - ) - read_only_fields=('documents','requirements') - - def get_approval_level_document(self,obj): - if obj.approval_level_document is not None: - return [obj.approval_level_document.name,obj.approval_level_document._file.url] - else: - return obj.approval_level_document - - def get_assessor_mode(self,obj): - # TODO check if the proposal has been accepted or declined - request = self.context['request'] - user = request.user._wrapped if hasattr(request.user,'_wrapped') else request.user - return { - 'assessor_mode': True, - 'has_assessor_mode': obj.has_assessor_mode(user), - 'assessor_can_assess': obj.can_assess(user), - 'assessor_level': 'assessor', - 'assessor_box_view': obj.assessor_comments_view(user) - } - - def get_can_edit_activities(self,obj): - request = self.context['request'] - user = request.user._wrapped if hasattr(request.user,'_wrapped') else request.user - return obj.can_edit_activities(user) - - def get_readonly(self,obj): - return True - - def get_current_assessor(self,obj): - return { - 'id': self.context['request'].user.id, - 'name': self.context['request'].user.get_full_name(), - 'email': self.context['request'].user.email - } - - def get_assessor_data(self,obj): - return obj.assessor_data - - def get_reversion_ids(self,obj): - return obj.reversion_ids[:5] - - def get_fee_invoice_url(self,obj): - return '/cols/payments/invoice-pdf/{}'.format(obj.fee_invoice_reference) if obj.fee_paid else None - - def get_selected_parks_activities(self,obj): - return [] - - def get_selected_trails_activities(self,obj): - return [] - - def get_marine_parks_activities(self,obj): - return [] - - -class ReferralProposalSerializer(InternalProposalSerializer): - def get_assessor_mode(self,obj): - # TODO check if the proposal has been accepted or declined - request = self.context['request'] - user = request.user._wrapped if hasattr(request.user,'_wrapped') else request.user - try: - referral = Referral.objects.get(proposal=obj,referral=user) - except: - referral = None - return { - 'assessor_mode': True, - 'assessor_can_assess': referral.can_assess_referral(user) if referral else None, - 'assessor_level': 'referral', - 'assessor_box_view': obj.assessor_comments_view(user) - } - -class ReferralSerializer(serializers.ModelSerializer): - processing_status = serializers.CharField(source='get_processing_status_display') - latest_referrals = ProposalReferralSerializer(many=True) - can_be_completed = serializers.BooleanField() - can_process=serializers.SerializerMethodField() - referral_assessment=ProposalAssessmentSerializer(read_only=True) - - - class Meta: - model = Referral - fields = '__all__' - - def __init__(self,*args,**kwargs): - super(ReferralSerializer, self).__init__(*args, **kwargs) - self.fields['proposal'] = ReferralProposalSerializer(context={'request':self.context['request']}) - - def get_can_process(self,obj): - request = self.context['request'] - user = request.user._wrapped if hasattr(request.user,'_wrapped') else request.user - return obj.can_process(user) - -class ProposalUserActionSerializer(serializers.ModelSerializer): - who = serializers.CharField(source='who.get_full_name') - class Meta: - model = ProposalUserAction - fields = '__all__' - -class ProposalLogEntrySerializer(CommunicationLogEntrySerializer): - documents = serializers.SerializerMethodField() - class Meta: - model = ProposalLogEntry - fields = '__all__' - read_only_fields = ( - 'customer', - ) - - def get_documents(self,obj): - return [[d.name,d._file.url] for d in obj.documents.all()] - -class SendReferralSerializer(serializers.Serializer): - #email = serializers.EmailField() - email_group = serializers.CharField() - text = serializers.CharField(allow_blank=True) - -class DTReferralSerializer(serializers.ModelSerializer): - processing_status = serializers.CharField(source='proposal.get_processing_status_display') - referral_status = serializers.CharField(source='get_processing_status_display') - proposal_lodgement_date = serializers.CharField(source='proposal.lodgement_date') - proposal_lodgement_number = serializers.CharField(source='proposal.lodgement_number') - submitter = serializers.SerializerMethodField() - region = serializers.CharField(source='region.name', read_only=True) - #referral = EmailUserSerializer() - referral = serializers.CharField(source='referral_group.name') - document = serializers.SerializerMethodField() - class Meta: - model = Referral - fields = ( - 'id', - 'region', - 'activity', - 'title', - 'applicant', - 'submitter', - 'processing_status', - 'referral_status', - 'lodged_on', - 'proposal', - 'can_be_processed', - 'referral', - 'proposal_lodgement_date', - 'proposal_lodgement_number', - 'referral_text', - 'document', - ) - - def get_submitter(self,obj): - return EmailUserSerializer(obj.proposal.submitter).data - - def get_document(self,obj): - docs = [[d.name,d._file.url] for d in obj.referral_documents.all()] - return docs[0] if docs else None - -class RequirementDocumentSerializer(serializers.ModelSerializer): - class Meta: - model = RequirementDocument - fields = ('id', 'name', '_file') - #fields = '__all__' - -class ProposalRequirementSerializer(serializers.ModelSerializer): - due_date = serializers.DateField(input_formats=['%d/%m/%Y'],required=False,allow_null=True) - can_referral_edit=serializers.SerializerMethodField() - requirement_documents = RequirementDocumentSerializer(many=True, read_only=True) - class Meta: - model = ProposalRequirement - fields = ( - 'id', - 'due_date', - 'free_requirement', - 'standard_requirement', - 'standard','order', - 'proposal', - 'recurrence', - 'recurrence_schedule', - 'recurrence_pattern', - 'requirement', - 'is_deleted', - 'copied_from', - 'referral_group', - 'can_referral_edit', - 'requirement_documents' - ) - read_only_fields = ('order','requirement', 'copied_from') - - def get_can_referral_edit(self,obj): - request = self.context['request'] - user = request.user._wrapped if hasattr(request.user,'_wrapped') else request.user - return obj.can_referral_edit(user) - -class ProposalStandardRequirementSerializer(serializers.ModelSerializer): - class Meta: - model = ProposalStandardRequirement - fields = ('id','code','text') - -class ProposedApprovalSerializer(serializers.Serializer): - expiry_date = serializers.DateField(input_formats=['%d/%m/%Y']) - start_date = serializers.DateField(input_formats=['%d/%m/%Y']) - details = serializers.CharField() - cc_email = serializers.CharField(required=False,allow_null=True) - -class PropedDeclineSerializer(serializers.Serializer): - reason = serializers.CharField() - cc_email = serializers.CharField(required=False) - -class OnHoldSerializer(serializers.Serializer): - comment = serializers.CharField() - - -class AmendmentRequestSerializer(serializers.ModelSerializer): - #reason = serializers.SerializerMethodField() - - class Meta: - model = AmendmentRequest - fields = '__all__' - - #def get_reason (self,obj): - #return obj.get_reason_display() - #return obj.reason.reason - -class AmendmentRequestDisplaySerializer(serializers.ModelSerializer): - reason = serializers.SerializerMethodField() - - class Meta: - model = AmendmentRequest - fields = '__all__' - - def get_reason (self,obj): - #return obj.get_reason_display() - return obj.reason.reason if obj.reason else None - - -class SearchKeywordSerializer(serializers.Serializer): - number = serializers.CharField() - id = serializers.IntegerField() - type = serializers.CharField() - applicant = serializers.CharField() - #text = serializers.CharField(required=False,allow_null=True) - text = serializers.JSONField(required=False) - -class SearchReferenceSerializer(serializers.Serializer): - id = serializers.IntegerField() - type = serializers.CharField() - -class VehicleSerializer(serializers.ModelSerializer): - access_type= AccessTypeSerializer() - rego_expiry=serializers.DateField(format="%d/%m/%Y") - class Meta: - model = Vehicle - fields = ('id', 'capacity', 'rego', 'license', 'access_type', 'rego_expiry', 'proposal') - -class VesselSerializer(serializers.ModelSerializer): - class Meta: - model = Vessel - fields = '__all__' - -class SaveVehicleSerializer(serializers.ModelSerializer): - #access_type= AccessTypeSerializer() - rego_expiry = serializers.DateField(input_formats=['%d/%m/%Y'], allow_null=True) - class Meta: - model = Vehicle - fields = ('id', 'capacity', 'rego', 'license', 'access_type', 'rego_expiry', 'proposal') - diff --git a/commercialoperator/components/proposals/signals.py b/commercialoperator/components/proposals/signals.py deleted file mode 100755 index cbc5a57b3c..0000000000 --- a/commercialoperator/components/proposals/signals.py +++ /dev/null @@ -1,66 +0,0 @@ -from django.db.models.signals import post_delete, pre_save, post_save, m2m_changed -from django.core.exceptions import ValidationError -from django.dispatch import receiver -from ledger.accounts.models import EmailUser -from commercialoperator.components.proposals.models import ( - ProposalAssessorGroup, - Referral, - Proposal -) - -import logging -logger = logging.getLogger(__name__) - - -class ProposalAssessorGroupListener(object): - """ - Event listener for ProposalAssessorGroup - """ - - @staticmethod - @receiver(pre_save, sender=ProposalAssessorGroup) - def _pre_save(sender, instance, **kwargs): - if instance.pk: - original_instance = ProposalAssessorGroup.objects.get(pk=instance.pk) - setattr(instance, "_original_instance", original_instance) - - elif hasattr(instance, "_original_instance"): - delattr(instance, "_original_instance") - instance.full_clean() - - @staticmethod - @receiver(m2m_changed, sender=ProposalAssessorGroup.members.through) - def members_changed(sender,instance, action,**kwargs): - if action == 'pre_remove': - for o in EmailUser.objects.filter(id__in=kwargs.get('pk_set')): - if instance.member_is_assigned(o): - proposals = list(Proposal.objects.filter(assigned_officer_id=o.id).values_list('id', flat=True)) - logger.info('{0} deleted from assessors group. {0} is currently assigned to proposal_id__in={1}'.format(o.email, proposals)) - #raise ValidationError('{} is currently assigned to a proposal(s)'.format(o.email)) - -class ReferralListener(object): - """ - Event listener for Referral - """ - - @staticmethod - @receiver(pre_save, sender=Referral) - def _pre_save(sender, instance, **kwargs): - if instance.pk: - original_instance = Referral.objects.get(pk=instance.pk) - setattr(instance, "_original_instance", original_instance) - - elif hasattr(instance, "_original_instance"): - delattr(instance, "_original_instance") - - @staticmethod - @receiver(post_save, sender=Referral) - def _post_save(sender, instance, **kwargs): - original_instance = getattr(instance, "_original_instance") if hasattr(instance, "_original_instance") else None - if original_instance: - # Check if the proposal attached to the referral outstanding referrals - outstanding = instance.proposal.referrals.filter(processing_status='with_referral') - if len(outstanding) == 0: - instance.proposal.processing_status = 'with_assessor' - instance.proposal.save() - diff --git a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_amendment_notification.html b/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_amendment_notification.html deleted file mode 100755 index 981784aeeb..0000000000 --- a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_amendment_notification.html +++ /dev/null @@ -1,22 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} - Your Application {{ proposal.lodgement_number }} for a commercial operations licence has been returned to you for further information. - - {% if reason %} -

- Amendment Reason: {{ reason }} -

- {% endif %} - - {% if amendment_request_text %} -

Amendment details:
{{ amendment_request_text }}

- {% endif %} -

- Please login to your account to complete the application. -

-

You will receive a notification email if there is any incomplete information or documents missing from the application.

- - - -{% endblock %} diff --git a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_amendment_notification.txt b/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_amendment_notification.txt deleted file mode 100755 index 89ecbe0df0..0000000000 --- a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_amendment_notification.txt +++ /dev/null @@ -1,22 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.txt' %} - -{% block content %} - Your Application {{ proposal.lodgement_number }} has been reviewed and requires an amendment before further assessment. - - {% if reason %} -

- Amendment Reason: {{ reason }} -

- {% endif %} - - {% if amendment_request_text %} -

Amendment details:
{{ amendment_request_text }}

- {% endif %} - - Please login to your account to complete the application. - - You will receive a notification email if there is any incomplete information or documents missing from the application. - - - -{% endblock %} diff --git a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_approval_notification.html b/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_approval_notification.html deleted file mode 100755 index a791b7d2d3..0000000000 --- a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_approval_notification.html +++ /dev/null @@ -1,32 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} - - - -

Your licence to conduct commercial operations on Conservation and Land Management Act 1984 has been approved and expires on {{proposal.approval.expiry_date}}. A copy of your licence is attached to this email and can be accessed in the Commercial Operator Licensing System (COLS) under your account, click here to login.

- -

Parks and Activities
- The activities and parks you are permitted to operate within are listed in Schedule 1 of your licence.

- -

Commercial Operator Handbook - Licence Conditions
- All operators are required to adhere to the licence conditions listed in the Commercial Operator Handbook (2019). A copy of the handbook can be downloaded from the DBCA website here. Please ensure you have a copy of this handbook on hand either in hardcopy or an electronic version.

- -

Additional Licence Conditions
- Additional licence conditions are listed in schedule 2 of the licence, and are listed under the “Licence Requirements” section in COLS. You will need to login to your account and ensure you have completed all additional licence conditions by the due date by uploading the requested documents.

- -

If you have any enquiries or need assistance with the online system please contact a licensing office on {{settings.DEP_PHONE}} or email {{settings.SUPPORT_EMAIL}}

- - - -{% endblock %} diff --git a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_approval_notification.txt b/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_approval_notification.txt deleted file mode 100755 index 8b93cd191a..0000000000 --- a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_approval_notification.txt +++ /dev/null @@ -1,18 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.txt' %} - -{% block content %} - - Your licence to conduct commercial operations on Conservation and Land Management Act 1984 has been approved and expires on {{proposal.approval.expiry_date}}. A copy of your licence is attached to this email and can be accessed in the Commercial Operator Licensing System (COLS) under your account, click here to login. - - Parks and Activities - The activities and parks you are permitted to operate within are listed in Schedule 1 of your licence. - - Commercial Operator Handbook - Licence Conditions - All operators are required to adhere to the licence conditions listed in the Commercial Operator Handbook (2019). A copy of the handbook can be downloaded from the DBCA website here. Please ensure you have a copy of this handbook on hand either in hardcopy or an electronic version. - - Additional Licence Conditions - Additional licence conditions are listed in schedule 2 of the licence, and are listed under the “Licence Requirements” section in COLS. You will need to login to your account and ensure you have completed all additional licence conditions by the due date by uploading the requested documents. - - If you have any enquiries or need assistance with the online system please contact a licensing office on {{settings.DEP_PHONE}} or email {{settings.SUPPORT_EMAIL}} - -{% endblock %} diff --git a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_approver_approve_notification.html b/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_approver_approve_notification.html deleted file mode 100755 index d858616764..0000000000 --- a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_approver_approve_notification.html +++ /dev/null @@ -1,23 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} - The Application {{ proposal.lodgement_number }} has been assessed and has been recommended for approval. - - {% comment %} - {% if proposal.proposed_issuance_approval %} -

- Approved: -

-

Start date: {{ start_date }}

-

Expiry date: {{ expiry_date }}

-

Details: {{ details }}

- {% endif %} - {% endcomment %} - -

- You can access this Application using the following link: -

- Access Application - - -{% endblock %} diff --git a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_approver_approve_notification.txt b/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_approver_approve_notification.txt deleted file mode 100755 index ecaf8f8301..0000000000 --- a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_approver_approve_notification.txt +++ /dev/null @@ -1,12 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.txt' %} - -{% block content %} - The Application {{ proposal.lodgement_number }} has been assessed and has been recommended for approval. - -

- You can access this Application using the following link: -

- Access Application - - -{% endblock %} diff --git a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_approver_decline_notification.html b/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_approver_decline_notification.html deleted file mode 100755 index 5c7a930486..0000000000 --- a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_approver_decline_notification.html +++ /dev/null @@ -1,17 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} - Your Application {{ proposal.lodgement_number }} has been reviewed and has been recommended for decline. - {% if reason %} -

- Declined Reason: {{ reason }} -

- {% endif %} - -

- You can access this Application using the following link: -

- Access Application - - -{% endblock %} diff --git a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_approver_decline_notification.txt b/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_approver_decline_notification.txt deleted file mode 100755 index bafd5ee56b..0000000000 --- a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_approver_decline_notification.txt +++ /dev/null @@ -1,18 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.txt' %} - -{% block content %} - Your Application {{ proposal.lodgement_number }} has been reviewed and has been recommended for decline. - - {% if reason %} -

- Declined Reason: {{ reason }} -

- {% endif %} - -

- You can access this Application using the following link: -

- Access Application - - -{% endblock %} diff --git a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_approver_sendback_notification.html b/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_approver_sendback_notification.html deleted file mode 100755 index 80c6f03c78..0000000000 --- a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_approver_sendback_notification.html +++ /dev/null @@ -1,15 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} - The Application {{ proposal.lodgement_number }} has been sent back by approver. - -

Approver comments: {{ approver_comment }}

- - -

- You can access this Application using the following link: -

- Access Application - - -{% endblock %} diff --git a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_approver_sendback_notification.txt b/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_approver_sendback_notification.txt deleted file mode 100755 index 0644546c20..0000000000 --- a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_approver_sendback_notification.txt +++ /dev/null @@ -1,13 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.txt' %} - -{% block content %} - The Application {{ proposal.lodgement_number }} has been sent back by approver. - - Approver comments: {{ approver_comment }} - - You can access this Application using the following link: - - Access Application - - -{% endblock %} diff --git a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_decline_notification.html b/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_decline_notification.html deleted file mode 100755 index f7c485d34c..0000000000 --- a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_decline_notification.html +++ /dev/null @@ -1,10 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} - -

Your application for a commercial operations licence {{proposal.lodgement_number}} has been declined

-

For further information please login to your account.

- -

If you have any queries regarding this decision please contact a licensing officer on {{settings.DEP_PHONE}}, or email {{settings.SUPPORT_EMAIL}}

- -{% endblock %} diff --git a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_decline_notification.txt b/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_decline_notification.txt deleted file mode 100755 index 678445e2a3..0000000000 --- a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_decline_notification.txt +++ /dev/null @@ -1,10 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.txt' %} - -{% block content %} - - Your application for a commercial operations licence {{proposal.lodgement_number}} has been declined - For further information please login to your account. - - If you have any queries regarding this decision please contact a licensing officer on {{settings.DEP_PHONE}}, or email {{settings.SUPPORT_EMAIL}} - -{% endblock %} diff --git a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_external_submit_notification.html b/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_external_submit_notification.html deleted file mode 100755 index 31014d0bb9..0000000000 --- a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_external_submit_notification.html +++ /dev/null @@ -1,24 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} - Your Application for a commercial operations licence has been submitted, the application number is {{ proposal.lodgement_number }}

- - Submitter: {{ proposal.submitter.get_full_name }}
- Lodgement date: {{ proposal.lodgement_date }} - -

- It may take up to 2 weeks to process your application. -

- -

- You will receive a notification email if there is any incomplete information or documents missing from the application. -

-

If you would like to amend the application noew please contact a licensing office on {{settings.DEP_PHONE}} or email {{settings.SUPPORT_EMAIL}}

- - - - -{% endblock %} diff --git a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_external_submit_notification.txt b/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_external_submit_notification.txt deleted file mode 100755 index 31f9d7a5d6..0000000000 --- a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_external_submit_notification.txt +++ /dev/null @@ -1,19 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.txt' %} - -{% block content %} - Your Application for a commercial operations licence has been submitted, the application number is {{ proposal.lodgement_number }} - - Submitter: {{ proposal.submitter.get_full_name }} - Lodgement date: {{ proposal.lodgement_date }} - - - It may take up to 2 weeks to process your application. - - - - You will receive a notification email if there is any incomplete information or documents missing from the application. - - If you would like to amend the application noew please contact a licensing office on {{settings.DEP_PHONE}} or email {{settings.SUPPORT_EMAIL}} - - -{% endblock %} diff --git a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_qaofficer_complete_notification.html b/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_qaofficer_complete_notification.html deleted file mode 100755 index 0d9c614e2f..0000000000 --- a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_qaofficer_complete_notification.html +++ /dev/null @@ -1,8 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} -

A QA for Application {{proposal.lodgement_number}} has been completed ({{completed_by}}):

-

QA Officer Comments: {{comments}}

-

You can access this Application using the following link:

- Access Application -{% endblock %} diff --git a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_qaofficer_complete_notification.txt b/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_qaofficer_complete_notification.txt deleted file mode 100755 index 3cc2c698a0..0000000000 --- a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_qaofficer_complete_notification.txt +++ /dev/null @@ -1,11 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.txt' %} - -{% block content %} - A QA for Application {{proposal.lodgement_number}} has been completed ({{completed_by}}): - QA Officer Comments: {{comments}} - - You can access this referral using the following link: - - {{url}} - -{% endblock %} diff --git a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_qaofficer_notification.html b/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_qaofficer_notification.html deleted file mode 100755 index b0552a47ba..0000000000 --- a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_qaofficer_notification.html +++ /dev/null @@ -1,12 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} - {% if reminder %} -

This is a reminder for QA for Application {{proposal.lodgement_number}} that has been sent to you:

- {% else %} -

A QA for Application A{{proposal.id}} has been sent to you:

-

Comments ({{completed_by}}): {{comments}}

- {% endif %} -

You can access this Application using the following link:

- Access Application -{% endblock %} diff --git a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_qaofficer_notification.txt b/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_qaofficer_notification.txt deleted file mode 100755 index 4493f16d9e..0000000000 --- a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_qaofficer_notification.txt +++ /dev/null @@ -1,15 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.txt' %} - -{% block content %} - {% if reminder %} - This is a reminder for QA for Application {{proposal.lodgement_number}} that has been sent to you - {% else %} - A QA for Application A{{proposal.id}} has been sent to you: - Comments: {{comments}} - {% endif %} - - You can access this Application using the following link: - - {{url}} - -{% endblock %} diff --git a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_referral_complete_notification.html b/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_referral_complete_notification.html deleted file mode 100755 index acfa34943b..0000000000 --- a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_referral_complete_notification.html +++ /dev/null @@ -1,8 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} -

A referral for Application {{proposal.lodgement_number}} has been completed ({{completed_by}}):

-

Referral Comments: {{referral_comments}}

-

You can access this Application using the following link:

- Access Application -{% endblock %} diff --git a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_referral_complete_notification.txt b/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_referral_complete_notification.txt deleted file mode 100755 index bb52120745..0000000000 --- a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_referral_complete_notification.txt +++ /dev/null @@ -1,11 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.txt' %} - -{% block content %} - A referral for Application {{proposal.lodgement_number}} has been completed ({{completed_by}}): - Referral Comments: {{referral_comments}} - - You can access this referral using the following link: - - {{url}} - -{% endblock %} diff --git a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_referral_notification.html b/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_referral_notification.html deleted file mode 100755 index 12b38c8086..0000000000 --- a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_referral_notification.html +++ /dev/null @@ -1,12 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} - {% if reminder %} -

This is a reminder for a referral for Application {{proposal.lodgement_number}} that has been sent to you:

- {% else %} -

A referral for Application A{{proposal.id}} has been sent to you:

-

Comments: {{comments}}

- {% endif %} -

You can access this referral using the following link:

- Access Referral -{% endblock %} diff --git a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_referral_notification.txt b/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_referral_notification.txt deleted file mode 100755 index 51d6817a25..0000000000 --- a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_referral_notification.txt +++ /dev/null @@ -1,15 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.txt' %} - -{% block content %} - {% if reminder %} - This is a reminder for a referral for Application {{proposal.lodgement_number}} that has been sent to you - {% else %} - A referral for Application A{{proposal.id}} has been sent to you: - Comments: {{comments}} - {% endif %} - - You can access this referral using the following link: - - {{url}} - -{% endblock %} diff --git a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_submit_notification.html b/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_submit_notification.html deleted file mode 100755 index db4f5480df..0000000000 --- a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_submit_notification.html +++ /dev/null @@ -1,12 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.html' %} - -{% block content %} - The Application {{ proposal.lodgement_number }} has been submitted and can be assessed. - -

- You can access this Application using the following link: -

- Access Application - - -{% endblock %} diff --git a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_submit_notification.txt b/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_submit_notification.txt deleted file mode 100755 index 7a696502cb..0000000000 --- a/commercialoperator/components/proposals/templates/commercialoperator/emails/proposals/send_submit_notification.txt +++ /dev/null @@ -1,11 +0,0 @@ -{% extends 'commercialoperator/emails/base_email.txt' %} - -{% block content %} - The Application {{ proposal.lodgement_number }} has been submitted and can be assessed. - - You can access this Application using the following link: - - {{url}} - - -{% endblock %} diff --git a/commercialoperator/components/proposals/templates/commercialoperator/help_page_changelist.html b/commercialoperator/components/proposals/templates/commercialoperator/help_page_changelist.html deleted file mode 100755 index be726a53dc..0000000000 --- a/commercialoperator/components/proposals/templates/commercialoperator/help_page_changelist.html +++ /dev/null @@ -1,24 +0,0 @@ -{% extends 'admin/change_list.html' %} - -{% block object-tools %} -
-
- {% csrf_token %} - -
-
-
- {% csrf_token %} - -
-
-
- {% csrf_token %} - -
-
- -
-
- {{ block.super }} -{% endblock %} diff --git a/commercialoperator/components/proposals/templates/commercialoperator/mgt-commands.html b/commercialoperator/components/proposals/templates/commercialoperator/mgt-commands.html deleted file mode 100755 index 5aa79d92e4..0000000000 --- a/commercialoperator/components/proposals/templates/commercialoperator/mgt-commands.html +++ /dev/null @@ -1,21 +0,0 @@ -{% extends 'commercialoperator/base.html' %} - -{% block content %} -
-

Hover over button to see help text.

-
- {% csrf_token %} -

-

-

-

-

-

-
-
-
-
- {{ ret }} - {{ block.super }} -{% endblock %} - diff --git a/commercialoperator/components/proposals/templates/commercialoperator/reversion_history.html b/commercialoperator/components/proposals/templates/commercialoperator/reversion_history.html deleted file mode 100755 index 7626aa89ac..0000000000 --- a/commercialoperator/components/proposals/templates/commercialoperator/reversion_history.html +++ /dev/null @@ -1,43 +0,0 @@ -{% extends "admin/base.html" %} - -{% block extrastyle %} - {{ block.super }} - - - -{% endblock %} - - - - -{% block content %} - - {% include "reversion-compare/action_list_partial.html" %} - {% if request.GET.version_id1 %} - {% include "reversion-compare/compare_partial.html" %} - {% include "reversion-compare/compare_links_partial.html" %} - {% endif %} - - - -{% endblock %} - diff --git a/commercialoperator/components/proposals/utils.py b/commercialoperator/components/proposals/utils.py deleted file mode 100755 index 9f6b6b3be1..0000000000 --- a/commercialoperator/components/proposals/utils.py +++ /dev/null @@ -1,963 +0,0 @@ -import re -from django.db import transaction -from django.utils import timezone -from django.core.exceptions import ValidationError -from django.conf import settings -from preserialize.serialize import serialize -from ledger.accounts.models import EmailUser, Document -from commercialoperator.components.proposals.models import ProposalDocument, ProposalPark, ProposalParkActivity, ProposalParkAccess, ProposalTrail, ProposalTrailSectionActivity, ProposalTrailSection, ProposalParkZone, ProposalParkZoneActivity, ProposalOtherDetails, ProposalAccreditation, ProposalUserAction, ProposalAssessment, ProposalAssessmentAnswer, ChecklistQuestion -from commercialoperator.components.approvals.models import Approval -from commercialoperator.components.proposals.email import send_submit_email_notification, send_external_submit_email_notification -from commercialoperator.components.proposals.serializers import SaveProposalSerializer, SaveProposalParkSerializer, SaveProposalTrailSerializer, ProposalAccreditationSerializer, ProposalOtherDetailsSerializer -from commercialoperator.components.main.models import Activity, Park, AccessType, Trail, Section, Zone -import traceback -import os -from copy import deepcopy -from datetime import datetime - -import logging -logger = logging.getLogger(__name__) - -def create_data_from_form(schema, post_data, file_data, post_data_index=None,special_fields=[],assessor_data=False): - data = {} - special_fields_list = [] - assessor_data_list = [] - comment_data_list = {} - special_fields_search = SpecialFieldsSearch(special_fields) - if assessor_data: - assessor_fields_search = AssessorDataSearch() - comment_fields_search = CommentDataSearch() - try: - for item in schema: - data.update(_create_data_from_item(item, post_data, file_data, 0, '')) - #_create_data_from_item(item, post_data, file_data, 0, '') - special_fields_search.extract_special_fields(item, post_data, file_data, 0, '') - if assessor_data: - assessor_fields_search.extract_special_fields(item, post_data, file_data, 0, '') - comment_fields_search.extract_special_fields(item, post_data, file_data, 0, '') - special_fields_list = special_fields_search.special_fields - if assessor_data: - assessor_data_list = assessor_fields_search.assessor_data - comment_data_list = comment_fields_search.comment_data - except: - traceback.print_exc() - if assessor_data: - return [data],special_fields_list,assessor_data_list,comment_data_list - - return [data],special_fields_list - - -def _extend_item_name(name, suffix, repetition): - return '{}{}-{}'.format(name, suffix, repetition) - -def _create_data_from_item(item, post_data, file_data, repetition, suffix): - item_data = {} - - if 'name' in item: - extended_item_name = item['name'] - else: - raise Exception('Missing name in item %s' % item['label']) - - if 'children' not in item: - if item['type'] in ['checkbox' 'declaration']: - #item_data[item['name']] = post_data[item['name']] - item_data[item['name']] = extended_item_name in post_data - elif item['type'] == 'file': - if extended_item_name in file_data: - item_data[item['name']] = str(file_data.get(extended_item_name)) - # TODO save the file here - elif extended_item_name + '-existing' in post_data and len(post_data[extended_item_name + '-existing']) > 0: - item_data[item['name']] = post_data.get(extended_item_name + '-existing') - else: - item_data[item['name']] = '' - else: - if extended_item_name in post_data: - if item['type'] == 'multi-select': - item_data[item['name']] = post_data.getlist(extended_item_name) - else: - item_data[item['name']] = post_data.get(extended_item_name) - else: - if 'repetition' in item: - item_data = generate_item_data(extended_item_name,item,item_data,post_data,file_data,len(post_data[item['name']]),suffix) - else: - item_data = generate_item_data(extended_item_name, item, item_data, post_data, file_data,1,suffix) - - - if 'conditions' in item: - for condition in item['conditions'].keys(): - for child in item['conditions'][condition]: - item_data.update(_create_data_from_item(child, post_data, file_data, repetition, suffix)) - - return item_data - -def generate_item_data(item_name,item,item_data,post_data,file_data,repetition,suffix): - item_data_list = [] - for rep in xrange(0, repetition): - child_data = {} - for child_item in item.get('children'): - child_data.update(_create_data_from_item(child_item, post_data, file_data, 0, - '{}-{}'.format(suffix, rep))) - item_data_list.append(child_data) - - item_data[item['name']] = item_data_list - return item_data - -class AssessorDataSearch(object): - - def __init__(self,lookup_field='canBeEditedByAssessor'): - self.lookup_field = lookup_field - self.assessor_data = [] - - def extract_assessor_data(self,item,post_data): - values = [] - res = { - 'name': item, - 'assessor': '', - 'referrals':[] - } - for k in post_data: - if re.match(item,k): - values.append({k:post_data[k]}) - if values: - for v in values: - for k,v in v.items(): - parts = k.split('{}-'.format(item)) - if len(parts) > 1: - # split parts to see if referall - ref_parts = parts[1].split('Referral-') - if len(ref_parts) > 1: - # Referrals - res['referrals'].append({ - 'value':v, - 'email':ref_parts[1], - 'full_name': EmailUser.objects.get(email=ref_parts[1]).get_full_name() - }) - elif k.split('-')[-1].lower() == 'assessor': - # Assessor - res['assessor'] = v - - return res - - def extract_special_fields(self,item, post_data, file_data, repetition, suffix): - item_data = {} - if 'name' in item: - extended_item_name = item['name'] - else: - raise Exception('Missing name in item %s' % item['label']) - - if 'children' not in item: - if 'conditions' in item: - for condition in item['conditions'].keys(): - for child in item['conditions'][condition]: - item_data.update(self.extract_special_fields(child, post_data, file_data, repetition, suffix)) - - if item.get(self.lookup_field): - self.assessor_data.append(self.extract_assessor_data(extended_item_name,post_data)) - - else: - if 'repetition' in item: - item_data = self.generate_item_data_special_field(extended_item_name,item,item_data,post_data,file_data,len(post_data[item['name']]),suffix) - else: - item_data = self.generate_item_data_special_field(extended_item_name, item, item_data, post_data, file_data,1,suffix) - - if 'conditions' in item: - for condition in item['conditions'].keys(): - for child in item['conditions'][condition]: - item_data.update(self.extract_special_fields(child, post_data, file_data, repetition, suffix)) - - return item_data - - def generate_item_data_special_field(self,item_name,item,item_data,post_data,file_data,repetition,suffix): - item_data_list = [] - for rep in xrange(0, repetition): - child_data = {} - for child_item in item.get('children'): - child_data.update(self.extract_special_fields(child_item, post_data, file_data, 0, - '{}-{}'.format(suffix, rep))) - item_data_list.append(child_data) - - item_data[item['name']] = item_data_list - return item_data - -class CommentDataSearch(object): - - def __init__(self,lookup_field='canBeEditedByAssessor'): - self.lookup_field = lookup_field - self.comment_data = {} - - def extract_comment_data(self,item,post_data): - res = {} - values = [] - for k in post_data: - if re.match(item,k): - values.append({k:post_data[k]}) - if values: - for v in values: - for k,v in v.items(): - parts = k.split('{}'.format(item)) - if len(parts) > 1: - ref_parts = parts[1].split('-comment-field') - if len(ref_parts) > 1: - res = {'{}'.format(item):v} - return res - - def extract_special_fields(self,item, post_data, file_data, repetition, suffix): - item_data = {} - if 'name' in item: - extended_item_name = item['name'] - else: - raise Exception('Missing name in item %s' % item['label']) - - if 'children' not in item: - self.comment_data.update(self.extract_comment_data(extended_item_name,post_data)) - - else: - if 'repetition' in item: - item_data = self.generate_item_data_special_field(extended_item_name,item,item_data,post_data,file_data,len(post_data[item['name']]),suffix) - else: - item_data = self.generate_item_data_special_field(extended_item_name, item, item_data, post_data, file_data,1,suffix) - - - if 'conditions' in item: - for condition in item['conditions'].keys(): - for child in item['conditions'][condition]: - item_data.update(self.extract_special_fields(child, post_data, file_data, repetition, suffix)) - - return item_data - - def generate_item_data_special_field(self,item_name,item,item_data,post_data,file_data,repetition,suffix): - item_data_list = [] - for rep in xrange(0, repetition): - child_data = {} - for child_item in item.get('children'): - child_data.update(self.extract_special_fields(child_item, post_data, file_data, 0, - '{}-{}'.format(suffix, rep))) - item_data_list.append(child_data) - - item_data[item['name']] = item_data_list - return item_data - -class SpecialFieldsSearch(object): - - def __init__(self,lookable_fields): - self.lookable_fields = lookable_fields - self.special_fields = {} - - def extract_special_fields(self,item, post_data, file_data, repetition, suffix): - item_data = {} - if 'name' in item: - extended_item_name = item['name'] - else: - raise Exception('Missing name in item %s' % item['label']) - - if 'children' not in item: - for f in self.lookable_fields: - if item['type'] in ['checkbox' 'declaration']: - val = None - val = item.get(f,None) - if val: - item_data[f] = extended_item_name in post_data - self.special_fields.update(item_data) - else: - if extended_item_name in post_data: - val = None - val = item.get(f,None) - if val: - if item['type'] == 'multi-select': - item_data[f] = ','.join(post_data.getlist(extended_item_name)) - else: - item_data[f] = post_data.get(extended_item_name) - self.special_fields.update(item_data) - else: - if 'repetition' in item: - item_data = self.generate_item_data_special_field(extended_item_name,item,item_data,post_data,file_data,len(post_data[item['name']]),suffix) - else: - item_data = self.generate_item_data_special_field(extended_item_name, item, item_data, post_data, file_data,1,suffix) - - - if 'conditions' in item: - for condition in item['conditions'].keys(): - for child in item['conditions'][condition]: - item_data.update(self.extract_special_fields(child, post_data, file_data, repetition, suffix)) - - return item_data - - def generate_item_data_special_field(self,item_name,item,item_data,post_data,file_data,repetition,suffix): - item_data_list = [] - for rep in xrange(0, repetition): - child_data = {} - for child_item in item.get('children'): - child_data.update(self.extract_special_fields(child_item, post_data, file_data, 0, - '{}-{}'.format(suffix, rep))) - item_data_list.append(child_data) - - item_data[item['name']] = item_data_list - return item_data - -def save_park_activity_data(instance,select_parks_activities, request): - with transaction.atomic(): - try: - if select_parks_activities or len(select_parks_activities)==0: - try: - #current_parks=instance.parks.all() - selected_parks=[] - for item in select_parks_activities: - if item['park']: - selected_parks.append(item['park']) - try: - #Check if PrposalPark record already exists. If exists, check for activities - park=ProposalPark.objects.get(park=item['park'],proposal=instance) - current_activities=park.land_activities.all() - current_activities_id=[a.activity_id for a in current_activities] - #Get the access records related to ProposalPark - current_access=park.access_types.all() - current_access_id=[a.access_type_id for a in current_access] - if item['activities']: - for a in item['activities']: - if a in current_activities_id: - #if activity already exists then pass otherwise create the record. - pass - else: - try: - #TODO add logging - if a not in park.park.allowed_activities_ids: - #raise Exception('Activity not allowed for this park') - pass - else: - activity=Activity.objects.get(id=a) - ProposalParkActivity.objects.create(proposal_park=park, activity=activity) - instance.log_user_action(ProposalUserAction.ACTION_LINK_ACTIVITY.format(activity.id,park.park.id),request) - except: - raise - if item['access']: - for a in item['access']: - if a in current_access_id: - #if access type already exists then pass otherwise create the record. - pass - else: - try: - if a not in park.park.allowed_access_ids: - #raise Exception('Activity not allowed for this park') - pass - else: - access=AccessType.objects.get(id=a) - ProposalParkAccess.objects.create(proposal_park=park, access_type=access) - instance.log_user_action(ProposalUserAction.ACTION_LINK_ACCESS.format(access.id,park.park.id),request) - except: - raise - except ProposalPark.DoesNotExist: - try: - #If ProposalPark does not exists then create a new record and activities for it. - park_instance=Park.objects.get(id=item['park']) - park=ProposalPark.objects.create(park=park_instance, proposal=instance) - instance.log_user_action(ProposalUserAction.ACTION_LINK_PARK.format(park.park.id,instance.id),request) - current_activities=[] - for a in item['activities']: - try: - if a not in park.park.allowed_activities_ids: - #raise Exception('Activity not allowed for this park') - pass - else: - activity=Activity.objects.get(id=a) - ProposalParkActivity.objects.create(proposal_park=park, activity=activity) - instance.log_user_action(ProposalUserAction.ACTION_LINK_ACTIVITY.format(activity.id,park.park.id),request) - except: - raise - for a in item['access']: - try: - if a not in park.park.allowed_access_ids: - #raise Exception('Activity not allowed for this park') - pass - else: - access=AccessType.objects.get(id=a) - ProposalParkAccess.objects.create(proposal_park=park, access_type=access) - instance.log_user_action(ProposalUserAction.ACTION_LINK_ACCESS.format(access.id,park.park.id),request) - except: - raise - except: - raise - #compare all activities (new+old) with the list of activities selected activities to get - #the list of deleted activities. - new_activities=park.land_activities.all() - new_activities_id=set(a.activity_id for a in new_activities) - diff_activity=set(new_activities_id).difference(set(item['activities'])) - for d in diff_activity: - act=ProposalParkActivity.objects.get(activity_id=d, proposal_park=park) - act.delete() - instance.log_user_action(ProposalUserAction.ACTION_UNLINK_ACTIVITY.format(d,park.park.id),request) - new_access=park.access_types.all() - new_access_id=set(a.access_type_id for a in new_access) - diff_access=set(new_access_id).difference(set(item['access'])) - for d in diff_access: - acc=ProposalParkAccess.objects.get(access_type_id=d, proposal_park=park) - acc.delete() - instance.log_user_action(ProposalUserAction.ACTION_UNLINK_ACCESS.format(d,park.park.id),request) - new_parks=instance.parks.filter(park__park_type='land') - new_parks_id=set(p.park_id for p in new_parks) - diff_parks=set(new_parks_id).difference(set(selected_parks)) - for d in diff_parks: - pk=ProposalPark.objects.get(park=d, proposal=instance) - pk.delete() - instance.log_user_action(ProposalUserAction.ACTION_UNLINK_PARK.format(d,instance.id),request) - except: - raise - except: - raise - - -def save_trail_section_activity_data(instance,select_trails_activities, request): - with transaction.atomic(): - try: - if select_trails_activities or len(select_trails_activities)==0: - try: - #current_parks=instance.parks.all() - selected_trails=[] - #print("selected_trails",selected_trails) - for item in select_trails_activities: - if item['trail']: - selected_trails.append(item['trail']) - selected_sections=[] - try: - #Check if PrposalPark record already exists. If exists, check for sections - trail=ProposalTrail.objects.get(trail=item['trail'],proposal=instance) - current_sections=trail.sections.all() - current_sections_ids=[a.section_id for a in current_sections] - if item['activities']: - for a in item['activities']: - if a['section']: - selected_sections.append(a['section']) - if a['section'] in current_sections_ids: - section=ProposalTrailSection.objects.get(proposal_trail=trail, section=a['section']) - current_activities=section.trail_activities.all() - current_activities_id=[s.activity_id for s in current_activities] - if a['activities']: - for act in a['activities']: - if act in current_activities_id: - #if activity already exists then pass otherwise create the record. - pass - else: - try: - if act not in trail.trail.allowed_activities_ids: - pass - else: - activity=Activity.objects.get(id=act) - ProposalTrailSectionActivity.objects.create(trail_section=section, activity=activity) - instance.log_user_action(ProposalUserAction.ACTION_LINK_ACTIVITY_SECTION.format(activity.id,section.section.id, trail.trail.id),request) - except: - raise - else: - section_instance=Section.objects.get(id=a['section']) - section=ProposalTrailSection.objects.create(proposal_trail=trail, section=section_instance) - instance.log_user_action(ProposalUserAction.ACTION_LINK_SECTION.format(section.section.id, trail.trail.id),request) - if a['activities']: - for act in a['activities']: - try: - if act not in trail.trail.allowed_activities_ids: - pass - else: - activity=Activity.objects.get(id=act) - ProposalTrailSectionActivity.objects.create(trail_section=section, activity=activity) - instance.log_user_action(ProposalUserAction.ACTION_LINK_ACTIVITY_SECTION.format(activity.id,section.section.id, trail.trail.id),request) - except: - raise - new_activities=section.trail_activities.all() - new_activities_id=set(n.activity_id for n in new_activities) - diff_activity=set(new_activities_id).difference(set(a['activities'])) - #print("trail:",trail.trail_id,"section:",section.section_id,"new_activities:",new_activities_id, "diff:", diff_activity) - for d in diff_activity: - act=ProposalTrailSectionActivity.objects.get(activity_id=d, trail_section=section) - act.delete() - instance.log_user_action(ProposalUserAction.ACTION_UNLINK_ACTIVITY_SECTION.format(d,section.section.id, trail.trail.id),request) - except ProposalTrail.DoesNotExist: - try: - #If ProposalPark does not exists then create a new record and activities for it. - trail_instance=Trail.objects.get(id=item['trail']) - trail=ProposalTrail.objects.create(trail=trail_instance, proposal=instance) - instance.log_user_action(ProposalUserAction.ACTION_LINK_TRAIL.format(trail.trail.id, instance.id),request) - current_sections=[] - if item['activities']: - for a in item['activities']: - if a['section']: - selected_sections.append(a['section']) - section_instance=Section.objects.get(id=a['section']) - section=ProposalTrailSection.objects.create(proposal_trail=trail, section=section_instance) - instance.log_user_action(ProposalUserAction.ACTION_LINK_SECTION.format(section.section.id, trail.trail.id),request) - if a['activities']: - for act in a['activities']: - try: - if act not in trail.trail.allowed_activities_ids: - pass - else: - activity=Activity.objects.get(id=act) - ProposalTrailSectionActivity.objects.create(trail_section=section, activity=activity) - instance.log_user_action(ProposalUserAction.ACTION_LINK_ACTIVITY_SECTION.format(activity.id,section.section.id, trail.trail.id),request) - except: - raise - #Just to check the new activities. Next 3 lines can be deleted. - new_activities=section.trail_activities.all() - new_activities_id=set(nw.activity_id for nw in new_activities) - diff_activity=set(new_activities_id).difference(set(a['activities'])) - #print("not deleting","trail:",trail.trail_id,"section:",section.section_id,"new_activities:",new_activities_id, "diff:", diff_activity) - except: - raise - #compare all sections (new+old) with the list of sections selected to get - #the list of deleted sections. - new_sections=trail.sections.all() - new_sections_ids=set(a.section_id for a in new_sections) - diff_sections=set(new_sections_ids).difference(set(selected_sections)) - #print("trail:",trail.trail_id, "new_sections:", new_sections_ids,"diff_sections:", diff_sections) - for d in diff_sections: - pk=ProposalTrailSection.objects.get(section=d, proposal_trail=trail) - pk.delete() - instance.log_user_action(ProposalUserAction.ACTION_UNLINK_SECTION.format(d, trail.trail.id),request) - new_trails=instance.trails.all() - new_trails_id=set(p.trail_id for p in new_trails) - diff_trails=set(new_trails_id).difference(set(selected_trails)) - #print("new_trails", new_trails_id, "diff:", diff_trails) - for d in diff_trails: - pk=ProposalTrail.objects.get(trail=d, proposal=instance) - pk.delete() - instance.log_user_action(ProposalUserAction.ACTION_UNLINK_TRAIL.format(d, instance.id),request) - except: - raise - except: - raise - - - -#Save Marine parks, zones and related activity for TClass license -def save_park_zone_activity_data(instance,marine_parks_activities, request): - with transaction.atomic(): - try: - if marine_parks_activities or len(marine_parks_activities)==0: - try: - #current_parks=instance.parks.all() - selected_parks=[] - #print("selected_parks",selected_parks) - for item in marine_parks_activities: - if item['park']: - selected_parks.append(item['park']) - selected_zones=[] - try: - #Check if PrposalPark record already exists. If exists, check for zones - park=ProposalPark.objects.get(park=item['park'],proposal=instance) - current_zones=park.zones.all() - current_zones_ids=[a.zone_id for a in current_zones] - if item['activities']: - for a in item['activities']: - if a['zone']: - selected_zones.append(a['zone']) - if a['zone'] in current_zones_ids: - zone=ProposalParkZone.objects.get(proposal_park=park, zone=a['zone']) - current_activities=zone.park_activities.all() - current_activities_id=[s.activity_id for s in current_activities] - if a['activities']: - for act in a['activities']: - if act in current_activities_id: - #if activity already exists then pass otherwise create the record. - pass - else: - try: - if act not in zone.zone.allowed_activities_ids: - pass - else: - activity=Activity.objects.get(id=act) - ProposalParkZoneActivity.objects.create(park_zone=zone, activity=activity) - instance.log_user_action(ProposalUserAction.ACTION_LINK_ACTIVITY_ZONE.format(activity.id,zone.zone.id, park.park.id),request) - except: - raise - if 'access_point' in a: - zone.access_point = a['access_point'] - zone.save() - else: - zone_instance=Zone.objects.get(id=a['zone']) - zone=ProposalParkZone.objects.create(proposal_park=park, zone=zone_instance) - instance.log_user_action(ProposalUserAction.ACTION_LINK_ZONE.format(zone.zone.id, park.park.id),request) - if a['activities']: - for act in a['activities']: - try: - if act not in zone.zone.allowed_activities_ids: - pass - else: - activity=Activity.objects.get(id=act) - ProposalParkZoneActivity.objects.create(park_zone=zone, activity=activity) - instance.log_user_action(ProposalUserAction.ACTION_LINK_ACTIVITY_ZONE.format(activity.id,zone.zone.id, park.park.id),request) - except: - raise - if 'access_point' in a: - zone.access_point = a['access_point'] - zone.save() - new_activities=zone.park_activities.all() - new_activities_id=set(n.activity_id for n in new_activities) - diff_activity=set(new_activities_id).difference(set(a['activities'])) - #print("park:",park.park_id,"zone:",zone.zone_id,"new_activities:",new_activities_id, "diff:", diff_activity) - for d in diff_activity: - act=ProposalParkZoneActivity.objects.get(activity_id=d, park_zone=zone) - act.delete() - instance.log_user_action(ProposalUserAction.ACTION_UNLINK_ACTIVITY_ZONE.format(d,zone.zone.id, park.park.id),request) - - except ProposalPark.DoesNotExist: - try: - #If ProposalPark does not exists then create a new record and activities for it. - park_instance=Park.objects.get(id=item['park']) - park=ProposalPark.objects.create(park=park_instance, proposal=instance) - instance.log_user_action(ProposalUserAction.ACTION_LINK_PARK.format(park.park.id, instance.id),request) - current_zones=[] - if item['activities']: - for a in item['activities']: - if a['zone']: - selected_zones.append(a['zone']) - zone_instance=Zone.objects.get(id=a['zone']) - zone=ProposalParkZone.objects.create(proposal_park=park, zone=zone_instance) - instance.log_user_action(ProposalUserAction.ACTION_LINK_ZONE.format(zone.zone.id, park.park.id),request) - if a['activities']: - for act in a['activities']: - try: - if act not in zone.zone.allowed_activities_ids: - pass - else: - activity=Activity.objects.get(id=act) - ProposalParkZoneActivity.objects.create(park_zone=zone, activity=activity) - instance.log_user_action(ProposalUserAction.ACTION_LINK_ACTIVITY_ZONE.format(activity.id,zone.zone.id, park.park.id),request) - except: - raise - if 'access_point' in a: - zone.access_point = a['access_point'] - zone.save() - #Just to check the new activities. Next 3 lines can be deleted. - #new_activities=zone.park_activities.all() - #new_activities_id=set(nw.activity_id for nw in new_activities) - #diff_activity=set(new_activities_id).difference(set(a['activities'])) - #print("not deleting","park:",park.park_id,"zone:",zone.zone_id,"new_activities:",new_activities_id, "diff:", diff_activity) - except: - raise - #compare all zones (new+old) with the list of zones selected to get - #the list of deleted zones. - new_zones=park.zones.all() - new_zones_ids=set(a.zone_id for a in new_zones) - diff_zones=set(new_zones_ids).difference(set(selected_zones)) - #print("park:",park.park_id, "new_zones:", new_zones_ids,"diff_zones:", diff_zones) - for d in diff_zones: - pk=ProposalParkZone.objects.get(zone=d, proposal_park=park) - pk.delete() - instance.log_user_action(ProposalUserAction.ACTION_UNLINK_ZONE.format(d, park.park.id),request) - new_parks=instance.parks.filter(park__park_type='marine') - new_parks_id=set(p.park_id for p in new_parks) - diff_parks=set(new_parks_id).difference(set(selected_parks)) - #print("new_parks", new_parks_id, "diff:", diff_parks) - for d in diff_parks: - pk=ProposalPark.objects.get(park=d, proposal=instance) - pk.delete() - instance.log_user_action(ProposalUserAction.ACTION_UNLINK_PARK.format(d, instance.id),request) - except: - raise - except: - raise - -def save_proponent_data(instance,request,viewset,parks=None,trails=None): - with transaction.atomic(): - try: -# lookable_fields = ['isTitleColumnForDashboard','isActivityColumnForDashboard','isRegionColumnForDashboard'] -# extracted_fields,special_fields = create_data_from_form(instance.schema, request.POST, request.FILES, special_fields=lookable_fields) -# instance.data = extracted_fields -# data = { -# #'region': special_fields.get('isRegionColumnForDashboard',None), -# 'title': special_fields.get('isTitleColumnForDashboard',None), -# 'activity': special_fields.get('isActivityColumnForDashboard',None), -# -# 'data': extracted_fields, -# 'processing_status': instance.PROCESSING_STATUS_CHOICES[1][0] if instance.processing_status == 'temp' else instance.processing_status, -# 'customer_status': instance.PROCESSING_STATUS_CHOICES[1][0] if instance.processing_status == 'temp' else instance.customer_status, -# } - data = { - } - - try: - schema=request.data.get('schema') - except: - schema=request.POST.get('schema') - import json - sc=json.loads(schema) - other_details_data=sc['other_details'] - #print other_details_data - if instance.is_amendment_proposal or instance.pending_amendment_request: - other_details_data['preferred_licence_period']=instance.other_details.preferred_licence_period - serializer = ProposalOtherDetailsSerializer(instance.other_details,data=other_details_data) - serializer.is_valid(raise_exception=True) - serializer.save() - #select_parks_activities=sc['selected_parks_activities'] - #select_trails_activities=sc['selected_trails_activities'] - - try: - select_parks_activities=json.loads(request.data.get('selected_parks_activities')) - select_trails_activities=json.loads(request.data.get('selected_trails_activities')) - marine_parks_activities=json.loads(request.data.get('marine_parks_activities')) - except: - select_parks_activities=json.loads(request.POST.get('selected_parks_activities', None)) - select_trails_activities=json.loads(request.POST.get('selected_trails_activities', None)) - marine_parks_activities=json.loads(request.POST.get('marine_parks_activities', None)) - - other_details=ProposalOtherDetails.objects.update_or_create(proposal=instance) - # instance.save() - serializer = SaveProposalSerializer(instance, data, partial=True) - serializer.is_valid(raise_exception=True) - viewset.perform_update(serializer) - if 'accreditations' in other_details_data: - accreditation_types = instance.other_details.accreditations.values_list('accreditation_type', flat=True) - for acc in other_details_data['accreditations']: - #print acc - if 'id' in acc: - #acc_qs = ProposalAccreditation.objects.filter(id=acc['id']) - acc_qs = instance.other_details.accreditations.filter(id=acc['id']) - - if acc_qs and 'is_deleted' in acc and acc['is_deleted']==True: - acc_qs[0].delete() - - elif acc['accreditation_type'] in accreditation_types: - try: - instance.other_details.accreditations.filter(id=acc['id']).update( - accreditation_type = acc['accreditation_type'], - comments = acc['comments'], - accreditation_expiry = datetime.strptime(acc['accreditation_expiry'], "%d/%m/%Y").date() if acc['accreditation_expiry'] else None, # TODO later this may be mandatory - ) - except Exception, e: - logger.error('An error occurred while updating Accreditations {}'.format(e)) - else: - serializer=ProposalAccreditationSerializer(data=acc) - serializer.is_valid(raise_exception=True) - serializer.save() - #ProposalAccreditation.objects.create( - # id=acc['id'], - # accreditation_type=acc['accreditation_type'], - # comments = acc['comments'], - # accreditation_expiry = datetime.strptime(acc['accreditation_expiry'], "%d/%m/%Y").date(), - #) - - elif acc['accreditation_type'] not in accreditation_types: - serializer=ProposalAccreditationSerializer(data=acc) - serializer.is_valid(raise_exception=True) - serializer.save() - else: - logger.warn('Possible duplicate Accreditation Type for Application {}'.format(instance.lodgement_number)) - - if select_parks_activities or len(select_parks_activities)==0: - try: - - save_park_activity_data(instance, select_parks_activities, request) - - except: - raise - if select_trails_activities or len(select_trails_activities)==0: - try: - - save_trail_section_activity_data(instance, select_trails_activities, request) - - except: - raise - if marine_parks_activities or len(marine_parks_activities)==0: - try: - save_park_zone_activity_data(instance, marine_parks_activities, request) - except: - raise - except: - raise - -def save_assessor_data(instance,request,viewset): - with transaction.atomic(): - try: - # lookable_fields = ['isTitleColumnForDashboard','isActivityColumnForDashboard','isRegionColumnForDashboard'] - # extracted_fields,special_fields,assessor_data,comment_data = create_data_from_form( - # instance.schema, request.POST, request.FILES,special_fields=lookable_fields,assessor_data=True) - # data = { - # 'data': extracted_fields, - # 'assessor_data': assessor_data, - # 'comment_data': comment_data, - # } - data={} - serializer = SaveProposalSerializer(instance, data, partial=True) - serializer.is_valid(raise_exception=True) - viewset.perform_update(serializer) - #Save activities - try: - schema=request.data.get('schema') - except: - schema=request.POST.get('schema') - import json - sc=json.loads(schema) - #select_parks_activities=sc['selected_parks_activities'] - #select_trails_activities=sc['selected_trails_activities'] - try: - select_parks_activities=json.loads(request.data.get('selected_parks_activities')) - select_trails_activities=json.loads(request.data.get('selected_trails_activities')) - marine_parks_activities=json.loads(request.data.get('marine_parks_activities')) - except: - select_parks_activities=request.POST.get('selected_parks_activities', None) - if select_parks_activities: - select_parks_activities=json.loads(select_parks_activities) - select_trails_activities=request.POST.get('selected_trails_activities', None) - if select_trails_activities: - select_trails_activities=json.loads(select_trails_activities) - marine_parks_activities=request.POST.get('marine_parks_activities', None) - if marine_parks_activities: - marine_parks_activities=json.loads(marine_parks_activities) - #print select_parks_activities, selected_trails_activities - if select_parks_activities or len(select_parks_activities)==0: - try: - save_park_activity_data(instance, select_parks_activities, request) - except: - raise - if select_trails_activities or len(select_trails_activities)==0: - try: - save_trail_section_activity_data(instance, select_trails_activities, request) - except: - raise - if marine_parks_activities or len(marine_parks_activities)==0: - try: - save_park_zone_activity_data(instance, marine_parks_activities, request) - except: - raise - # Save Documents - for f in request.FILES: - try: - #document = instance.documents.get(name=str(request.FILES[f])) - document = instance.documents.get(input_name=f) - except ProposalDocument.DoesNotExist: - document = instance.documents.get_or_create(input_name=f)[0] - document.name = str(request.FILES[f]) - if document._file and os.path.isfile(document._file.path): - os.remove(document._file.path) - document._file = request.FILES[f] - document.save() - # End Save Documents - except: - raise - -def proposal_submit(proposal,request): - with transaction.atomic(): - if proposal.can_user_edit: - proposal.submitter = request.user - #proposal.lodgement_date = datetime.datetime.strptime(timezone.now().strftime('%Y-%m-%d'),'%Y-%m-%d').date() - proposal.lodgement_date = timezone.now() - proposal.training_completed = True - if (proposal.amendment_requests): - qs = proposal.amendment_requests.filter(status = "requested") - if (qs): - for q in qs: - q.status = 'amended' - q.save() - - # Create a log entry for the proposal - proposal.log_user_action(ProposalUserAction.ACTION_LODGE_APPLICATION.format(proposal.id),request) - # Create a log entry for the organisation - #proposal.applicant.log_user_action(ProposalUserAction.ACTION_LODGE_APPLICATION.format(proposal.id),request) - applicant_field=getattr(proposal, proposal.applicant_field) - applicant_field.log_user_action(ProposalUserAction.ACTION_LODGE_APPLICATION.format(proposal.id),request) - - ret1 = send_submit_email_notification(request, proposal) - ret2 = send_external_submit_email_notification(request, proposal) - - #proposal.save_form_tabs(request) - if ret1 and ret2: - proposal.processing_status = 'with_assessor' - proposal.customer_status = 'with_assessor' - proposal.documents.all().update(can_delete=False) - proposal.save() - else: - raise ValidationError('An error occurred while submitting proposal (Submit email notifications failed)') - #Create assessor checklist with the current assessor_list type questions - #Assessment instance already exits then skip. - try: - assessor_assessment=ProposalAssessment.objects.get(proposal=proposal,referral_group=None, referral_assessment=False) - except ProposalAssessment.DoesNotExist: - assessor_assessment=ProposalAssessment.objects.create(proposal=proposal,referral_group=None, referral_assessment=False) - checklist=ChecklistQuestion.objects.filter(list_type='assessor_list', obsolete=False) - for chk in checklist: - try: - chk_instance=ProposalAssessmentAnswer.objects.get(question=chk, assessment=assessor_assessment) - except ProposalAssessmentAnswer.DoesNotExist: - chk_instance=ProposalAssessmentAnswer.objects.create(question=chk, assessment=assessor_assessment) - - return proposal - - else: - raise ValidationError('You can\'t edit this proposal at this moment') - - -def is_payment_officer(user): - from commercialoperator.components.proposals.models import PaymentOfficerGroup - try: - group= PaymentOfficerGroup.objects.get(default=True) - except PaymentOfficerGroup.DoesNotExist: - group= None - if group: - if user in group.members.all(): - return True - return False - - -from commercialoperator.components.proposals.models import Proposal, Referral, AmendmentRequest, ProposalDeclinedDetails -from commercialoperator.components.approvals.models import Approval -from commercialoperator.components.compliances.models import Compliance -from commercialoperator.components.bookings.models import ApplicationFee, Booking -from ledger.payments.models import Invoice -from commercialoperator.components.proposals import email as proposal_email -from commercialoperator.components.approvals import email as approval_email -from commercialoperator.components.compliances import email as compliance_email -from commercialoperator.components.bookings import email as booking_email -def test_proposal_emails(request): - """ Script to test all emails (listed below) from the models """ - # setup - if not (settings.PRODUCTION_EMAIL): - recipients = [request.user.email] - #proposal = Proposal.objects.last() - approval = Approval.objects.filter(migrated=False).last() - proposal = approval.current_proposal - referral = Referral.objects.last() - amendment_request = AmendmentRequest.objects.last() - reason = 'Not enough information' - proposal_decline = ProposalDeclinedDetails.objects.last() - compliance = Compliance.objects.last() - - application_fee = ApplicationFee.objects.last() - api = Invoice.objects.get(reference=application_fee.application_fee_invoices.last().invoice_reference) - - booking = Booking.objects.last() - bi = Invoice.objects.get(reference=booking.invoices.last().invoice_reference) - - proposal_email.send_qaofficer_email_notification(proposal, recipients, request, reminder=False) - proposal_email.send_qaofficer_complete_email_notification(proposal, recipients, request, reminder=False) - proposal_email.send_referral_email_notification(referral,recipients,request,reminder=False) - proposal_email.send_referral_complete_email_notification(referral,request) - proposal_email.send_amendment_email_notification(amendment_request, request, proposal) - proposal_email.send_submit_email_notification(request, proposal) - proposal_email.send_external_submit_email_notification(request, proposal) - proposal_email.send_approver_decline_email_notification(reason, request, proposal) - proposal_email.send_approver_approve_email_notification(request, proposal) - proposal_email.send_proposal_decline_email_notification(proposal,request,proposal_decline) - proposal_email.send_proposal_approver_sendback_email_notification(request, proposal) - proposal_email.send_proposal_approval_email_notification(proposal,request) - - approval_email.send_approval_expire_email_notification(approval) - approval_email.send_approval_cancel_email_notification(approval) - approval_email.send_approval_suspend_email_notification(approval, request) - approval_email.send_approval_surrender_email_notification(approval, request) - approval_email.send_approval_renewal_email_notification(approval) - approval_email.send_approval_reinstate_email_notification(approval, request) - - compliance_email.send_amendment_email_notification(amendment_request, request, compliance, is_test=True) - compliance_email.send_reminder_email_notification(compliance, is_test=True) - compliance_email.send_internal_reminder_email_notification(compliance, is_test=True) - compliance_email.send_due_email_notification(compliance, is_test=True) - compliance_email.send_internal_due_email_notification(compliance, is_test=True) - compliance_email.send_compliance_accept_email_notification(compliance,request, is_test=True) - compliance_email.send_external_submit_email_notification(request, compliance, is_test=True) - compliance_email.send_submit_email_notification(request, compliance, is_test=True) - - - booking_email.send_application_fee_invoice_tclass_email_notification(request, proposal, api, recipients, is_test=True) - booking_email.send_application_fee_confirmation_tclass_email_notification(request, application_fee, api, recipients, is_test=True) - booking_email.send_invoice_tclass_email_notification(request, booking, bi, recipients, is_test=True) - booking_email.send_confirmation_tclass_email_notification(request, booking, bi, recipients, is_test=True) - - - diff --git a/commercialoperator/components/proposals/views.py b/commercialoperator/components/proposals/views.py deleted file mode 100755 index db067dd84d..0000000000 --- a/commercialoperator/components/proposals/views.py +++ /dev/null @@ -1,121 +0,0 @@ -from django.http import HttpResponse,JsonResponse -from django.urls import reverse -from django.shortcuts import render, redirect, get_object_or_404 -from django.views.generic import View, TemplateView -from django.db.models import Q -from commercialoperator.components.proposals.utils import create_data_from_form -from commercialoperator.components.proposals.models import Proposal, Referral, ProposalType, HelpPage -from commercialoperator.components.approvals.models import Approval -from commercialoperator.components.compliances.models import Compliance -import json,traceback -from reversion_compare.views import HistoryCompareDetailView -from reversion.models import Version - -class ProposalView(TemplateView): - template_name = 'commercialoperator/proposal.html' - - def post(self, request, *args, **kwargs): - extracted_fields = [] - try: - proposal_id = request.POST.pop('proposal_id') - proposal = Proposal.objects.get(proposal_id) - schema = json.loads(request.POST.pop('schema')[0]) - extracted_fields = create_data_from_form(schema,request.POST, request.FILES) - proposal.schema = schema; - proposal.data = extracted_fields - proposal.save() - return redirect(reverse('external')) - except: - traceback.print_exc - return JsonResponse({error:"something went wrong"},safe=False,status=400) - - -class ProposalHistoryCompareView(HistoryCompareDetailView): - """ - View for reversion_compare - """ - model = Proposal - template_name = 'commercialoperator/reversion_history.html' - - -class ProposalFilteredHistoryCompareView(HistoryCompareDetailView): - """ - View for reversion_compare - with 'status' in the comment field only' - """ - model = Proposal - template_name = 'commercialoperator/reversion_history.html' - - def _get_action_list(self,): - """ Get only versions when processing_status changed, and add the most recent (current) version """ - current_revision_id = Version.objects.get_for_object(self.get_object()).first().revision_id - action_list = [ - {"version": version, "revision": version.revision} - for version in self._order_version_queryset( - #Version.objects.get_for_object(self.get_object()).select_related("revision__user").filter(revision__comment__icontains='status') - Version.objects.get_for_object(self.get_object()).select_related("revision__user").filter(Q(revision__comment__icontains='status') | Q(revision_id=current_revision_id)) - ) - ] - return action_list - -class ReferralHistoryCompareView(HistoryCompareDetailView): - """ - View for reversion_compare - """ - model = Referral - template_name = 'commercialoperator/reversion_history.html' - - -class ApprovalHistoryCompareView(HistoryCompareDetailView): - """ - View for reversion_compare - """ - model = Approval - template_name = 'commercialoperator/reversion_history.html' - - -class ComplianceHistoryCompareView(HistoryCompareDetailView): - """ - View for reversion_compare - """ - model = Compliance - template_name = 'commercialoperator/reversion_history.html' - - - -class ProposalTypeHistoryCompareView(HistoryCompareDetailView): - """ - View for reversion_compare - """ - model = ProposalType - template_name = 'commercialoperator/reversion_history.html' - - -class HelpPageHistoryCompareView(HistoryCompareDetailView): - """ - View for reversion_compare - """ - model = HelpPage - template_name = 'commercialoperator/reversion_history.html' - - -class PreviewLicencePDFView(View): - def post(self, request, *args, **kwargs): - response = HttpResponse(content_type='application/pdf') - - proposal = self.get_object() - details = json.loads(request.POST.get('formData')) - - response.write(proposal.preview_approval(request, details)) - return response - - def get_object(self): - return get_object_or_404(Proposal, id=self.kwargs['proposal_pk']) - - -from commercialoperator.components.proposals.utils import test_proposal_emails -class TestEmailView(View): - def get(self, request, *args, **kwargs): - test_proposal_emails(request) - return HttpResponse('Test Email Script Completed') - - diff --git a/commercialoperator/components/users/__init__.py b/commercialoperator/components/users/__init__.py deleted file mode 100755 index e69de29bb2..0000000000 diff --git a/commercialoperator/components/users/admin.py b/commercialoperator/components/users/admin.py deleted file mode 100755 index c08addc3f7..0000000000 --- a/commercialoperator/components/users/admin.py +++ /dev/null @@ -1,4 +0,0 @@ -from django.contrib import admin -from commercialoperator.components.users import models -# Register your models here. - diff --git a/commercialoperator/components/users/api.py b/commercialoperator/components/users/api.py deleted file mode 100755 index 4f62c8c4a7..0000000000 --- a/commercialoperator/components/users/api.py +++ /dev/null @@ -1,247 +0,0 @@ -import traceback -import base64 -import geojson -from six.moves.urllib.parse import urlparse -from wsgiref.util import FileWrapper -from django.db.models import Q, Min -from django.db import transaction -from django.http import HttpResponse -from django.core.files.base import ContentFile -from django.core.exceptions import ValidationError -from django.conf import settings -from django.contrib import messages -from django.views.decorators.http import require_http_methods -from django.views.decorators.csrf import csrf_exempt -from django.utils import timezone -from rest_framework import viewsets, serializers, status, generics, views -from rest_framework.decorators import detail_route, list_route,renderer_classes -from rest_framework.response import Response -from rest_framework.renderers import JSONRenderer -from rest_framework.permissions import IsAuthenticated, AllowAny, IsAdminUser, BasePermission -from rest_framework.pagination import PageNumberPagination -from datetime import datetime, timedelta -from collections import OrderedDict -from django.core.cache import cache -from ledger.accounts.models import EmailUser,Address, Profile, EmailIdentity, EmailUserAction -from ledger.address.models import Country -from datetime import datetime,timedelta, date -from commercialoperator.components.organisations.models import ( - Organisation, - ) - -from commercialoperator.components.users.serializers import ( - UserSerializer, - UserFilterSerializer, - UserAddressSerializer, - PersonalSerializer, - ContactSerializer, - EmailUserActionSerializer, - EmailUserCommsSerializer, - EmailUserLogEntrySerializer - ) -from commercialoperator.components.organisations.serializers import ( - OrganisationRequestDTSerializer, -) -from commercialoperator.components.main.utils import retrieve_department_users - -class DepartmentUserList(views.APIView): - renderer_classes = [JSONRenderer,] - def get(self, request, format=None): - data = cache.get('department_users') - if not data: - retrieve_department_users() - data = cache.get('department_users') - return Response(data) - - serializer = UserSerializer(request.user) - -class GetProfile(views.APIView): - renderer_classes = [JSONRenderer,] - def get(self, request, format=None): - serializer = UserSerializer(request.user) - return Response(serializer.data) - -from rest_framework import filters -class UserListFilterView(generics.ListAPIView): - """ https://cop-internal.dbca.wa.gov.au/api/filtered_users?search=russell - """ - queryset = EmailUser.objects.all() - serializer_class = UserFilterSerializer - filter_backends = (filters.SearchFilter,) - search_fields = ('email', 'first_name', 'last_name') - -class UserViewSet(viewsets.ModelViewSet): - queryset = EmailUser.objects.all() - serializer_class = UserSerializer - - @detail_route(methods=['POST',]) - def update_personal(self, request, *args, **kwargs): - try: - instance = self.get_object() - serializer = PersonalSerializer(instance,data=request.data) - serializer.is_valid(raise_exception=True) - instance = serializer.save() - serializer = UserSerializer(instance) - return Response(serializer.data); - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['POST',]) - def update_contact(self, request, *args, **kwargs): - try: - instance = self.get_object() - serializer = ContactSerializer(instance,data=request.data) - serializer.is_valid(raise_exception=True) - instance = serializer.save() - serializer = UserSerializer(instance) - return Response(serializer.data); - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['POST',]) - def update_address(self, request, *args, **kwargs): - try: - instance = self.get_object() - serializer = UserAddressSerializer(data=request.data) - serializer.is_valid(raise_exception=True) - address, created = Address.objects.get_or_create( - line1 = serializer.validated_data['line1'], - locality = serializer.validated_data['locality'], - state = serializer.validated_data['state'], - country = serializer.validated_data['country'], - postcode = serializer.validated_data['postcode'], - user = instance - ) - instance.residential_address = address - instance.save() - serializer = UserSerializer(instance) - return Response(serializer.data); - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['POST',]) - def upload_id(self, request, *args, **kwargs): - try: - instance = self.get_object() - instance.upload_identification(request) - with transaction.atomic(): - instance.save() - instance.log_user_action(EmailUserAction.ACTION_ID_UPDATE.format( - '{} {} ({})'.format(instance.first_name, instance.last_name, instance.email)), request) - serializer = UserSerializer(instance, partial=True) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['GET', ]) - def pending_org_requests(self, request, *args, **kwargs): - try: - instance = self.get_object() - serializer = OrganisationRequestDTSerializer( - instance.organisationrequest_set.filter( - status='with_assessor'), - many=True, - context={'request': request}) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['GET', ]) - def action_log(self, request, *args, **kwargs): - try: - instance = self.get_object() - qs = instance.action_logs.all() - serializer = EmailUserActionSerializer(qs, many=True) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - - @detail_route(methods=['GET',]) - def comms_log(self, request, *args, **kwargs): - try: - instance = self.get_object() - qs = instance.comms_logs.all() - serializer = EmailUserCommsSerializer(qs,many=True) - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) - - @detail_route(methods=['POST',]) - @renderer_classes((JSONRenderer,)) - def add_comms_log(self, request, *args, **kwargs): - try: - with transaction.atomic(): - instance = self.get_object() - request.data['emailuser'] = u'{}'.format(instance.id) - request.data['staff'] = u'{}'.format(request.user.id) - serializer = EmailUserLogEntrySerializer(data=request.data) - serializer.is_valid(raise_exception=True) - comms = serializer.save() - # Save the files - for f in request.FILES: - document = comms.documents.create() - document.name = str(request.FILES[f]) - document._file = request.FILES[f] - document.save() - # End Save Documents - - return Response(serializer.data) - except serializers.ValidationError: - print(traceback.print_exc()) - raise - except ValidationError as e: - print(traceback.print_exc()) - raise serializers.ValidationError(repr(e.error_dict)) - except Exception as e: - print(traceback.print_exc()) - raise serializers.ValidationError(str(e)) diff --git a/commercialoperator/components/users/models.py b/commercialoperator/components/users/models.py deleted file mode 100755 index e69de29bb2..0000000000 diff --git a/commercialoperator/components/users/serializers.py b/commercialoperator/components/users/serializers.py deleted file mode 100755 index fbe91343b1..0000000000 --- a/commercialoperator/components/users/serializers.py +++ /dev/null @@ -1,221 +0,0 @@ -from django.conf import settings -from ledger.accounts.models import EmailUser,Address, Profile,EmailIdentity,Document, EmailUserAction, EmailUserLogEntry, CommunicationsLogEntry -from commercialoperator.components.organisations.models import ( - Organisation, - ) -from commercialoperator.components.organisations.utils import can_admin_org, is_consultant -from rest_framework import serializers -from ledger.accounts.utils import in_dbca_domain -from ledger.payments.helpers import is_payment_admin - -class DocumentSerializer(serializers.ModelSerializer): - - class Meta: - model = Document - fields = ('id','description','file','name','uploaded_date') - -class UserAddressSerializer(serializers.ModelSerializer): - class Meta: - model = Address - fields = ( - 'id', - 'line1', - 'locality', - 'state', - 'country', - 'postcode' - ) - -class UserOrganisationSerializer(serializers.ModelSerializer): - name = serializers.CharField(source='organisation.name') - abn = serializers.CharField(source='organisation.abn') - email = serializers.SerializerMethodField() - is_consultant = serializers.SerializerMethodField(read_only=True) - is_admin = serializers.SerializerMethodField(read_only=True) - - class Meta: - model = Organisation - fields = ( - 'id', - 'name', - 'abn', - 'email', - 'is_consultant', - 'is_admin' - ) - - def get_is_admin(self, obj): - user = EmailUser.objects.get(id=self.context.get('user_id')) - return can_admin_org(obj, user) - - def get_is_consultant(self, obj): - user = EmailUser.objects.get(id=self.context.get('user_id')) - return is_consultant(obj, user) - - def get_email(self, obj): - email = EmailUser.objects.get(id=self.context.get('user_id')).email - return email - - -class UserFilterSerializer(serializers.ModelSerializer): - name = serializers.SerializerMethodField() - - class Meta: - model = EmailUser - fields = ( - 'id', - 'last_name', - 'first_name', - 'email', - 'name' - ) - - def get_name(self, obj): - return obj.get_full_name() - - -class UserSerializer(serializers.ModelSerializer): - commercialoperator_organisations = serializers.SerializerMethodField() - residential_address = UserAddressSerializer() - personal_details = serializers.SerializerMethodField() - address_details = serializers.SerializerMethodField() - contact_details = serializers.SerializerMethodField() - full_name = serializers.SerializerMethodField() - identification = DocumentSerializer() - is_department_user = serializers.SerializerMethodField() - is_payment_admin = serializers.SerializerMethodField() - - class Meta: - model = EmailUser - fields = ( - 'id', - 'last_name', - 'first_name', - 'email', - 'identification', - 'residential_address', - 'phone_number', - 'mobile_number', - 'commercialoperator_organisations', - 'personal_details', - 'address_details', - 'contact_details', - 'full_name', - 'is_department_user', - 'is_payment_admin' - ) - - def get_personal_details(self,obj): - return True if obj.last_name and obj.first_name else False - - def get_address_details(self,obj): - return True if obj.residential_address else False - - def get_contact_details(self,obj): - if obj.mobile_number and obj.email: - return True - elif obj.phone_number and obj.email: - return True - elif obj.mobile_number and obj.phone_number: - return True - else: - return False - - def get_full_name(self, obj): - return obj.get_full_name() - - def get_is_department_user(self, obj): - if obj.email: - return in_dbca_domain(obj) - else: - return False - - def get_is_payment_admin(self, obj): - return is_payment_admin(obj) - - def get_commercialoperator_organisations(self, obj): - commercialoperator_organisations = obj.commercialoperator_organisations - serialized_orgs = UserOrganisationSerializer( - commercialoperator_organisations, many=True, context={ - 'user_id': obj.id}).data - return serialized_orgs - - -class PersonalSerializer(serializers.ModelSerializer): - class Meta: - model = EmailUser - fields = ( - 'id', - 'last_name', - 'first_name', - ) - -class ContactSerializer(serializers.ModelSerializer): - class Meta: - model = EmailUser - fields = ( - 'id', - 'email', - 'phone_number', - 'mobile_number', - ) - - def validate(self, obj): - #Mobile and phone number for dbca user are updated from active directory so need to skip these users from validation. - domain=None - if obj['email']: - domain = obj['email'].split('@')[1] - if domain in settings.DEPT_DOMAINS: - return obj - else: - if not obj.get('phone_number') and not obj.get('mobile_number'): - raise serializers.ValidationError('You must provide a mobile/phone number') - return obj - -class EmailUserActionSerializer(serializers.ModelSerializer): - who = serializers.CharField(source='who.get_full_name') - - class Meta: - model = EmailUserAction - fields = '__all__' - -class EmailUserCommsSerializer(serializers.ModelSerializer): - class Meta: - model = EmailUserLogEntry - fields = '__all__' - -class CommunicationLogEntrySerializer(serializers.ModelSerializer): - customer = serializers.PrimaryKeyRelatedField(queryset=EmailUser.objects.all(),required=False) - documents = serializers.SerializerMethodField() - class Meta: - model = CommunicationsLogEntry - fields = ( - 'id', - 'customer', - 'to', - 'fromm', - 'cc', - 'log_type', - 'reference', - 'subject' - 'text', - 'created', - 'staff', - 'emailuser', - 'documents' - ) - - def get_documents(self,obj): - return [[d.name,d._file.url] for d in obj.documents.all()] - -class EmailUserLogEntrySerializer(CommunicationLogEntrySerializer): - documents = serializers.SerializerMethodField() - class Meta: - model = EmailUserLogEntry - fields = '__all__' - read_only_fields = ( - 'customer', - ) - - def get_documents(self,obj): - return [[d.name,d._file.url] for d in obj.documents.all()] diff --git a/commercialoperator/cron.py b/commercialoperator/cron.py deleted file mode 100644 index e9c2977806..0000000000 --- a/commercialoperator/cron.py +++ /dev/null @@ -1,24 +0,0 @@ -from datetime import date, timedelta - -from django.db.models import Q -from django.core import management -from django_cron import CronJobBase, Schedule -from django.conf import settings - -from commercialoperator.components.bookings.utils import oracle_integration - - -class OracleIntegrationCronJob(CronJobBase): - """ - To Test (shortly after RUN_AT_TIMES): - ./manage_co.py runcrons - """ - #RUN_AT_TIMES = ['04:05'] - RUN_AT_TIMES = [settings.CRON_RUN_AT_TIMES] - - schedule = Schedule(run_at_times=RUN_AT_TIMES) - code = 'cols.oracle_integration' - - def do(self): - oracle_integration(str(date.today()-timedelta(days=1)),False) - diff --git a/commercialoperator/data/initial_data.json b/commercialoperator/data/initial_data.json deleted file mode 100755 index ecf536aa23..0000000000 --- a/commercialoperator/data/initial_data.json +++ /dev/null @@ -1,239 +0,0 @@ -[ -{ - "model": "commercialoperator.applicationtype", - "pk": 1, - "fields": { - "name": "T Class", - "order": 1, - "visible": true - } -}, -{ - "model": "commercialoperator.applicationtype", - "pk": 2, - "fields": { - "name": "Filming", - "order": 2, - "visible": true - } -}, -{ - "model": "commercialoperator.applicationtype", - "pk": 3, - "fields": { - "name": "Event", - "order": 3, - "visible": true - } -}, -{ - "model": "commercialoperator.activitymatrix", - "pk": 1, - "fields": { - "name": "Commercial Operator", - "description": "testing", - "schema": [ - {} - ], - "replaced_by": null, - "version": 1, - "ordered": false - } -}, -{ - "model": "commercialoperator.proposaltype", - "pk": 1, - "fields": { - "description": "T Class Dummy", - "name": "T Class", - "schema": [ - {} - ], - "replaced_by": null, - "version": 1 - } -}, -{ - "model": "commercialoperator.proposalassessorgroup", - "pk": 1, - "fields": { - "name": "Default Group", - "region": null, - "default": true, - "members": [ - 255 - ] - } -}, -{ - "model": "commercialoperator.proposalapprovergroup", - "pk": 1, - "fields": { - "name": "Default Group", - "region": null, - "default": true, - "members": [ - 255 - ] - } -}, -{ - "model": "commercialoperator.proposal", - "pk": 1, - "fields": { - "proposal_type": "new_proposal", - "data": [ - { - "regionActivitySection": [ - { - "Sub-activity level 2": "", - "Sub-activity level 1": "", - "District": null, - "Management area": "", - "Region": null, - "ActivityType": "" - } - ] - } - ], - "assessor_data": null, - "comment_data": null, - "schema": [ - {} - ], - "proposed_issuance_approval": null, - "customer_status": "draft", - "applicant": 1, - "lodgement_number": "P000001", - "lodgement_sequence": 0, - "lodgement_date": null, - "proxy_applicant": null, - "submitter": 255, - "assigned_officer": null, - "assigned_approver": null, - "processing_status": "draft", - "id_check_status": "not_checked", - "compliance_check_status": "not_checked", - "character_check_status": "not_checked", - "review_status": "not_reviewed", - "approval": null, - "previous_application": null, - "proposed_decline_status": false, - "title": null, - "activity": "", - "tenure": null, - "region": null, - "district": null, - "application_type": 1, - "approval_level": "", - "approval_level_document": null, - "approval_comment": "" - } -}, -{ - "model": "commercialoperator.proposal", - "pk": 2, - "fields": { - "proposal_type": "new_proposal", - "data": [ - { - "regionActivitySection": [ - { - "Sub-activity level 2": "", - "Sub-activity level 1": "", - "District": null, - "Management area": "", - "Region": null, - "ActivityType": "" - } - ] - } - ], - "assessor_data": null, - "comment_data": null, - "schema": [ - {} - ], - "proposed_issuance_approval": null, - "customer_status": "draft", - "applicant": 1, - "lodgement_number": "P000002", - "lodgement_sequence": 0, - "lodgement_date": null, - "proxy_applicant": null, - "submitter": 255, - "assigned_officer": null, - "assigned_approver": null, - "processing_status": "draft", - "id_check_status": "not_checked", - "compliance_check_status": "not_checked", - "character_check_status": "not_checked", - "review_status": "not_reviewed", - "approval": null, - "previous_application": null, - "proposed_decline_status": false, - "title": null, - "activity": "", - "tenure": null, - "region": null, - "district": null, - "application_type": 1, - "approval_level": "", - "approval_level_document": null, - "approval_comment": "" - } -}, -{ - "model": "commercialoperator.proposal", - "pk": 3, - "fields": { - "proposal_type": "new_proposal", - "data": [ - { - "regionActivitySection": [ - { - "Sub-activity level 2": "", - "Sub-activity level 1": "", - "District": null, - "Management area": "", - "Region": null, - "ActivityType": "" - } - ] - } - ], - "assessor_data": null, - "comment_data": null, - "schema": [ - {} - ], - "proposed_issuance_approval": null, - "customer_status": "draft", - "applicant": 1, - "lodgement_number": "P000003", - "lodgement_sequence": 0, - "lodgement_date": null, - "proxy_applicant": null, - "submitter": 255, - "assigned_officer": null, - "assigned_approver": null, - "processing_status": "draft", - "id_check_status": "not_checked", - "compliance_check_status": "not_checked", - "character_check_status": "not_checked", - "review_status": "not_reviewed", - "approval": null, - "previous_application": null, - "proposed_decline_status": false, - "title": null, - "activity": "", - "tenure": null, - "region": null, - "district": null, - "application_type": 1, - "approval_level": "", - "approval_level_document": null, - "approval_comment": "" - } -} -] diff --git a/commercialoperator/exceptions.py b/commercialoperator/exceptions.py deleted file mode 100755 index 75d36dea44..0000000000 --- a/commercialoperator/exceptions.py +++ /dev/null @@ -1,27 +0,0 @@ -from rest_framework.exceptions import APIException,PermissionDenied - -class ReferralNotAuthorized(PermissionDenied): - default_detail = 'You are not authorised to work on this referral' - default_code = 'referral_not_authorized' - -class ProposalNotAuthorized(PermissionDenied): - default_detail = 'You are not authorised to work on this proposal' - default_code = 'proposal_not_authorized' - -class ReferralCanNotSend(PermissionDenied): - default_detail = 'You can only send referrals sent from an assessor' - default_code = 'referral_level_send_unauthorized' - -class ProposalReferralCannotBeSent(PermissionDenied): - default_detail = 'Referrals can only be sent if it is in the right processing status' - default_code = 'proposal_referral_cannot_be_sent' - -class ProposalNotComplete(APIException): - status_code = 400 - default_detail = 'The proposal is not complete' - default_code = 'proposal_incoplete' - -class ProposalMissingFields(APIException): - status_code = 400 - default_detail = 'The proposal has missing required fields' - default_code = 'proposal_missing_fields' diff --git a/commercialoperator/fixtures/districts.json b/commercialoperator/fixtures/districts.json deleted file mode 100755 index 8fee18e760..0000000000 --- a/commercialoperator/fixtures/districts.json +++ /dev/null @@ -1,249 +0,0 @@ -[ -{ - "pk": 1, - "model": "commercialoperator.region", - "fields": { - "name": "Goldfields" - } -}, -{ - "pk": 2, - "model": "commercialoperator.region", - "fields": { - "name": "Kimberley" - } -}, -{ - "pk": 3, - "model": "commercialoperator.region", - "fields": { - "name": "Midwest" - } -}, -{ - "pk": 4, - "model": "commercialoperator.region", - "fields": { - "name": "Pilbara" - } -}, -{ - "pk": 5, - "model": "commercialoperator.region", - "fields": { - "name": "South Coast" - } -}, -{ - "pk": 6, - "model": "commercialoperator.region", - "fields": { - "name": "South West", - "forest_region": true - } -}, -{ - "pk": 7, - "model": "commercialoperator.region", - "fields": { - "name": "Swan", - "forest_region": true - } -}, -{ - "pk": 8, - "model": "commercialoperator.region", - "fields": { - "name": "Warren", - "forest_region": true - } -}, -{ - "pk": 9, - "model": "commercialoperator.region", - "fields": { - "name": "Wheatbelt" - } -}, - -{ - "pk": 1, - "model": "commercialoperator.district", - "fields": { - "archive_date": null, - "region": 1, - "code": "GLD", - "name": "Goldfields Region" - } -}, -{ - "pk": 2, - "model": "commercialoperator.district", - "fields": { - "archive_date": null, - "region": 2, - "code": "EKM", - "name": "East Kimberley" - } -}, -{ - "pk": 3, - "model": "commercialoperator.district", - "fields": { - "archive_date": null, - "region": 2, - "code": "WKM", - "name": "West Kimberley" - } -}, -{ - "pk": 4, - "model": "commercialoperator.district", - "fields": { - "archive_date": null, - "region": 3, - "code": "GER", - "name": "Geraldton" - } -}, -{ - "pk": 5, - "model": "commercialoperator.district", - "fields": { - "archive_date": null, - "region": 3, - "code": "MOR", - "name": "Moora" - } -}, -{ - "pk": 6, - "model": "commercialoperator.district", - "fields": { - "archive_date": null, - "region": 3, - "code": "SHB", - "name": "Shark Bay" - } -}, -{ - "pk": 7, - "model": "commercialoperator.district", - "fields": { - "archive_date": null, - "region": 4, - "code": "EXM", - "name": "Exmouth" - } -}, -{ - "pk": 8, - "model": "commercialoperator.district", - "fields": { - "archive_date": null, - "region": 4, - "code": "PIL", - "name": "Pilbara Region" - } -}, -{ - "pk": 9, - "model": "commercialoperator.district", - "fields": { - "archive_date": null, - "region": 5, - "code": "ALB", - "name": "Albany" - } -}, -{ - "pk": 10, - "model": "commercialoperator.district", - "fields": { - "archive_date": null, - "region": 5, - "code": "ESP", - "name": "Esperance" - } -}, -{ - "pk": 11, - "model": "commercialoperator.district", - "fields": { - "archive_date": null, - "region": 6, - "code": "BWD", - "name": "Blackwood" - } -}, -{ - "pk": 12, - "model": "commercialoperator.district", - "fields": { - "archive_date": null, - "region": 6, - "code": "WTN", - "name": "Wellington" - } -}, -{ - "pk": 13, - "model": "commercialoperator.district", - "fields": { - "archive_date": null, - "region": 7, - "code": "PHS", - "name": "Perth Hills" - } -}, -{ - "pk": 14, - "model": "commercialoperator.district", - "fields": { - "archive_date": null, - "region": 7, - "code": "SWC", - "name": "Swan Coastal" - } -}, -{ - "pk": 15, - "model": "commercialoperator.district", - "fields": { - "archive_date": null, - "region": 8, - "code": "DON", - "name": "Donnelly" - } -}, -{ - "pk": 16, - "model": "commercialoperator.district", - "fields": { - "archive_date": null, - "region": 8, - "code": "FRK", - "name": "Frankland" - } -}, -{ - "pk": 17, - "model": "commercialoperator.district", - "fields": { - "archive_date": null, - "region": 9, - "code": "CWB", - "name": "Central Wheatbelt" - } -}, -{ - "pk": 18, - "model": "commercialoperator.district", - "fields": { - "archive_date": null, - "region": 9, - "code": "SWB", - "name": "Wheatbelt Region" - } -} -] diff --git a/commercialoperator/fixtures/dumpdata_uat_25Jul2019.json b/commercialoperator/fixtures/dumpdata_uat_25Jul2019.json deleted file mode 100644 index 47adcf6b17..0000000000 --- a/commercialoperator/fixtures/dumpdata_uat_25Jul2019.json +++ /dev/null @@ -1,1766 +0,0 @@ -[ -{ - "model": "commercialoperator.accesstype", - "pk": 1, - "fields": { - "name": "Coach", - "visible": true - } -}, -{ - "model": "commercialoperator.accesstype", - "pk": 2, - "fields": { - "name": "Minibus", - "visible": true - } -}, -{ - "model": "commercialoperator.accesstype", - "pk": 3, - "fields": { - "name": "4WD", - "visible": true - } -}, -{ - "model": "commercialoperator.activity", - "pk": 9, - "fields": { - "name": "Abseiling", - "visible": true, - "activity_category": 5 - } -}, -{ - "model": "commercialoperator.activity", - "pk": 10, - "fields": { - "name": "Bushwalking", - "visible": true, - "activity_category": 5 - } -}, -{ - "model": "commercialoperator.activity", - "pk": 11, - "fields": { - "name": "Cruise ships", - "visible": true, - "activity_category": 6 - } -}, -{ - "model": "commercialoperator.activity", - "pk": 12, - "fields": { - "name": "Boat tours or charters", - "visible": true, - "activity_category": 6 - } -}, -{ - "model": "commercialoperator.activity", - "pk": 13, - "fields": { - "name": "Waterskiing", - "visible": true, - "activity_category": 8 - } -}, -{ - "model": "commercialoperator.activity", - "pk": 14, - "fields": { - "name": "Sailing Tours", - "visible": true, - "activity_category": 8 - } -}, -{ - "model": "commercialoperator.activity", - "pk": 15, - "fields": { - "name": "Camping", - "visible": true, - "activity_category": 5 - } -}, -{ - "model": "commercialoperator.activity", - "pk": 16, - "fields": { - "name": "Canoening", - "visible": true, - "activity_category": 5 - } -}, -{ - "model": "commercialoperator.activity", - "pk": 17, - "fields": { - "name": "Caving", - "visible": true, - "activity_category": 5 - } -}, -{ - "model": "commercialoperator.activity", - "pk": 18, - "fields": { - "name": "Rafting", - "visible": true, - "activity_category": 5 - } -}, -{ - "model": "commercialoperator.activity", - "pk": 19, - "fields": { - "name": "Rock Climbing", - "visible": true, - "activity_category": 5 - } -}, -{ - "model": "commercialoperator.activity", - "pk": 20, - "fields": { - "name": "Mountain Biking", - "visible": true, - "activity_category": 5 - } -}, -{ - "model": "commercialoperator.activitycategory", - "pk": 5, - "fields": { - "name": "default", - "visible": true, - "activity_type": "land" - } -}, -{ - "model": "commercialoperator.activitycategory", - "pk": 6, - "fields": { - "name": "Motorised boating", - "visible": true, - "activity_type": "marine" - } -}, -{ - "model": "commercialoperator.activitycategory", - "pk": 7, - "fields": { - "name": "Motorised watersports", - "visible": true, - "activity_type": "marine" - } -}, -{ - "model": "commercialoperator.activitycategory", - "pk": 8, - "fields": { - "name": "Non-motorised watersports", - "visible": true, - "activity_type": "marine" - } -}, -{ - "model": "commercialoperator.checklistquestion", - "pk": 1, - "fields": { - "text": "Assessor Question 1", - "list_type": "assessor_list", - "obsolete": false - } -}, -{ - "model": "commercialoperator.checklistquestion", - "pk": 2, - "fields": { - "text": "Assessor Question 2", - "list_type": "assessor_list", - "obsolete": false - } -}, -{ - "model": "commercialoperator.checklistquestion", - "pk": 3, - "fields": { - "text": "Assessor Question 3", - "list_type": "assessor_list", - "obsolete": false - } -}, -{ - "model": "commercialoperator.checklistquestion", - "pk": 4, - "fields": { - "text": "Assessor Question 4", - "list_type": "assessor_list", - "obsolete": false - } -}, -{ - "model": "commercialoperator.checklistquestion", - "pk": 5, - "fields": { - "text": "Referral Question 1", - "list_type": "referral_list", - "obsolete": false - } -}, -{ - "model": "commercialoperator.checklistquestion", - "pk": 6, - "fields": { - "text": "Referral Question 2", - "list_type": "referral_list", - "obsolete": false - } -}, -{ - "model": "commercialoperator.checklistquestion", - "pk": 7, - "fields": { - "text": "Referral Question 3", - "list_type": "referral_list", - "obsolete": false - } -}, -{ - "model": "commercialoperator.globalsettings", - "pk": 1, - "fields": { - "key": "credit_facility_link", - "value": "https://parks.dpaw.wa.gov.au/park-finder" - } -}, -{ - "model": "commercialoperator.globalsettings", - "pk": 2, - "fields": { - "key": "deed_poll", - "value": "https://parks.dpaw.wa.gov.au/park-finder" - } -}, -{ - "model": "commercialoperator.globalsettings", - "pk": 3, - "fields": { - "key": "online_training_document", - "value": "https://parks.dpaw.wa.gov.au/park-finder" - } -}, -{ - "model": "commercialoperator.park", - "pk": 2, - "fields": { - "district": 9, - "name": "Albany district park one", - "code": "A1", - "park_type": "land", - "adult_price": "10.00", - "child_price": "7.00", - "oracle_code": "NNP439 GST", - "is_gst_exempt": false, - "allowed_activities": [ - 9 - ], - "allowed_access": [ - 3, - 1, - 2 - ] - } -}, -{ - "model": "commercialoperator.park", - "pk": 3, - "fields": { - "district": 2, - "name": "East Kimberley Park one", - "code": "EK2", - "park_type": "land", - "adult_price": "10.00", - "child_price": "7.00", - "oracle_code": "NNP445 GST", - "is_gst_exempt": false, - "allowed_activities": [ - 9, - 15, - 17 - ], - "allowed_access": [ - 3, - 1, - 2 - ] - } -}, -{ - "model": "commercialoperator.park", - "pk": 4, - "fields": { - "district": 15, - "name": "Rowley Shoal Marine Park", - "code": "R1", - "park_type": "marine", - "adult_price": "10.00", - "child_price": "7.00", - "oracle_code": "ABC123 GST", - "is_gst_exempt": false, - "allowed_activities": [], - "allowed_access": [] - } -}, -{ - "model": "commercialoperator.park", - "pk": 5, - "fields": { - "district": 12, - "name": "Wellington Marine Park", - "code": "W1", - "park_type": "marine", - "adult_price": "10.00", - "child_price": "7.00", - "oracle_code": "ABC123 GST", - "is_gst_exempt": false, - "allowed_activities": [], - "allowed_access": [] - } -}, -{ - "model": "commercialoperator.park", - "pk": 6, - "fields": { - "district": 1, - "name": "Goldfields park one", - "code": "GOP1", - "park_type": "land", - "adult_price": "10.00", - "child_price": "7.00", - "oracle_code": "ABC123 GST", - "is_gst_exempt": false, - "allowed_activities": [ - 9, - 15, - 16, - 17, - 19 - ], - "allowed_access": [ - 3, - 1, - 2 - ] - } -}, -{ - "model": "commercialoperator.park", - "pk": 7, - "fields": { - "district": 4, - "name": "Geraldton Park one", - "code": "GEP1", - "park_type": "land", - "adult_price": "10.00", - "child_price": "7.00", - "oracle_code": "ABC123 GST", - "is_gst_exempt": false, - "allowed_activities": [ - 9, - 15, - 16, - 19 - ], - "allowed_access": [ - 3, - 1, - 2 - ] - } -}, -{ - "model": "commercialoperator.park", - "pk": 8, - "fields": { - "district": 7, - "name": "Exmouth park one", - "code": "EXP1", - "park_type": "land", - "adult_price": "10.00", - "child_price": "7.00", - "oracle_code": "ABC123 GST", - "is_gst_exempt": false, - "allowed_activities": [ - 9, - 17, - 18 - ], - "allowed_access": [ - 3, - 1, - 2 - ] - } -}, -{ - "model": "commercialoperator.park", - "pk": 9, - "fields": { - "district": 11, - "name": "Blackwood park one", - "code": "BLK1", - "park_type": "land", - "adult_price": "0.00", - "child_price": "0.00", - "oracle_code": "ABC123 GST", - "is_gst_exempt": false, - "allowed_activities": [ - 9, - 10, - 16, - 19 - ], - "allowed_access": [ - 3, - 1, - 2 - ] - } -}, -{ - "model": "commercialoperator.park", - "pk": 10, - "fields": { - "district": 13, - "name": "Perth hills park one", - "code": "PHO1", - "park_type": "land", - "adult_price": "10.00", - "child_price": "7.00", - "oracle_code": "ABC123 GST", - "is_gst_exempt": false, - "allowed_activities": [ - 9, - 15, - 17, - 19 - ], - "allowed_access": [ - 3, - 1, - 2 - ] - } -}, -{ - "model": "commercialoperator.park", - "pk": 11, - "fields": { - "district": 15, - "name": "Donelly park one", - "code": "DON1", - "park_type": "land", - "adult_price": "0.00", - "child_price": "0.00", - "oracle_code": "ABC123 GST", - "is_gst_exempt": false, - "allowed_activities": [ - 9, - 15, - 19 - ], - "allowed_access": [ - 3, - 1, - 2 - ] - } -}, -{ - "model": "commercialoperator.park", - "pk": 12, - "fields": { - "district": 17, - "name": "Central park one", - "code": "CEN1", - "park_type": "land", - "adult_price": "0.00", - "child_price": "0.00", - "oracle_code": "ABC123 GST", - "is_gst_exempt": false, - "allowed_activities": [ - 10, - 15, - 19 - ], - "allowed_access": [ - 3, - 1, - 2 - ] - } -}, -{ - "model": "commercialoperator.park", - "pk": 13, - "fields": { - "district": 2, - "name": "East kimberley park two", - "code": "", - "park_type": "land", - "adult_price": "12.00", - "child_price": "5.00", - "oracle_code": "a123", - "is_gst_exempt": false, - "allowed_activities": [ - 9, - 10 - ], - "allowed_access": [ - 1, - 2 - ] - } -}, -{ - "model": "commercialoperator.park", - "pk": 14, - "fields": { - "district": 2, - "name": "Drysdale River NP", - "code": "", - "park_type": "land", - "adult_price": "0.00", - "child_price": "0.00", - "oracle_code": "ABC123 GST", - "is_gst_exempt": false, - "allowed_activities": [ - 10, - 15, - 16 - ], - "allowed_access": [] - } -}, -{ - "model": "commercialoperator.park", - "pk": 15, - "fields": { - "district": 2, - "name": "Mirima NP", - "code": "", - "park_type": "land", - "adult_price": "6.00", - "child_price": "6.00", - "oracle_code": "ABC123 GST", - "is_gst_exempt": false, - "allowed_activities": [ - 10 - ], - "allowed_access": [ - 3, - 1, - 2 - ] - } -}, -{ - "model": "commercialoperator.park", - "pk": 16, - "fields": { - "district": 2, - "name": "Purnululu NP", - "code": "", - "park_type": "land", - "adult_price": "6.00", - "child_price": "6.00", - "oracle_code": "ABC123 GST", - "is_gst_exempt": false, - "allowed_activities": [ - 10, - 15 - ], - "allowed_access": [ - 3 - ] - } -}, -{ - "model": "commercialoperator.park", - "pk": 17, - "fields": { - "district": 2, - "name": "Wolfe Creek Crater NP", - "code": "", - "park_type": "land", - "adult_price": "0.00", - "child_price": "0.00", - "oracle_code": "ABC123 GST", - "is_gst_exempt": false, - "allowed_activities": [ - 10, - 15 - ], - "allowed_access": [ - 3, - 1, - 2 - ] - } -}, -{ - "model": "commercialoperator.park", - "pk": 18, - "fields": { - "district": 2, - "name": "Lawley River NP", - "code": "", - "park_type": "land", - "adult_price": "0.00", - "child_price": "0.00", - "oracle_code": "ABC123 GST", - "is_gst_exempt": false, - "allowed_activities": [ - 10 - ], - "allowed_access": [] - } -}, -{ - "model": "commercialoperator.park", - "pk": 19, - "fields": { - "district": 2, - "name": "Prince Regent NP", - "code": "", - "park_type": "land", - "adult_price": "0.00", - "child_price": "0.00", - "oracle_code": "ABC123 GST", - "is_gst_exempt": false, - "allowed_activities": [ - 10 - ], - "allowed_access": [] - } -}, -{ - "model": "commercialoperator.park", - "pk": 20, - "fields": { - "district": 2, - "name": "Parry Lagoons NP", - "code": "", - "park_type": "land", - "adult_price": "0.00", - "child_price": "0.00", - "oracle_code": "ABC123 GST", - "is_gst_exempt": false, - "allowed_activities": [ - 10 - ], - "allowed_access": [ - 3, - 1, - 2 - ] - } -}, -{ - "model": "commercialoperator.park", - "pk": 21, - "fields": { - "district": 3, - "name": "Geikie Gorge NP", - "code": "", - "park_type": "land", - "adult_price": "0.00", - "child_price": "0.00", - "oracle_code": "ABC123 GST", - "is_gst_exempt": false, - "allowed_activities": [ - 10, - 16 - ], - "allowed_access": [ - 3, - 1, - 2 - ] - } -}, -{ - "model": "commercialoperator.park", - "pk": 22, - "fields": { - "district": 3, - "name": "King Leopold Ranges CP", - "code": "", - "park_type": "land", - "adult_price": "6.00", - "child_price": "6.00", - "oracle_code": "ABC123 GST", - "is_gst_exempt": false, - "allowed_activities": [ - 10, - 15 - ], - "allowed_access": [ - 3 - ] - } -}, -{ - "model": "commercialoperator.park", - "pk": 23, - "fields": { - "district": 3, - "name": "Tunnel Creek NP", - "code": "", - "park_type": "land", - "adult_price": "0.00", - "child_price": "0.00", - "oracle_code": "ABC123 GST", - "is_gst_exempt": false, - "allowed_activities": [ - 10, - 17 - ], - "allowed_access": [ - 3, - 1, - 2 - ] - } -}, -{ - "model": "commercialoperator.park", - "pk": 24, - "fields": { - "district": 3, - "name": "Windjana Gorge NP", - "code": "", - "park_type": "land", - "adult_price": "6.00", - "child_price": "6.00", - "oracle_code": "ABC123 GST", - "is_gst_exempt": false, - "allowed_activities": [ - 10, - 15 - ], - "allowed_access": [ - 3, - 1, - 2 - ] - } -}, -{ - "model": "commercialoperator.park", - "pk": 25, - "fields": { - "district": 8, - "name": "Collier Range NP", - "code": "", - "park_type": "land", - "adult_price": "0.00", - "child_price": "0.00", - "oracle_code": "ABC123 GST", - "is_gst_exempt": false, - "allowed_activities": [ - 10, - 15 - ], - "allowed_access": [ - 3 - ] - } -}, -{ - "model": "commercialoperator.park", - "pk": 26, - "fields": { - "district": 8, - "name": "Karijini NP", - "code": "", - "park_type": "land", - "adult_price": "6.00", - "child_price": "6.00", - "oracle_code": "ABC123 GST", - "is_gst_exempt": false, - "allowed_activities": [ - 9, - 10, - 15, - 19 - ], - "allowed_access": [ - 3, - 1, - 2 - ] - } -}, -{ - "model": "commercialoperator.park", - "pk": 27, - "fields": { - "district": 8, - "name": "Millstream Chichester NP", - "code": "", - "park_type": "land", - "adult_price": "6.00", - "child_price": "6.00", - "oracle_code": "ABC123 GST", - "is_gst_exempt": false, - "allowed_activities": [ - 9, - 10, - 15, - 19 - ], - "allowed_access": [ - 3, - 1, - 2 - ] - } -}, -{ - "model": "commercialoperator.park", - "pk": 28, - "fields": { - "district": 8, - "name": "Karlamilyi NP (formerly Rudall River NP)", - "code": "", - "park_type": "land", - "adult_price": "0.00", - "child_price": "0.00", - "oracle_code": "ABC123 GST", - "is_gst_exempt": false, - "allowed_activities": [ - 10, - 15 - ], - "allowed_access": [ - 3 - ] - } -}, -{ - "model": "commercialoperator.park", - "pk": 29, - "fields": { - "district": 8, - "name": "Dampier Archipelago (mixed tenure)", - "code": "", - "park_type": "land", - "adult_price": "0.00", - "child_price": "0.00", - "oracle_code": "ABC123 GST", - "is_gst_exempt": false, - "allowed_activities": [ - 10, - 15 - ], - "allowed_access": [] - } -}, -{ - "model": "commercialoperator.park", - "pk": 30, - "fields": { - "district": 8, - "name": "Montebello Islands CP", - "code": "", - "park_type": "land", - "adult_price": "0.00", - "child_price": "0.00", - "oracle_code": "ABC123 GST", - "is_gst_exempt": false, - "allowed_activities": [ - 10, - 15 - ], - "allowed_access": [] - } -}, -{ - "model": "commercialoperator.park", - "pk": 31, - "fields": { - "district": 7, - "name": "Cape Range NP", - "code": "", - "park_type": "land", - "adult_price": "6.00", - "child_price": "6.00", - "oracle_code": "ABC123 GST", - "is_gst_exempt": false, - "allowed_activities": [ - 9, - 10, - 15, - 17, - 19 - ], - "allowed_access": [ - 3, - 1, - 2 - ] - } -}, -{ - "model": "commercialoperator.park", - "pk": 32, - "fields": { - "district": 6, - "name": "Francois Peron NP", - "code": "", - "park_type": "land", - "adult_price": "6.00", - "child_price": "6.00", - "oracle_code": "ABC123 GST", - "is_gst_exempt": false, - "allowed_activities": [ - 10, - 15, - 16 - ], - "allowed_access": [ - 3, - 2 - ] - } -}, -{ - "model": "commercialoperator.park", - "pk": 33, - "fields": { - "district": 6, - "name": "Hamelin Pool MNR", - "code": "", - "park_type": "land", - "adult_price": "0.00", - "child_price": "0.00", - "oracle_code": "ABC123 GST", - "is_gst_exempt": false, - "allowed_activities": [ - 10 - ], - "allowed_access": [ - 3, - 2 - ] - } -}, -{ - "model": "commercialoperator.park", - "pk": 34, - "fields": { - "district": 6, - "name": "Shell Beach CP", - "code": "", - "park_type": "land", - "adult_price": "0.00", - "child_price": "0.00", - "oracle_code": "ABC123 GST", - "is_gst_exempt": false, - "allowed_activities": [ - 10 - ], - "allowed_access": [ - 3, - 1, - 2 - ] - } -}, -{ - "model": "commercialoperator.park", - "pk": 35, - "fields": { - "district": 4, - "name": "Kennedy Range NP", - "code": "", - "park_type": "land", - "adult_price": "0.00", - "child_price": "0.00", - "oracle_code": "ABC123 GST", - "is_gst_exempt": false, - "allowed_activities": [ - 10, - 15 - ], - "allowed_access": [ - 3, - 1, - 2 - ] - } -}, -{ - "model": "commercialoperator.park", - "pk": 36, - "fields": { - "district": 4, - "name": "Mt Augustus NP", - "code": "", - "park_type": "land", - "adult_price": "0.00", - "child_price": "0.00", - "oracle_code": "ABC123 GST", - "is_gst_exempt": false, - "allowed_activities": [ - 10 - ], - "allowed_access": [ - 3, - 1, - 2 - ] - } -}, -{ - "model": "commercialoperator.park", - "pk": 37, - "fields": { - "district": 4, - "name": "Coalseam CP", - "code": "", - "park_type": "land", - "adult_price": "0.00", - "child_price": "0.00", - "oracle_code": "ABC123 GST", - "is_gst_exempt": false, - "allowed_activities": [ - 10, - 15 - ], - "allowed_access": [ - 3, - 1, - 2 - ] - } -}, -{ - "model": "commercialoperator.park", - "pk": 38, - "fields": { - "district": 4, - "name": "Kalbarri NP", - "code": "", - "park_type": "land", - "adult_price": "6.00", - "child_price": "6.00", - "oracle_code": "ABC123 GST", - "is_gst_exempt": false, - "allowed_activities": [ - 9, - 10, - 16, - 18, - 19 - ], - "allowed_access": [] - } -}, -{ - "model": "commercialoperator.park", - "pk": 39, - "fields": { - "district": 5, - "name": "Alexander Morrison NP", - "code": "", - "park_type": "land", - "adult_price": "0.00", - "child_price": "0.00", - "oracle_code": "ABC123 GST", - "is_gst_exempt": false, - "allowed_activities": [ - 10 - ], - "allowed_access": [] - } -}, -{ - "model": "commercialoperator.park", - "pk": 40, - "fields": { - "district": 5, - "name": "Badgingarra NP", - "code": "", - "park_type": "land", - "adult_price": "0.00", - "child_price": "0.00", - "oracle_code": "ABC123 GST", - "is_gst_exempt": false, - "allowed_activities": [ - 10 - ], - "allowed_access": [] - } -}, -{ - "model": "commercialoperator.park", - "pk": 41, - "fields": { - "district": 5, - "name": "Drovers Cave NP", - "code": "", - "park_type": "land", - "adult_price": "0.00", - "child_price": "0.00", - "oracle_code": "ABC123 GST", - "is_gst_exempt": false, - "allowed_activities": [ - 10 - ], - "allowed_access": [] - } -}, -{ - "model": "commercialoperator.park", - "pk": 42, - "fields": { - "district": 5, - "name": "Lesueur NP", - "code": "", - "park_type": "land", - "adult_price": "6.00", - "child_price": "6.00", - "oracle_code": "ABC123 GST", - "is_gst_exempt": false, - "allowed_activities": [ - 10 - ], - "allowed_access": [ - 3, - 1, - 2 - ] - } -}, -{ - "model": "commercialoperator.park", - "pk": 43, - "fields": { - "district": 5, - "name": "Nambung NP", - "code": "", - "park_type": "land", - "adult_price": "6.00", - "child_price": "6.00", - "oracle_code": "ABC123 GST", - "is_gst_exempt": false, - "allowed_activities": [ - 10 - ], - "allowed_access": [ - 3, - 1, - 2 - ] - } -}, -{ - "model": "commercialoperator.park", - "pk": 44, - "fields": { - "district": 5, - "name": "Stockyard Gully [5(1)(g) reserve]", - "code": "", - "park_type": "land", - "adult_price": "0.00", - "child_price": "0.00", - "oracle_code": "ABC123 GST", - "is_gst_exempt": false, - "allowed_activities": [ - 10, - 17 - ], - "allowed_access": [ - 3 - ] - } -}, -{ - "model": "commercialoperator.park", - "pk": 45, - "fields": { - "district": 5, - "name": "Tathra NP", - "code": "", - "park_type": "land", - "adult_price": "0.00", - "child_price": "0.00", - "oracle_code": "ABC123 GST", - "is_gst_exempt": false, - "allowed_activities": [ - 10 - ], - "allowed_access": [] - } -}, -{ - "model": "commercialoperator.park", - "pk": 46, - "fields": { - "district": 5, - "name": "Watheroo NP", - "code": "", - "park_type": "land", - "adult_price": "0.00", - "child_price": "0.00", - "oracle_code": "ABC123 GST", - "is_gst_exempt": false, - "allowed_activities": [ - 10 - ], - "allowed_access": [ - 3, - 1, - 2 - ] - } -}, -{ - "model": "commercialoperator.question", - "pk": 1, - "fields": { - "question_text": "Are there more than 10 rules for absiling?", - "answer_one": "Yes", - "answer_two": "No", - "answer_three": "", - "answer_four": "", - "correct_answer": "answer_one" - } -}, -{ - "model": "commercialoperator.question", - "pk": 2, - "fields": { - "question_text": "Are you allowed to abseil after sunset?", - "answer_one": "Yes", - "answer_two": "No", - "answer_three": "Neither", - "answer_four": "", - "correct_answer": "answer_two" - } -}, -{ - "model": "commercialoperator.question", - "pk": 3, - "fields": { - "question_text": "Is a free fall an acceptable method for abseiling?", - "answer_one": "Yes", - "answer_two": "No", - "answer_three": "Neither", - "answer_four": "both", - "correct_answer": "answer_three" - } -}, -{ - "model": "commercialoperator.section", - "pk": 1, - "fields": { - "name": "Map 1", - "visible": true, - "trail": 1, - "doc_url": "https://parks.dpaw.wa.gov.au/park-finder" - } -}, -{ - "model": "commercialoperator.section", - "pk": 2, - "fields": { - "name": "Map 2", - "visible": true, - "trail": 1, - "doc_url": "" - } -}, -{ - "model": "commercialoperator.section", - "pk": 3, - "fields": { - "name": "Map 1", - "visible": true, - "trail": 3, - "doc_url": "https://parks.dpaw.wa.gov.au/park-finder" - } -}, -{ - "model": "commercialoperator.section", - "pk": 4, - "fields": { - "name": "Map 2", - "visible": true, - "trail": 3, - "doc_url": "" - } -}, -{ - "model": "commercialoperator.section", - "pk": 5, - "fields": { - "name": "Map 1", - "visible": true, - "trail": 2, - "doc_url": "https://parks.dpaw.wa.gov.au/park-finder" - } -}, -{ - "model": "commercialoperator.section", - "pk": 6, - "fields": { - "name": "Map 2", - "visible": true, - "trail": 2, - "doc_url": "" - } -}, -{ - "model": "commercialoperator.trail", - "pk": 1, - "fields": { - "name": "Bibbulmun Track", - "code": "T1", - "allowed_activities": [ - 10 - ] - } -}, -{ - "model": "commercialoperator.trail", - "pk": 2, - "fields": { - "name": "Munda Bidi Trail", - "code": "T2", - "allowed_activities": [ - 9, - 10 - ] - } -}, -{ - "model": "commercialoperator.trail", - "pk": 3, - "fields": { - "name": "Cape to Cape Track", - "code": "T3", - "allowed_activities": [ - 10 - ] - } -}, -{ - "model": "commercialoperator.zone", - "pk": 1, - "fields": { - "name": "Sanctuary zone", - "visible": true, - "park": 4, - "allowed_activities": [ - 11, - 13 - ] - } -}, -{ - "model": "commercialoperator.zone", - "pk": 2, - "fields": { - "name": "Water zone", - "visible": true, - "park": 4, - "allowed_activities": [ - 12, - 14, - 13 - ] - } -}, -{ - "model": "commercialoperator.zone", - "pk": 3, - "fields": { - "name": "Sanctuary zone", - "visible": true, - "park": 5, - "allowed_activities": [ - 12, - 11, - 14 - ] - } -}, -{ - "model": "commercialoperator.region", - "pk": 1, - "fields": { - "name": "Goldfields", - "forest_region": false - } -}, -{ - "model": "commercialoperator.region", - "pk": 2, - "fields": { - "name": "Kimberley", - "forest_region": false - } -}, -{ - "model": "commercialoperator.region", - "pk": 3, - "fields": { - "name": "Midwest", - "forest_region": false - } -}, -{ - "model": "commercialoperator.region", - "pk": 4, - "fields": { - "name": "Pilbara", - "forest_region": false - } -}, -{ - "model": "commercialoperator.region", - "pk": 5, - "fields": { - "name": "South Coast", - "forest_region": false - } -}, -{ - "model": "commercialoperator.region", - "pk": 6, - "fields": { - "name": "South West", - "forest_region": true - } -}, -{ - "model": "commercialoperator.region", - "pk": 7, - "fields": { - "name": "Swan", - "forest_region": true - } -}, -{ - "model": "commercialoperator.region", - "pk": 8, - "fields": { - "name": "Warren", - "forest_region": true - } -}, -{ - "model": "commercialoperator.region", - "pk": 9, - "fields": { - "name": "Wheatbelt", - "forest_region": false - } -}, -{ - "model": "commercialoperator.district", - "pk": 1, - "fields": { - "region": 1, - "name": "Goldfields Region", - "code": "GLD", - "archive_date": null - } -}, -{ - "model": "commercialoperator.district", - "pk": 2, - "fields": { - "region": 2, - "name": "East Kimberley", - "code": "EKM", - "archive_date": null - } -}, -{ - "model": "commercialoperator.district", - "pk": 3, - "fields": { - "region": 2, - "name": "West Kimberley", - "code": "WKM", - "archive_date": null - } -}, -{ - "model": "commercialoperator.district", - "pk": 4, - "fields": { - "region": 3, - "name": "Geraldton", - "code": "GER", - "archive_date": null - } -}, -{ - "model": "commercialoperator.district", - "pk": 5, - "fields": { - "region": 3, - "name": "Moora", - "code": "MOR", - "archive_date": null - } -}, -{ - "model": "commercialoperator.district", - "pk": 6, - "fields": { - "region": 3, - "name": "Shark Bay", - "code": "SHB", - "archive_date": null - } -}, -{ - "model": "commercialoperator.district", - "pk": 7, - "fields": { - "region": 4, - "name": "Exmouth", - "code": "EXM", - "archive_date": null - } -}, -{ - "model": "commercialoperator.district", - "pk": 8, - "fields": { - "region": 4, - "name": "Pilbara Region", - "code": "PIL", - "archive_date": null - } -}, -{ - "model": "commercialoperator.district", - "pk": 9, - "fields": { - "region": 5, - "name": "Albany", - "code": "ALB", - "archive_date": null - } -}, -{ - "model": "commercialoperator.district", - "pk": 10, - "fields": { - "region": 5, - "name": "Esperance", - "code": "ESP", - "archive_date": null - } -}, -{ - "model": "commercialoperator.district", - "pk": 11, - "fields": { - "region": 6, - "name": "Blackwood", - "code": "BWD", - "archive_date": null - } -}, -{ - "model": "commercialoperator.district", - "pk": 12, - "fields": { - "region": 6, - "name": "Wellington", - "code": "WTN", - "archive_date": null - } -}, -{ - "model": "commercialoperator.district", - "pk": 13, - "fields": { - "region": 7, - "name": "Perth Hills", - "code": "PHS", - "archive_date": null - } -}, -{ - "model": "commercialoperator.district", - "pk": 14, - "fields": { - "region": 7, - "name": "Swan Coastal", - "code": "SWC", - "archive_date": null - } -}, -{ - "model": "commercialoperator.district", - "pk": 15, - "fields": { - "region": 8, - "name": "Donnelly", - "code": "DON", - "archive_date": null - } -}, -{ - "model": "commercialoperator.district", - "pk": 16, - "fields": { - "region": 8, - "name": "Frankland", - "code": "FRK", - "archive_date": null - } -}, -{ - "model": "commercialoperator.district", - "pk": 17, - "fields": { - "region": 9, - "name": "Central Wheatbelt", - "code": "CWB", - "archive_date": null - } -}, -{ - "model": "commercialoperator.district", - "pk": 18, - "fields": { - "region": 9, - "name": "Wheatbelt Region", - "code": "SWB", - "archive_date": null - } -}, -{ - "model": "commercialoperator.applicationtype", - "pk": 1, - "fields": { - "name": "T Class", - "order": 1, - "visible": true, - "max_renewals": null, - "max_renewal_period": null, - "application_fee": "117.00", - "oracle_code": "GGE53 EXEMPT", - "is_gst_exempt": true - } -}, -{ - "model": "commercialoperator.applicationtype", - "pk": 2, - "fields": { - "name": "Filming", - "order": 2, - "visible": false, - "max_renewals": null, - "max_renewal_period": null, - "application_fee": "40.00", - "oracle_code": "ABC123 GST", - "is_gst_exempt": true - } -}, -{ - "model": "commercialoperator.applicationtype", - "pk": 3, - "fields": { - "name": "Event", - "order": 2, - "visible": false, - "max_renewals": null, - "max_renewal_period": null, - "application_fee": "117.00", - "oracle_code": "ABC123 GST", - "is_gst_exempt": true - } -}, -{ - "model": "commercialoperator.applicationtype", - "pk": 6, - "fields": { - "name": "E Class", - "order": 0, - "visible": false, - "max_renewals": 1, - "max_renewal_period": 5, - "application_fee": "117.00", - "oracle_code": "ABC123 GST", - "is_gst_exempt": true - } -}, -{ - "model": "commercialoperator.proposaltype", - "pk": 1, - "fields": { - "description": "T Class Dummy", - "name": "T Class", - "schema": [ - {} - ], - "replaced_by": null, - "version": 1 - } -}, -{ - "model": "commercialoperator.proposaltype", - "pk": 2, - "fields": { - "description": "Filming Dummy", - "name": "Filming", - "schema": [ - {} - ], - "replaced_by": null, - "version": 1 - } -}, -{ - "model": "commercialoperator.proposaltype", - "pk": 3, - "fields": { - "description": "Event", - "name": "Event", - "schema": [ - {} - ], - "replaced_by": null, - "version": 1 - } -}, -{ - "model": "commercialoperator.proposaltype", - "pk": 4, - "fields": { - "description": "E Class", - "name": "E Class", - "schema": [ - {} - ], - "replaced_by": null, - "version": 1 - } -} -] diff --git a/commercialoperator/forms.py b/commercialoperator/forms.py deleted file mode 100755 index 425a03d0e8..0000000000 --- a/commercialoperator/forms.py +++ /dev/null @@ -1,123 +0,0 @@ -from __future__ import unicode_literals -from crispy_forms.bootstrap import FormActions -from crispy_forms.helper import FormHelper -from crispy_forms.layout import Layout, Submit -from django.contrib.auth import get_user_model -from django.forms import Form, ModelForm, CharField, ValidationError, EmailField - -from ledger.accounts.models import Profile, Address, Organisation - - -User = get_user_model() - - -class LoginForm(Form): - email = EmailField(max_length=254) - -class PersonalForm(ModelForm): - - class Meta: - model = User - fields = ['first_name', 'last_name'] - - def __init__(self, *args, **kwargs): - super(ProfileForm, self).__init__(*args, **kwargs) - self.helper = BaseFormHelper(self) - self.helper.form_id = 'id_form_emailuserprofile_update' - self.helper.attrs = {'novalidate': ''} - # Define the form layout. - self.helper.layout = Layout( - 'first_name', 'last_name', - FormActions( - Submit('save', 'Save', css_class='btn-lg'), - Submit('cancel', 'Cancel') - ) - ) - -class ContactForm(ModelForm): - - class Meta: - model = User - fields = ['email', 'phone_number','mobile_number'] - - def __init__(self, *args, **kwargs): - super(ProfileForm, self).__init__(*args, **kwargs) - self.helper = BaseFormHelper(self) - self.helper.form_id = 'id_form_emailuserprofile_update' - self.helper.attrs = {'novalidate': ''} - # Define the form layout. - self.helper.layout = Layout( - 'phone_number', 'mobile_number','email', - FormActions( - Submit('save', 'Save', css_class='btn-lg'), - Submit('cancel', 'Cancel') - ) - ) - - -class AddressForm(ModelForm): - - class Meta: - model = Address - fields = ['line1', 'line2', 'locality', 'state', 'postcode'] - - def __init__(self, *args, **kwargs): - super(AddressForm, self).__init__(*args, **kwargs) - self.helper = BaseFormHelper(self) - self.helper.form_id = 'id_form_address' - self.helper.attrs = {'novalidate': ''} - self.helper.add_input(Submit('save', 'Save', css_class='btn-lg')) - self.helper.add_input(Submit('cancel', 'Cancel')) - - -class OrganisationAdminForm(ModelForm): - """ModelForm that is used in the Django admin site. - """ - model = Organisation - - def clean_abn(self): - data = self.cleaned_data['abn'] - # If it's changed, check for any existing organisations with the same ABN. - if data and self.instance.abn != data and Organisation.objects.filter(abn=data).exists(): - raise ValidationError('An organisation with this ABN already exists.') - return data - - -class OrganisationForm(OrganisationAdminForm): - - class Meta: - model = Organisation - fields = ['name', 'abn', 'identification'] - - def __init__(self, *args, **kwargs): - super(OrganisationForm, self).__init__(*args, **kwargs) - self.fields['name'].label = 'Company name' - self.fields['identification'].label = 'Certificate of incorporation' - self.fields['identification'].help_text = 'Electronic copy of current certificate (e.g. image/PDF)' - self.helper = BaseFormHelper(self) - self.helper.form_id = 'id_form_organisation' - self.helper.attrs = {'novalidate': ''} - self.helper.add_input(Submit('save', 'Save', css_class='btn-lg')) - self.helper.add_input(Submit('cancel', 'Cancel')) - - -class DelegateAccessForm(Form): - - def __init__(self, *args, **kwargs): - super(DelegateAccessForm, self).__init__(*args, **kwargs) - self.helper = BaseFormHelper(self) - self.helper.add_input(Submit('confirm', 'Confirm', css_class='btn-lg')) - self.helper.add_input(Submit('cancel', 'Cancel')) - - -class UnlinkDelegateForm(ModelForm): - - class Meta: - model = Organisation - exclude = ['name', 'abn', 'identification', 'postal_address', 'billing_address', 'delegates'] - - def __init__(self, *args, **kwargs): - super(UnlinkDelegateForm, self).__init__(*args, **kwargs) - self.helper = BaseFormHelper(self) - self.helper.add_input(Submit('unlink', 'Unlink user', css_class='btn-lg btn-danger')) - self.helper.add_input(Submit('cancel', 'Cancel')) diff --git a/commercialoperator/frontend/commercialoperator/.babelrc b/commercialoperator/frontend/commercialoperator/.babelrc deleted file mode 100755 index d3e028e0b2..0000000000 --- a/commercialoperator/frontend/commercialoperator/.babelrc +++ /dev/null @@ -1,15 +0,0 @@ -{ - "presets": [ - ["env", { "modules": false }], - "stage-2", - "es2015" - ], - "plugins": ["transform-runtime","transform-vue-jsx"], - "comments": false, - "env": { - "test": { - "presets": ["env", "stage-2"], - "plugins": [ "istanbul" ] - } - } -} diff --git a/commercialoperator/frontend/commercialoperator/.editorconfig b/commercialoperator/frontend/commercialoperator/.editorconfig deleted file mode 100755 index 9d08a1a828..0000000000 --- a/commercialoperator/frontend/commercialoperator/.editorconfig +++ /dev/null @@ -1,9 +0,0 @@ -root = true - -[*] -charset = utf-8 -indent_style = space -indent_size = 2 -end_of_line = lf -insert_final_newline = true -trim_trailing_whitespace = true diff --git a/commercialoperator/frontend/commercialoperator/.eslintignore b/commercialoperator/frontend/commercialoperator/.eslintignore deleted file mode 100755 index 34af3774f3..0000000000 --- a/commercialoperator/frontend/commercialoperator/.eslintignore +++ /dev/null @@ -1,2 +0,0 @@ -build/*.js -config/*.js diff --git a/commercialoperator/frontend/commercialoperator/.eslintrc.js b/commercialoperator/frontend/commercialoperator/.eslintrc.js deleted file mode 100755 index b73a586a87..0000000000 --- a/commercialoperator/frontend/commercialoperator/.eslintrc.js +++ /dev/null @@ -1,28 +0,0 @@ -// http://eslint.org/docs/user-guide/configuring - -module.exports = { - root: true, - parser: 'babel-eslint', - parserOptions: { - sourceType: 'module' - }, - env: { - browser: true, - }, - // https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style - extends: 'standard', - // required to lint *.vue files - plugins: [ - 'html' - ], - // add your custom rules here - 'rules': { - // allow paren-less arrow functions - 'arrow-parens': 0, - // allow async-await - 'generator-star-spacing': 0, - // allow debugger during development - 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0, - 'indent': ['warn',4] - } -} diff --git a/commercialoperator/frontend/commercialoperator/.gitignore b/commercialoperator/frontend/commercialoperator/.gitignore deleted file mode 100755 index 3e1d210d65..0000000000 --- a/commercialoperator/frontend/commercialoperator/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -.DS_Store -node_modules/ -dist/ -npm-debug.log* -yarn-debug.log* -yarn-error.log* -test/unit/coverage -test/e2e/reports -selenium-debug.log diff --git a/commercialoperator/frontend/commercialoperator/.postcssrc.js b/commercialoperator/frontend/commercialoperator/.postcssrc.js deleted file mode 100755 index ea9a5ab875..0000000000 --- a/commercialoperator/frontend/commercialoperator/.postcssrc.js +++ /dev/null @@ -1,8 +0,0 @@ -// https://github.com/michael-ciniawsky/postcss-load-config - -module.exports = { - "plugins": { - // to edit target browsers: use "browserlist" field in package.json - "autoprefixer": {} - } -} diff --git a/commercialoperator/frontend/commercialoperator/README.md b/commercialoperator/frontend/commercialoperator/README.md deleted file mode 100755 index 95f6bccf4e..0000000000 --- a/commercialoperator/frontend/commercialoperator/README.md +++ /dev/null @@ -1,30 +0,0 @@ -# commercialoperator - -> A Vue.js project - -## Build Setup - -``` bash -# install dependencies -npm install - -# serve with hot reload at localhost:8080 -npm run dev - -# build for production with minification -npm run build - -# build for production and view the bundle analyzer report -npm run build --report - -# run unit tests -npm run unit - -# run e2e tests -npm run e2e - -# run all tests -npm test -``` - -For detailed explanation on how things work, checkout the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader). diff --git a/commercialoperator/frontend/commercialoperator/build/build.js b/commercialoperator/frontend/commercialoperator/build/build.js deleted file mode 100755 index 6b8add100c..0000000000 --- a/commercialoperator/frontend/commercialoperator/build/build.js +++ /dev/null @@ -1,35 +0,0 @@ -require('./check-versions')() - -process.env.NODE_ENV = 'production' - -var ora = require('ora') -var rm = require('rimraf') -var path = require('path') -var chalk = require('chalk') -var webpack = require('webpack') -var config = require('../config') -var webpackConfig = require('./webpack.prod.conf') - -var spinner = ora('building for production...') -spinner.start() - -rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => { - if (err) throw err - webpack(webpackConfig, function (err, stats) { - spinner.stop() - if (err) throw err - process.stdout.write(stats.toString({ - colors: true, - modules: false, - children: false, - chunks: false, - chunkModules: false - }) + '\n\n') - - console.log(chalk.cyan(' Build complete.\n')) - console.log(chalk.yellow( - ' Tip: built files are meant to be served over an HTTP server.\n' + - ' Opening index.html over file:// won\'t work.\n' - )) - }) -}) diff --git a/commercialoperator/frontend/commercialoperator/build/check-versions.js b/commercialoperator/frontend/commercialoperator/build/check-versions.js deleted file mode 100755 index 100f3a0fe3..0000000000 --- a/commercialoperator/frontend/commercialoperator/build/check-versions.js +++ /dev/null @@ -1,48 +0,0 @@ -var chalk = require('chalk') -var semver = require('semver') -var packageConfig = require('../package.json') -var shell = require('shelljs') -function exec (cmd) { - return require('child_process').execSync(cmd).toString().trim() -} - -var versionRequirements = [ - { - name: 'node', - currentVersion: semver.clean(process.version), - versionRequirement: packageConfig.engines.node - }, -] - -if (shell.which('npm')) { - versionRequirements.push({ - name: 'npm', - currentVersion: exec('npm --version'), - versionRequirement: packageConfig.engines.npm - }) -} - -module.exports = function () { - var warnings = [] - for (var i = 0; i < versionRequirements.length; i++) { - var mod = versionRequirements[i] - if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) { - warnings.push(mod.name + ': ' + - chalk.red(mod.currentVersion) + ' should be ' + - chalk.green(mod.versionRequirement) - ) - } - } - - if (warnings.length) { - console.log('') - console.log(chalk.yellow('To use this template, you must update following to modules:')) - console.log() - for (var i = 0; i < warnings.length; i++) { - var warning = warnings[i] - console.log(' ' + warning) - } - console.log() - process.exit(1) - } -} diff --git a/commercialoperator/frontend/commercialoperator/build/dev-client.js b/commercialoperator/frontend/commercialoperator/build/dev-client.js deleted file mode 100755 index 796b3f5048..0000000000 --- a/commercialoperator/frontend/commercialoperator/build/dev-client.js +++ /dev/null @@ -1,9 +0,0 @@ -/* eslint-disable */ -require('eventsource-polyfill') -var hotClient = require('webpack-hot-middleware/client?path=__webpack_hmr&noInfo=true&reload=true&dynamicPublicPath=true') - -hotClient.subscribe(function (event) { - if (event.action === 'reload') { - window.location.reload() - } -}) diff --git a/commercialoperator/frontend/commercialoperator/build/dev-server.js b/commercialoperator/frontend/commercialoperator/build/dev-server.js deleted file mode 100755 index b5b034ff4c..0000000000 --- a/commercialoperator/frontend/commercialoperator/build/dev-server.js +++ /dev/null @@ -1,97 +0,0 @@ -require('./check-versions')() - -var config = require('../config') -if (!process.env.NODE_ENV) { - process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV) -} -var opn = require('opn') -var path = require('path') -var express = require('express') -var webpack = require('webpack') -var proxyMiddleware = require('http-proxy-middleware') -var webpackConfig = process.env.NODE_ENV === 'testing' - ? require('./webpack.prod.conf') - : require('./webpack.dev.conf') - -// default port where dev server listens for incoming traffic -var port = process.env.PORT || config.dev.port -// automatically open browser, if not set will be false -var autoOpenBrowser = !!config.dev.autoOpenBrowser -// Define HTTP proxies to your custom API backend -// https://github.com/chimurai/http-proxy-middleware -var proxyTable = config.dev.proxyTable - -var app = express() -var compiler = webpack(webpackConfig) - -var devMiddleware = require('webpack-dev-middleware')(compiler, { - publicPath: webpackConfig.output.publicPath, - quiet: true, - headers: { - 'Access-Control-Allow-Credentials': true, - 'Access-Control-Allow-Origin': '*' - } -}) - -var hotMiddleware = require('webpack-hot-middleware')(compiler, { - //log: () => {}, - path: '/__webpack_hmr', - heartbeat: 10 * 1000, -}) -// force page reload when html-webpack-plugin template changes -compiler.plugin('compilation', function (compilation) { - compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) { - hotMiddleware.publish({ action: 'reload' }) - cb() - }) -}) - -// proxy api requests -// enable hot-reload and state-preserving -// compilation error display -app.use(hotMiddleware) - -Object.keys(proxyTable).forEach(function (context) { - var options = proxyTable[context] - if (typeof options === 'string') { - options = { target: options } - } - app.use(proxyMiddleware(options.filter || context, options)) -}) - -// handle fallback for HTML5 history API -app.use(require('connect-history-api-fallback')()) - -// serve webpack bundle output -app.use(devMiddleware) - - -// serve pure static assets -var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory) -app.use(staticPath, express.static('./static')) - -var uri = 'http://localhost:' + port - -var _resolve -var readyPromise = new Promise(resolve => { - _resolve = resolve -}) - -console.log('> Starting dev server...') -devMiddleware.waitUntilValid(() => { - console.log('> Listening at ' + uri + '\n') - // when env is testing, don't need open it - if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') { - opn(uri) - } - _resolve() -}) - -var server = app.listen(port) - -module.exports = { - ready: readyPromise, - close: () => { - server.close() - } -} diff --git a/commercialoperator/frontend/commercialoperator/build/utils.js b/commercialoperator/frontend/commercialoperator/build/utils.js deleted file mode 100755 index b1d54b4d6c..0000000000 --- a/commercialoperator/frontend/commercialoperator/build/utils.js +++ /dev/null @@ -1,71 +0,0 @@ -var path = require('path') -var config = require('../config') -var ExtractTextPlugin = require('extract-text-webpack-plugin') - -exports.assetsPath = function (_path) { - var assetsSubDirectory = process.env.NODE_ENV === 'production' - ? config.build.assetsSubDirectory - : config.dev.assetsSubDirectory - return path.posix.join(assetsSubDirectory, _path) -} - -exports.cssLoaders = function (options) { - options = options || {} - - var cssLoader = { - loader: 'css-loader', - options: { - minimize: process.env.NODE_ENV === 'production', - sourceMap: options.sourceMap - } - } - - // generate loader string to be used with extract text plugin - function generateLoaders (loader, loaderOptions) { - var loaders = [cssLoader] - if (loader) { - loaders.push({ - loader: loader + '-loader', - options: Object.assign({}, loaderOptions, { - sourceMap: options.sourceMap - }) - }) - } - - // Extract CSS when that option is specified - // (which is the case during production build) - if (options.extract) { - return ExtractTextPlugin.extract({ - use: loaders, - fallback: 'vue-style-loader' - }) - } else { - return ['vue-style-loader'].concat(loaders) - } - } - - // https://vue-loader.vuejs.org/en/configurations/extract-css.html - return { - css: generateLoaders(), - postcss: generateLoaders(), - less: generateLoaders('less'), - sass: generateLoaders('sass', { indentedSyntax: true }), - scss: generateLoaders('sass'), - stylus: generateLoaders('stylus'), - styl: generateLoaders('stylus') - } -} - -// Generate loaders for standalone style files (outside of .vue) -exports.styleLoaders = function (options) { - var output = [] - var loaders = exports.cssLoaders(options) - for (var extension in loaders) { - var loader = loaders[extension] - output.push({ - test: new RegExp('\\.' + extension + '$'), - use: loader - }) - } - return output -} diff --git a/commercialoperator/frontend/commercialoperator/build/vue-loader.conf.js b/commercialoperator/frontend/commercialoperator/build/vue-loader.conf.js deleted file mode 100755 index 7aee79bae4..0000000000 --- a/commercialoperator/frontend/commercialoperator/build/vue-loader.conf.js +++ /dev/null @@ -1,12 +0,0 @@ -var utils = require('./utils') -var config = require('../config') -var isProduction = process.env.NODE_ENV === 'production' - -module.exports = { - loaders: utils.cssLoaders({ - sourceMap: isProduction - ? config.build.productionSourceMap - : config.dev.cssSourceMap, - extract: isProduction - }) -} diff --git a/commercialoperator/frontend/commercialoperator/build/webpack.base.conf.js b/commercialoperator/frontend/commercialoperator/build/webpack.base.conf.js deleted file mode 100755 index 7a5a28b257..0000000000 --- a/commercialoperator/frontend/commercialoperator/build/webpack.base.conf.js +++ /dev/null @@ -1,96 +0,0 @@ -var path = require('path') -var utils = require('./utils') -var config = require('../config') -var vueLoaderConfig = require('./vue-loader.conf') -var webpack = require('webpack'); - -function resolve (dir) { - return path.join(__dirname, '..', dir) -} - -module.exports = { - entry: { - "babel-polyfill": "babel-polyfill", - "app": "./src/main.js" - }, - output: { - path: config.build.assetsRoot, - filename: '[name].js', - publicPath: process.env.NODE_ENV === 'production' - ? config.build.assetsPublicPath - : config.dev.assetsPublicPath - }, - resolve: { - extensions: ['.js', '.vue', '.json'], - alias: { - 'vue$': 'vue/dist/vue.esm.js', - '@': resolve('src'), - '@vue-utils': resolve('src/utils/vue'), - '@common-utils': resolve('src/components/common/'), - 'datetimepicker':'eonasdan-bootstrap-datetimepicker/build/js/bootstrap-datetimepicker.min.js', - 'easing':'jquery.easing/jquery.easing.js' - } - }, - module: { - rules: [ - /*{ - test: /\.(js|vue)$/, - loader: 'eslint-loader', - enforce: 'pre', - include: [resolve('src'), resolve('test')], - options: { - formatter: require('eslint-friendly-formatter') - } - },*/ - { - test: /\.vue$/, - loader: 'vue-loader', - options: vueLoaderConfig - }, - { - test: /bootstrap.+\.(js)$/, - loader: 'imports-loader?jQuery=jquery,$=jquery,this=>window' - }, - { - test: /jquery.easing.+\.(js)$/, - loader: 'imports-loader?jQuery=jquery,$=jquery,this=>window' - }, - { - test: /\.js$/, - loader: 'babel-loader', - include: [resolve('src'), resolve('test')] - }, - { - test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, - loader: 'url-loader', - options: { - limit: 10000, - name: utils.assetsPath('img/[name].[hash:7].[ext]') - } - }, - { - test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, - loader: 'url-loader', - options: { - limit: 10000, - name: utils.assetsPath('fonts/[name].[hash:7].[ext]') - } - }, - { - test: /datatables\.net.*/, - loader: 'imports-loader?define=>false,jquery=>jquery,$=>jquery' - } - ] - }, - plugins:[ - new webpack.ProvidePlugin({ - $: "jquery", - jQuery: "jquery", - "select2": "../node_modules/select2/dist/js/select2.full.min.js", - moment: "moment", - swal: 'sweetalert2', - _: 'lodash', - datetimepicker:"../node_modules/eonasdan-bootstrap-datetimepicker/build/js/bootstrap-datetimepicker.min.js" - }) - ] -} diff --git a/commercialoperator/frontend/commercialoperator/build/webpack.dev.conf.js b/commercialoperator/frontend/commercialoperator/build/webpack.dev.conf.js deleted file mode 100755 index 5078b1ac33..0000000000 --- a/commercialoperator/frontend/commercialoperator/build/webpack.dev.conf.js +++ /dev/null @@ -1,37 +0,0 @@ -var utils = require('./utils') -var webpack = require('webpack') -var config = require('../config') -var merge = require('webpack-merge') -var baseWebpackConfig = require('./webpack.base.conf') -var HtmlWebpackPlugin = require('html-webpack-plugin') -var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin') - -// add hot-reload related code to entry chunks -Object.keys(baseWebpackConfig.entry).forEach(function (name) { - baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name]) -}) -module.exports = merge(baseWebpackConfig, { - module: { - rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap }) - }, - // cheap-module-eval-source-map is faster for development - devtool: '#cheap-module-eval-source-map', - output: { - publicPath: 'http://'+config.dev.webpackHost.replace(/\"/g,"")+'/' - }, - plugins: [ - new webpack.DefinePlugin({ - 'process.env': config.dev.env - }), - // https://github.com/glenjamin/webpack-hot-middleware#installation--usage - new webpack.HotModuleReplacementPlugin(), - new webpack.NoEmitOnErrorsPlugin(), - // https://github.com/ampedandwired/html-webpack-plugin - new HtmlWebpackPlugin({ - filename: 'index.html', - template: 'index.html', - inject: true - }), - new FriendlyErrorsPlugin() - ] -}) diff --git a/commercialoperator/frontend/commercialoperator/build/webpack.prod.conf.js b/commercialoperator/frontend/commercialoperator/build/webpack.prod.conf.js deleted file mode 100755 index febbefd5af..0000000000 --- a/commercialoperator/frontend/commercialoperator/build/webpack.prod.conf.js +++ /dev/null @@ -1,125 +0,0 @@ -var path = require('path') -var utils = require('./utils') -var webpack = require('webpack') -var config = require('../config') -var merge = require('webpack-merge') -var baseWebpackConfig = require('./webpack.base.conf') -var CopyWebpackPlugin = require('copy-webpack-plugin') -var HtmlWebpackPlugin = require('html-webpack-plugin') -var ExtractTextPlugin = require('extract-text-webpack-plugin') -var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin') - -var env = process.env.NODE_ENV === 'testing' - ? require('../config/test.env') - : config.build.env - -var webpackConfig = merge(baseWebpackConfig, { - module: { - rules: utils.styleLoaders({ - sourceMap: config.build.productionSourceMap, - extract: true - }) - }, - //devtool: config.build.productionSourceMap ? '#source-map' : false, - devtool: '#cheap-module-eval-source-map', - output: { - path: config.build.assetsRoot, - filename: utils.assetsPath('js/[name].js'), - chunkFilename: utils.assetsPath('js/[id].[chunkhash].js') - }, - plugins: [ - // http://vuejs.github.io/vue-loader/en/workflow/production.html - new webpack.DefinePlugin({ - 'process.env': env - }), - new webpack.optimize.UglifyJsPlugin({ - compress: { - warnings: false - }, - sourceMap: true - }), - // extract css into its own file - new ExtractTextPlugin({ - filename: utils.assetsPath('css/[name].css') - }), - // Compress extracted CSS. We are using this plugin so that possible - // duplicated CSS from different components can be deduped. - new OptimizeCSSPlugin({ - cssProcessorOptions: { - safe: true - } - }), - // generate dist index.html with correct asset hash for caching. - // you can customize output by editing /index.html - // see https://github.com/ampedandwired/html-webpack-plugin - new HtmlWebpackPlugin({ - filename: process.env.NODE_ENV === 'testing' - ? 'index.html' - : config.build.index, - template: 'index.html', - inject: true, - minify: { - removeComments: true, - collapseWhitespace: true, - removeAttributeQuotes: true - // more options: - // https://github.com/kangax/html-minifier#options-quick-reference - }, - // necessary to consistently work with multiple chunks via CommonsChunkPlugin - chunksSortMode: 'dependency' - }), - // split vendor js into its own file - new webpack.optimize.CommonsChunkPlugin({ - name: 'vendor', - minChunks: function (module, count) { - // any required modules inside node_modules are extracted to vendor - return ( - module.resource && - /\.js$/.test(module.resource) && - module.resource.indexOf( - path.join(__dirname, '../node_modules') - ) === 0 - ) - } - }), - // extract webpack runtime and module manifest to its own file in order to - // prevent vendor hash from being updated whenever app bundle is updated - new webpack.optimize.CommonsChunkPlugin({ - name: 'manifest', - chunks: ['vendor'] - }), - // copy custom static assets - new CopyWebpackPlugin([ - { - from: path.resolve(__dirname, '../static'), - to: config.build.assetsSubDirectory, - ignore: ['.*'] - } - ]) - ] -}) - -if (config.build.productionGzip) { - var CompressionWebpackPlugin = require('compression-webpack-plugin') - - webpackConfig.plugins.push( - new CompressionWebpackPlugin({ - asset: '[path].gz[query]', - algorithm: 'gzip', - test: new RegExp( - '\\.(' + - config.build.productionGzipExtensions.join('|') + - ')$' - ), - threshold: 10240, - minRatio: 0.8 - }) - ) -} - -if (config.build.bundleAnalyzerReport) { - var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin - webpackConfig.plugins.push(new BundleAnalyzerPlugin()) -} - -module.exports = webpackConfig diff --git a/commercialoperator/frontend/commercialoperator/build/webpack.test.conf.js b/commercialoperator/frontend/commercialoperator/build/webpack.test.conf.js deleted file mode 100755 index d6c8c8dd31..0000000000 --- a/commercialoperator/frontend/commercialoperator/build/webpack.test.conf.js +++ /dev/null @@ -1,31 +0,0 @@ -// This is the webpack config used for unit tests. - -var utils = require('./utils') -var webpack = require('webpack') -var merge = require('webpack-merge') -var baseConfig = require('./webpack.base.conf') - -var webpackConfig = merge(baseConfig, { - // use inline sourcemap for karma-sourcemap-loader - module: { - rules: utils.styleLoaders() - }, - devtool: '#inline-source-map', - resolveLoader: { - alias: { - // necessary to to make lang="scss" work in test when using vue-loader's ?inject option - // see discussion at https://github.com/vuejs/vue-loader/issues/724 - 'scss-loader': 'sass-loader' - } - }, - plugins: [ - new webpack.DefinePlugin({ - 'process.env': require('../config/test.env') - }) - ] -}) - -// no need for app entry during tests -delete webpackConfig.entry - -module.exports = webpackConfig diff --git a/commercialoperator/frontend/commercialoperator/config/dev.env.js b/commercialoperator/frontend/commercialoperator/config/dev.env.js deleted file mode 100755 index 2f55f01f38..0000000000 --- a/commercialoperator/frontend/commercialoperator/config/dev.env.js +++ /dev/null @@ -1,8 +0,0 @@ -var merge = require('webpack-merge') -var prodEnv = require('./prod.env') - -module.exports = merge(prodEnv, { - NODE_ENV: '"development"', - WEBPACK_HOST: '"172.31.1.50:8080"', - PORT: '"8080"' -}) diff --git a/commercialoperator/frontend/commercialoperator/config/dev.env.js.dist b/commercialoperator/frontend/commercialoperator/config/dev.env.js.dist deleted file mode 100755 index 5a0318fcd1..0000000000 --- a/commercialoperator/frontend/commercialoperator/config/dev.env.js.dist +++ /dev/null @@ -1,7 +0,0 @@ -var merge = require('webpack-merge') -var prodEnv = require('./prod.env') -module.exports = merge(prodEnv, { - NODE_ENV: '"development"', - WEBPACK_HOST: '"10.6.209.13:3001"', - PORT: '"3001"' -}) diff --git a/commercialoperator/frontend/commercialoperator/config/index.js b/commercialoperator/frontend/commercialoperator/config/index.js deleted file mode 100755 index e995caa622..0000000000 --- a/commercialoperator/frontend/commercialoperator/config/index.js +++ /dev/null @@ -1,38 +0,0 @@ -// see http://vuejs-templates.github.io/webpack for documentation. -var path = require('path') -module.exports = { - build: { - env: require('./prod.env'), - index: path.resolve(__dirname, '../../../static/commercialoperator_vue/index.html'), - assetsRoot: path.resolve(__dirname, '../../../static/commercialoperator_vue'), - assetsSubDirectory: 'static', - assetsPublicPath: '/', - productionSourceMap: true, - // Gzip off by default as many popular static hosts such as - // Surge or Netlify already gzip all static assets for you. - // Before setting to `true`, make sure to: - // npm install --save-dev compression-webpack-plugin - productionGzip: false, - productionGzipExtensions: ['js', 'css'], - // Run the build command with an extra argument to - // View the bundle analyzer report after build finishes: - // `npm run build --report` - // Set to `true` or `false` to always turn it on or off - bundleAnalyzerReport: process.env.npm_config_report - }, - dev: { - env: require('./dev.env'), - port: require('./dev.env').PORT.replace(/\"/g,""), - webpackHost: require('./dev.env').WEBPACK_HOST, - autoOpenBrowser: true, - assetsSubDirectory: 'static', - assetsPublicPath: '/', - proxyTable: {}, - // CSS Sourcemaps off by default because relative paths are "buggy" - // with this option, according to the CSS-Loader README - // (https://github.com/webpack/css-loader#sourcemaps) - // In our experience, they generally work as expected, - // just be aware of this issue when enabling this option. - cssSourceMap: false - } -} diff --git a/commercialoperator/frontend/commercialoperator/config/prod.env.js b/commercialoperator/frontend/commercialoperator/config/prod.env.js deleted file mode 100755 index 773d263d31..0000000000 --- a/commercialoperator/frontend/commercialoperator/config/prod.env.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - NODE_ENV: '"production"' -} diff --git a/commercialoperator/frontend/commercialoperator/config/test.env.js b/commercialoperator/frontend/commercialoperator/config/test.env.js deleted file mode 100755 index 89f90deb22..0000000000 --- a/commercialoperator/frontend/commercialoperator/config/test.env.js +++ /dev/null @@ -1,6 +0,0 @@ -var merge = require('webpack-merge') -var devEnv = require('./dev.env') - -module.exports = merge(devEnv, { - NODE_ENV: '"testing"' -}) diff --git a/commercialoperator/frontend/commercialoperator/index.html b/commercialoperator/frontend/commercialoperator/index.html deleted file mode 100755 index 45c323a94a..0000000000 --- a/commercialoperator/frontend/commercialoperator/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Commercial Operator - - -
- - - diff --git a/commercialoperator/frontend/commercialoperator/package-lock.json b/commercialoperator/frontend/commercialoperator/package-lock.json deleted file mode 100644 index 8f8fc12805..0000000000 --- a/commercialoperator/frontend/commercialoperator/package-lock.json +++ /dev/null @@ -1,12187 +0,0 @@ -{ - "name": "commercialoperator", - "version": "1.0.0", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@babel/runtime": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.5.5.tgz", - "integrity": "sha512-28QvEGyQyNkB0/m2B4FU7IEZGK2NUrcMtT6BZEFALTguLk+AUT6ofsHtPk5QyjAdUkpMJ+/Em+quwz4HOt30AQ==", - "requires": { - "regenerator-runtime": "^0.13.2" - }, - "dependencies": { - "regenerator-runtime": { - "version": "0.13.3", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz", - "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==" - } - } - }, - "@riophae/vue-treeselect": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@riophae/vue-treeselect/-/vue-treeselect-0.1.0.tgz", - "integrity": "sha512-LLPHfMc9wL/ZWDiY2gRfsG8ze3Ra45JV/Ju5OotX/u47Gg7EyxUwanEQldQYeO0nOe81s/VSC5FUWddBDueMyA==", - "requires": { - "@babel/runtime": "^7.3.1", - "babel-helper-vue-jsx-merge-props": "^2.0.3", - "easings-css": "^1.0.0", - "fuzzysearch": "^1.0.3", - "is-promise": "^2.1.0", - "lodash": "^4.0.0", - "material-colors": "^1.2.6", - "watch-size": "^2.0.0" - } - }, - "@sindresorhus/is": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz", - "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==" - }, - "@types/node": { - "version": "10.12.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.0.tgz", - "integrity": "sha512-3TUHC3jsBAB7qVRGxT6lWyYo2v96BMmD2PTcl47H25Lu7UXtFH/2qqmKiVrnel6Ne//0TFYf6uvNX+HW2FRkLQ==", - "dev": true - }, - "@types/semver": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-5.5.0.tgz", - "integrity": "sha512-41qEJgBH/TWgo5NFSvBCJ1qkoi3Q6ONSF2avrHq1LVEZfYpdHmj0y9SuTK+u9ZhG1sYQKBL1AWXKyLWP4RaUoQ==", - "dev": true - }, - "abbrev": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", - "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", - "dev": true - }, - "accepts": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", - "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", - "dev": true, - "requires": { - "mime-types": "~2.1.18", - "negotiator": "0.6.1" - } - }, - "acorn": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", - "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", - "dev": true - }, - "acorn-dynamic-import": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz", - "integrity": "sha1-x1K9IQvvZ5UBtsbLf8hPj0cVjMQ=", - "dev": true, - "requires": { - "acorn": "^4.0.3" - }, - "dependencies": { - "acorn": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", - "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", - "dev": true - } - } - }, - "acorn-jsx": { - "version": "3.0.1", - "resolved": "http://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", - "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", - "dev": true, - "requires": { - "acorn": "^3.0.4" - }, - "dependencies": { - "acorn": { - "version": "3.3.0", - "resolved": "http://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", - "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", - "dev": true - } - } - }, - "after": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", - "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=", - "dev": true - }, - "agent-base": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-2.1.1.tgz", - "integrity": "sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=", - "dev": true, - "requires": { - "extend": "~3.0.0", - "semver": "~5.0.1" - }, - "dependencies": { - "semver": { - "version": "5.0.3", - "resolved": "http://registry.npmjs.org/semver/-/semver-5.0.3.tgz", - "integrity": "sha1-d0Zt5YnNXTyV8TiqeLxWmjy10no=", - "dev": true - } - } - }, - "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "dev": true, - "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" - } - }, - "ajv-keywords": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", - "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=", - "dev": true - }, - "align-text": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", - "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", - "dev": true, - "requires": { - "kind-of": "^3.0.2", - "longest": "^1.0.1", - "repeat-string": "^1.5.2" - } - }, - "almond": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/almond/-/almond-0.3.3.tgz", - "integrity": "sha1-oOfJWsdiTWQXtElLHmi/9pMWiiA=" - }, - "alphanum-sort": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", - "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=", - "dev": true - }, - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true, - "optional": true - }, - "ansi-escapes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", - "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", - "dev": true - }, - "ansi-html": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", - "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=", - "dev": true - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "anymatch": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", - "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", - "dev": true, - "requires": { - "micromatch": "^2.1.5", - "normalize-path": "^2.0.0" - } - }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "arr-diff": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "dev": true, - "requires": { - "arr-flatten": "^1.0.1" - } - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true - }, - "array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", - "dev": true - }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", - "dev": true - }, - "array-slice": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", - "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", - "dev": true - }, - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, - "requires": { - "array-uniq": "^1.0.1" - } - }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true - }, - "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true - }, - "arraybuffer.slice": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz", - "integrity": "sha1-8zshWfBTKj8xB6JywMz70a0peco=", - "dev": true - }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true - }, - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "dev": true, - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "asn1.js": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", - "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", - "dev": true, - "requires": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } - }, - "assert": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", - "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", - "dev": true, - "requires": { - "util": "0.10.3" - }, - "dependencies": { - "inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", - "dev": true - }, - "util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", - "dev": true, - "requires": { - "inherits": "2.0.1" - } - } - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - }, - "assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true - }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true - }, - "ast-types": { - "version": "0.11.6", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.11.6.tgz", - "integrity": "sha512-nHiuV14upVGl7MWwFUYbzJ6YlfwWS084CU9EA8HajfYQjMSli5TQi3UTRygGF58LFWVkXxS1rbgRhROEqlQkXg==", - "dev": true - }, - "async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", - "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", - "dev": true, - "requires": { - "lodash": "^4.17.10" - } - }, - "async-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", - "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", - "dev": true - }, - "async-limiter": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", - "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", - "dev": true - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true - }, - "autoprefixer": { - "version": "6.7.7", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-6.7.7.tgz", - "integrity": "sha1-Hb0cg1ZY41zj+ZhAmdsAWFx4IBQ=", - "dev": true, - "requires": { - "browserslist": "^1.7.6", - "caniuse-db": "^1.0.30000634", - "normalize-range": "^0.1.2", - "num2fraction": "^1.2.2", - "postcss": "^5.2.16", - "postcss-value-parser": "^3.2.3" - } - }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "dev": true - }, - "aws4": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", - "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", - "dev": true - }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" - } - }, - "babel-core": { - "version": "6.26.3", - "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz", - "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", - "dev": true, - "requires": { - "babel-code-frame": "^6.26.0", - "babel-generator": "^6.26.0", - "babel-helpers": "^6.24.1", - "babel-messages": "^6.23.0", - "babel-register": "^6.26.0", - "babel-runtime": "^6.26.0", - "babel-template": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "convert-source-map": "^1.5.1", - "debug": "^2.6.9", - "json5": "^0.5.1", - "lodash": "^4.17.4", - "minimatch": "^3.0.4", - "path-is-absolute": "^1.0.1", - "private": "^0.1.8", - "slash": "^1.0.0", - "source-map": "^0.5.7" - } - }, - "babel-eslint": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-7.2.3.tgz", - "integrity": "sha1-sv4tgBJkcPXBlELcdXJTqJdxCCc=", - "dev": true, - "requires": { - "babel-code-frame": "^6.22.0", - "babel-traverse": "^6.23.1", - "babel-types": "^6.23.0", - "babylon": "^6.17.0" - } - }, - "babel-generator": { - "version": "6.26.1", - "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", - "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", - "dev": true, - "requires": { - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "detect-indent": "^4.0.0", - "jsesc": "^1.3.0", - "lodash": "^4.17.4", - "source-map": "^0.5.7", - "trim-right": "^1.0.1" - } - }, - "babel-helper-bindify-decorators": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz", - "integrity": "sha1-FMGeXxQte0fxmlJDHlKxzLxAozA=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-helper-builder-binary-assignment-operator-visitor": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", - "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", - "dev": true, - "requires": { - "babel-helper-explode-assignable-expression": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-helper-call-delegate": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", - "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", - "dev": true, - "requires": { - "babel-helper-hoist-variables": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-helper-define-map": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", - "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", - "dev": true, - "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "lodash": "^4.17.4" - } - }, - "babel-helper-explode-assignable-expression": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", - "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-helper-explode-class": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz", - "integrity": "sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes=", - "dev": true, - "requires": { - "babel-helper-bindify-decorators": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-helper-function-name": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", - "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", - "dev": true, - "requires": { - "babel-helper-get-function-arity": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-helper-get-function-arity": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", - "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-helper-hoist-variables": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", - "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-helper-optimise-call-expression": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", - "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-helper-regex": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", - "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "lodash": "^4.17.4" - } - }, - "babel-helper-remap-async-to-generator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", - "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", - "dev": true, - "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-helper-replace-supers": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", - "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", - "dev": true, - "requires": { - "babel-helper-optimise-call-expression": "^6.24.1", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-helper-vue-jsx-merge-props": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-2.0.3.tgz", - "integrity": "sha512-gsLiKK7Qrb7zYJNgiXKpXblxbV5ffSwR0f5whkPAaBAR4fhi6bwRZxX9wBlIc5M/v8CCkXUbXZL4N/nSE97cqg==" - }, - "babel-helpers": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", - "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "babel-loader": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-6.4.1.tgz", - "integrity": "sha1-CzQRLVsHSKjc2/Uaz2+b1C1QuMo=", - "dev": true, - "requires": { - "find-cache-dir": "^0.1.1", - "loader-utils": "^0.2.16", - "mkdirp": "^0.5.1", - "object-assign": "^4.0.1" - } - }, - "babel-messages": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", - "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-check-es2015-constants": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", - "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-istanbul": { - "version": "4.1.6", - "resolved": "http://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.6.tgz", - "integrity": "sha512-PWP9FQ1AhZhS01T/4qLSKoHGY/xvkZdVBGlKM/HuxxS3+sC66HhTNR7+MpbO/so/cz/wY94MeSWJuP1hXIPfwQ==", - "dev": true, - "requires": { - "babel-plugin-syntax-object-rest-spread": "^6.13.0", - "find-up": "^2.1.0", - "istanbul-lib-instrument": "^1.10.1", - "test-exclude": "^4.2.1" - }, - "dependencies": { - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - } - } - }, - "babel-plugin-syntax-async-functions": { - "version": "6.13.0", - "resolved": "http://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", - "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=", - "dev": true - }, - "babel-plugin-syntax-async-generators": { - "version": "6.13.0", - "resolved": "http://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz", - "integrity": "sha1-a8lj67FuzLrmuStZbrfzXDQqi5o=", - "dev": true - }, - "babel-plugin-syntax-class-properties": { - "version": "6.13.0", - "resolved": "http://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", - "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=", - "dev": true - }, - "babel-plugin-syntax-decorators": { - "version": "6.13.0", - "resolved": "http://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz", - "integrity": "sha1-MSVjtNvePMgGzuPkFszurd0RrAs=", - "dev": true - }, - "babel-plugin-syntax-dynamic-import": { - "version": "6.18.0", - "resolved": "http://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz", - "integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo=", - "dev": true - }, - "babel-plugin-syntax-exponentiation-operator": { - "version": "6.13.0", - "resolved": "http://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", - "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=", - "dev": true - }, - "babel-plugin-syntax-jsx": { - "version": "6.18.0", - "resolved": "http://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", - "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=", - "dev": true - }, - "babel-plugin-syntax-object-rest-spread": { - "version": "6.13.0", - "resolved": "http://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", - "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=", - "dev": true - }, - "babel-plugin-syntax-trailing-function-commas": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", - "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=", - "dev": true - }, - "babel-plugin-transform-async-generator-functions": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz", - "integrity": "sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds=", - "dev": true, - "requires": { - "babel-helper-remap-async-to-generator": "^6.24.1", - "babel-plugin-syntax-async-generators": "^6.5.0", - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-async-to-generator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", - "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", - "dev": true, - "requires": { - "babel-helper-remap-async-to-generator": "^6.24.1", - "babel-plugin-syntax-async-functions": "^6.8.0", - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-class-properties": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", - "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", - "dev": true, - "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-plugin-syntax-class-properties": "^6.8.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "babel-plugin-transform-decorators": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz", - "integrity": "sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0=", - "dev": true, - "requires": { - "babel-helper-explode-class": "^6.24.1", - "babel-plugin-syntax-decorators": "^6.13.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-arrow-functions": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", - "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-block-scoped-functions": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", - "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-block-scoping": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", - "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "babel-template": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "lodash": "^4.17.4" - } - }, - "babel-plugin-transform-es2015-classes": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", - "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", - "dev": true, - "requires": { - "babel-helper-define-map": "^6.24.1", - "babel-helper-function-name": "^6.24.1", - "babel-helper-optimise-call-expression": "^6.24.1", - "babel-helper-replace-supers": "^6.24.1", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-computed-properties": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", - "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-destructuring": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", - "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-duplicate-keys": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", - "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-for-of": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", - "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-function-name": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", - "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", - "dev": true, - "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-literals": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", - "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-modules-amd": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", - "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", - "dev": true, - "requires": { - "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-modules-commonjs": { - "version": "6.26.2", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz", - "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==", - "dev": true, - "requires": { - "babel-plugin-transform-strict-mode": "^6.24.1", - "babel-runtime": "^6.26.0", - "babel-template": "^6.26.0", - "babel-types": "^6.26.0" - } - }, - "babel-plugin-transform-es2015-modules-systemjs": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", - "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", - "dev": true, - "requires": { - "babel-helper-hoist-variables": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-modules-umd": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", - "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", - "dev": true, - "requires": { - "babel-plugin-transform-es2015-modules-amd": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-object-super": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", - "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", - "dev": true, - "requires": { - "babel-helper-replace-supers": "^6.24.1", - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-parameters": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", - "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", - "dev": true, - "requires": { - "babel-helper-call-delegate": "^6.24.1", - "babel-helper-get-function-arity": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-shorthand-properties": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", - "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-spread": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", - "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-sticky-regex": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", - "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", - "dev": true, - "requires": { - "babel-helper-regex": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-template-literals": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", - "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-typeof-symbol": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", - "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-unicode-regex": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", - "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", - "dev": true, - "requires": { - "babel-helper-regex": "^6.24.1", - "babel-runtime": "^6.22.0", - "regexpu-core": "^2.0.0" - } - }, - "babel-plugin-transform-exponentiation-operator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", - "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", - "dev": true, - "requires": { - "babel-helper-builder-binary-assignment-operator-visitor": "^6.24.1", - "babel-plugin-syntax-exponentiation-operator": "^6.8.0", - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-object-rest-spread": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", - "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", - "dev": true, - "requires": { - "babel-plugin-syntax-object-rest-spread": "^6.8.0", - "babel-runtime": "^6.26.0" - } - }, - "babel-plugin-transform-regenerator": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", - "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", - "dev": true, - "requires": { - "regenerator-transform": "^0.10.0" - } - }, - "babel-plugin-transform-runtime": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-runtime/-/babel-plugin-transform-runtime-6.23.0.tgz", - "integrity": "sha1-iEkNRGUC6puOfvsP4J7E2ZR5se4=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-strict-mode": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", - "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-vue-jsx": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-vue-jsx/-/babel-plugin-transform-vue-jsx-3.7.0.tgz", - "integrity": "sha512-W39X07/n3oJMQd8tALBO+440NraGSF//Lo1ydd/9Nme3+QiRGFBb1Q39T9iixh0jZPPbfv3so18tNoIgLatymw==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "babel-polyfill": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", - "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=", - "requires": { - "babel-runtime": "^6.26.0", - "core-js": "^2.5.0", - "regenerator-runtime": "^0.10.5" - } - }, - "babel-preset-env": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz", - "integrity": "sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg==", - "dev": true, - "requires": { - "babel-plugin-check-es2015-constants": "^6.22.0", - "babel-plugin-syntax-trailing-function-commas": "^6.22.0", - "babel-plugin-transform-async-to-generator": "^6.22.0", - "babel-plugin-transform-es2015-arrow-functions": "^6.22.0", - "babel-plugin-transform-es2015-block-scoped-functions": "^6.22.0", - "babel-plugin-transform-es2015-block-scoping": "^6.23.0", - "babel-plugin-transform-es2015-classes": "^6.23.0", - "babel-plugin-transform-es2015-computed-properties": "^6.22.0", - "babel-plugin-transform-es2015-destructuring": "^6.23.0", - "babel-plugin-transform-es2015-duplicate-keys": "^6.22.0", - "babel-plugin-transform-es2015-for-of": "^6.23.0", - "babel-plugin-transform-es2015-function-name": "^6.22.0", - "babel-plugin-transform-es2015-literals": "^6.22.0", - "babel-plugin-transform-es2015-modules-amd": "^6.22.0", - "babel-plugin-transform-es2015-modules-commonjs": "^6.23.0", - "babel-plugin-transform-es2015-modules-systemjs": "^6.23.0", - "babel-plugin-transform-es2015-modules-umd": "^6.23.0", - "babel-plugin-transform-es2015-object-super": "^6.22.0", - "babel-plugin-transform-es2015-parameters": "^6.23.0", - "babel-plugin-transform-es2015-shorthand-properties": "^6.22.0", - "babel-plugin-transform-es2015-spread": "^6.22.0", - "babel-plugin-transform-es2015-sticky-regex": "^6.22.0", - "babel-plugin-transform-es2015-template-literals": "^6.22.0", - "babel-plugin-transform-es2015-typeof-symbol": "^6.23.0", - "babel-plugin-transform-es2015-unicode-regex": "^6.22.0", - "babel-plugin-transform-exponentiation-operator": "^6.22.0", - "babel-plugin-transform-regenerator": "^6.22.0", - "browserslist": "^3.2.6", - "invariant": "^2.2.2", - "semver": "^5.3.0" - }, - "dependencies": { - "browserslist": { - "version": "3.2.8", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", - "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30000844", - "electron-to-chromium": "^1.3.47" - } - } - } - }, - "babel-preset-es2015": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz", - "integrity": "sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk=", - "dev": true, - "requires": { - "babel-plugin-check-es2015-constants": "^6.22.0", - "babel-plugin-transform-es2015-arrow-functions": "^6.22.0", - "babel-plugin-transform-es2015-block-scoped-functions": "^6.22.0", - "babel-plugin-transform-es2015-block-scoping": "^6.24.1", - "babel-plugin-transform-es2015-classes": "^6.24.1", - "babel-plugin-transform-es2015-computed-properties": "^6.24.1", - "babel-plugin-transform-es2015-destructuring": "^6.22.0", - "babel-plugin-transform-es2015-duplicate-keys": "^6.24.1", - "babel-plugin-transform-es2015-for-of": "^6.22.0", - "babel-plugin-transform-es2015-function-name": "^6.24.1", - "babel-plugin-transform-es2015-literals": "^6.22.0", - "babel-plugin-transform-es2015-modules-amd": "^6.24.1", - "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", - "babel-plugin-transform-es2015-modules-systemjs": "^6.24.1", - "babel-plugin-transform-es2015-modules-umd": "^6.24.1", - "babel-plugin-transform-es2015-object-super": "^6.24.1", - "babel-plugin-transform-es2015-parameters": "^6.24.1", - "babel-plugin-transform-es2015-shorthand-properties": "^6.24.1", - "babel-plugin-transform-es2015-spread": "^6.22.0", - "babel-plugin-transform-es2015-sticky-regex": "^6.24.1", - "babel-plugin-transform-es2015-template-literals": "^6.22.0", - "babel-plugin-transform-es2015-typeof-symbol": "^6.22.0", - "babel-plugin-transform-es2015-unicode-regex": "^6.24.1", - "babel-plugin-transform-regenerator": "^6.24.1" - } - }, - "babel-preset-stage-2": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz", - "integrity": "sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE=", - "dev": true, - "requires": { - "babel-plugin-syntax-dynamic-import": "^6.18.0", - "babel-plugin-transform-class-properties": "^6.24.1", - "babel-plugin-transform-decorators": "^6.24.1", - "babel-preset-stage-3": "^6.24.1" - } - }, - "babel-preset-stage-3": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz", - "integrity": "sha1-g2raCp56f6N8sTj7kyb4eTSkg5U=", - "dev": true, - "requires": { - "babel-plugin-syntax-trailing-function-commas": "^6.22.0", - "babel-plugin-transform-async-generator-functions": "^6.24.1", - "babel-plugin-transform-async-to-generator": "^6.24.1", - "babel-plugin-transform-exponentiation-operator": "^6.24.1", - "babel-plugin-transform-object-rest-spread": "^6.22.0" - } - }, - "babel-register": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", - "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", - "dev": true, - "requires": { - "babel-core": "^6.26.0", - "babel-runtime": "^6.26.0", - "core-js": "^2.5.0", - "home-or-tmp": "^2.0.0", - "lodash": "^4.17.4", - "mkdirp": "^0.5.1", - "source-map-support": "^0.4.15" - } - }, - "babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", - "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - }, - "dependencies": { - "regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" - } - } - }, - "babel-template": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", - "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "lodash": "^4.17.4" - } - }, - "babel-traverse": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", - "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", - "dev": true, - "requires": { - "babel-code-frame": "^6.26.0", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "debug": "^2.6.8", - "globals": "^9.18.0", - "invariant": "^2.2.2", - "lodash": "^4.17.4" - } - }, - "babel-types": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", - "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "esutils": "^2.0.2", - "lodash": "^4.17.4", - "to-fast-properties": "^1.0.3" - } - }, - "babylon": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", - "dev": true - }, - "backo2": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", - "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=", - "dev": true - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - } - } - }, - "base64-arraybuffer": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", - "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=", - "dev": true - }, - "base64-js": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", - "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", - "dev": true - }, - "base64id": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", - "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=", - "dev": true - }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dev": true, - "requires": { - "tweetnacl": "^0.14.3" - } - }, - "better-assert": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", - "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", - "dev": true, - "requires": { - "callsite": "1.0.0" - } - }, - "bfj-node4": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/bfj-node4/-/bfj-node4-5.3.1.tgz", - "integrity": "sha512-SOmOsowQWfXc7ybFARsK3C4MCOWzERaOMV/Fl3Tgjs+5dJWyzo3oa127jL44eMbQiAN17J7SvAs2TRxEScTUmg==", - "dev": true, - "requires": { - "bluebird": "^3.5.1", - "check-types": "^7.3.0", - "tryer": "^1.0.0" - } - }, - "big.js": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", - "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", - "dev": true - }, - "binary-extensions": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.12.0.tgz", - "integrity": "sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg==", - "dev": true - }, - "blob": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz", - "integrity": "sha1-vPEwUspURj8w+fx+lbmkdjCpSSE=", - "dev": true - }, - "bluebird": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.2.tgz", - "integrity": "sha512-dhHTWMI7kMx5whMQntl7Vr9C6BvV10lFXDAasnqnrMYhXVCzzk6IO9Fo2L75jXHT07WrOngL1WDXOp+yYS91Yg==", - "dev": true - }, - "bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "dev": true - }, - "body-parser": { - "version": "1.18.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", - "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", - "dev": true, - "requires": { - "bytes": "3.0.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "~1.6.3", - "iconv-lite": "0.4.23", - "on-finished": "~2.3.0", - "qs": "6.5.2", - "raw-body": "2.3.3", - "type-is": "~1.6.16" - } - }, - "boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", - "dev": true - }, - "bootstrap": { - "version": "3.3.7", - "resolved": "http://registry.npmjs.org/bootstrap/-/bootstrap-3.3.7.tgz", - "integrity": "sha1-WjiTlFSfIzMIdaOxUGVldPip63E=" - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "dev": true, - "requires": { - "expand-range": "^1.8.1", - "preserve": "^0.2.0", - "repeat-element": "^1.1.2" - } - }, - "brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", - "dev": true - }, - "browser-stdout": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", - "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", - "dev": true - }, - "browserify-aes": { - "version": "1.2.0", - "resolved": "http://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", - "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "dev": true, - "requires": { - "buffer-xor": "^1.0.3", - "cipher-base": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.3", - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "browserify-cipher": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", - "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", - "dev": true, - "requires": { - "browserify-aes": "^1.0.4", - "browserify-des": "^1.0.0", - "evp_bytestokey": "^1.0.0" - } - }, - "browserify-des": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", - "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", - "dev": true, - "requires": { - "cipher-base": "^1.0.1", - "des.js": "^1.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "browserify-rsa": { - "version": "4.0.1", - "resolved": "http://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", - "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "randombytes": "^2.0.1" - } - }, - "browserify-sign": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", - "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", - "dev": true, - "requires": { - "bn.js": "^4.1.1", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.2", - "elliptic": "^6.0.0", - "inherits": "^2.0.1", - "parse-asn1": "^5.0.0" - } - }, - "browserify-zlib": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", - "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", - "dev": true, - "requires": { - "pako": "~1.0.5" - } - }, - "browserslist": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", - "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", - "dev": true, - "requires": { - "caniuse-db": "^1.0.30000639", - "electron-to-chromium": "^1.2.7" - } - }, - "buffer": { - "version": "4.9.1", - "resolved": "http://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", - "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", - "dev": true, - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" - } - }, - "buffer-alloc": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", - "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", - "dev": true, - "requires": { - "buffer-alloc-unsafe": "^1.1.0", - "buffer-fill": "^1.0.0" - } - }, - "buffer-alloc-unsafe": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", - "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", - "dev": true - }, - "buffer-fill": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", - "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", - "dev": true - }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true - }, - "buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", - "dev": true - }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", - "dev": true - }, - "builtin-status-codes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", - "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", - "dev": true - }, - "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", - "dev": true - }, - "cacache": { - "version": "10.0.4", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz", - "integrity": "sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==", - "dev": true, - "requires": { - "bluebird": "^3.5.1", - "chownr": "^1.0.1", - "glob": "^7.1.2", - "graceful-fs": "^4.1.11", - "lru-cache": "^4.1.1", - "mississippi": "^2.0.0", - "mkdirp": "^0.5.1", - "move-concurrently": "^1.0.1", - "promise-inflight": "^1.0.1", - "rimraf": "^2.6.2", - "ssri": "^5.2.4", - "unique-filename": "^1.1.0", - "y18n": "^4.0.0" - } - }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "cacheable-request": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-2.1.4.tgz", - "integrity": "sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0=", - "requires": { - "clone-response": "1.0.2", - "get-stream": "3.0.0", - "http-cache-semantics": "3.8.1", - "keyv": "3.0.0", - "lowercase-keys": "1.0.0", - "normalize-url": "2.0.1", - "responselike": "1.0.2" - }, - "dependencies": { - "lowercase-keys": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", - "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=" - } - } - }, - "caller-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", - "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", - "dev": true, - "requires": { - "callsites": "^0.2.0" - } - }, - "callsite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", - "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", - "dev": true - }, - "callsites": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", - "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", - "dev": true - }, - "camel-case": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", - "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=", - "dev": true, - "requires": { - "no-case": "^2.2.0", - "upper-case": "^1.1.1" - } - }, - "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", - "dev": true - }, - "camelcase-keys": { - "version": "2.1.0", - "resolved": "http://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", - "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", - "dev": true, - "requires": { - "camelcase": "^2.0.0", - "map-obj": "^1.0.0" - } - }, - "caniuse-api": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-1.6.1.tgz", - "integrity": "sha1-tTTnxzTE+B7F++isoq0kNUuWLGw=", - "dev": true, - "requires": { - "browserslist": "^1.3.6", - "caniuse-db": "^1.0.30000529", - "lodash.memoize": "^4.1.2", - "lodash.uniq": "^4.5.0" - } - }, - "caniuse-db": { - "version": "1.0.30000892", - "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000892.tgz", - "integrity": "sha512-as/DXjiFJg051+GSJLmkY0hckkVsmTB4nuDUPLwK1sMHk94XsYuocNJuU0wdOpobwI/3sqNeW5ETebvdPGvwBQ==", - "dev": true - }, - "caniuse-lite": { - "version": "1.0.30000892", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000892.tgz", - "integrity": "sha512-X9rxMaWZNbJB5qjkDqPtNv/yfViTeUL6ILk0QJNxLV3OhKC5Acn5vxsuUvllR6B48mog8lmS+whwHq/QIYSL9w==", - "dev": true - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true - }, - "center-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", - "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", - "dev": true, - "requires": { - "align-text": "^0.1.3", - "lazy-cache": "^1.0.3" - } - }, - "chai": { - "version": "3.5.0", - "resolved": "http://registry.npmjs.org/chai/-/chai-3.5.0.tgz", - "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=", - "dev": true, - "requires": { - "assertion-error": "^1.0.1", - "deep-eql": "^0.1.3", - "type-detect": "^1.0.0" - } - }, - "chai-nightwatch": { - "version": "0.1.1", - "resolved": "http://registry.npmjs.org/chai-nightwatch/-/chai-nightwatch-0.1.1.tgz", - "integrity": "sha1-HKVt52jTwIaP5/wvTTLC/olOa+k=", - "dev": true, - "requires": { - "assertion-error": "1.0.0", - "deep-eql": "0.1.3" - }, - "dependencies": { - "assertion-error": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.0.tgz", - "integrity": "sha1-x/hUOP3UZrx8oWq5DIFRN5el0js=", - "dev": true - } - } - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "check-types": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/check-types/-/check-types-7.4.0.tgz", - "integrity": "sha512-YbulWHdfP99UfZ73NcUDlNJhEIDgm9Doq9GhpyXbF+7Aegi3CVV7qqMCKTTqJxlvEvnQBp9IA+dxsGN6xK/nSg==", - "dev": true - }, - "chokidar": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", - "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", - "dev": true, - "requires": { - "anymatch": "^1.3.0", - "async-each": "^1.0.0", - "fsevents": "^1.0.0", - "glob-parent": "^2.0.0", - "inherits": "^2.0.1", - "is-binary-path": "^1.0.0", - "is-glob": "^2.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0" - } - }, - "chownr": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz", - "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==", - "dev": true - }, - "chromedriver": { - "version": "2.42.1", - "resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-2.42.1.tgz", - "integrity": "sha512-ciiSoIZH3Pq3UNvNgITb717MP5aldpvte4BO5sLi/FBeahMoo6QZiQ7kDIG1LQY6yZh7N8dqjjiYENq2/J+Xlw==", - "dev": true, - "requires": { - "del": "^3.0.0", - "extract-zip": "^1.6.7", - "kew": "^0.7.0", - "mkdirp": "^0.5.1", - "request": "^2.87.0" - } - }, - "cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "circular-json": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", - "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", - "dev": true - }, - "clap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/clap/-/clap-1.2.3.tgz", - "integrity": "sha512-4CoL/A3hf90V3VIEjeuhSvlGFEHKzOz+Wfc2IVZc+FaUgU0ZQafJTP49fvnULipOPcAfqhyI2duwQyns6xqjYA==", - "dev": true, - "requires": { - "chalk": "^1.1.3" - } - }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "clean-css": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz", - "integrity": "sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g==", - "dev": true, - "requires": { - "source-map": "~0.6.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "cli-cursor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", - "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", - "dev": true, - "requires": { - "restore-cursor": "^1.0.1" - } - }, - "cli-spinners": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-1.3.1.tgz", - "integrity": "sha512-1QL4544moEsDVH9T/l6Cemov/37iv1RtoKf7NJ04A60+4MREXNfx/QvavbH6QoGdsD4N4Mwy49cmaINR/o2mdg==", - "dev": true - }, - "cli-width": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", - "dev": true - }, - "cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "dev": true, - "requires": { - "center-align": "^0.1.1", - "right-align": "^0.1.1", - "wordwrap": "0.0.2" - }, - "dependencies": { - "wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", - "dev": true - } - } - }, - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true - }, - "clone-response": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", - "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", - "requires": { - "mimic-response": "^1.0.0" - } - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true - }, - "coa": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/coa/-/coa-1.0.4.tgz", - "integrity": "sha1-qe8VNmDWqGqL3sAomlxoTSF0Mv0=", - "dev": true, - "requires": { - "q": "^1.1.2" - } - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true - }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - } - }, - "color": { - "version": "0.11.4", - "resolved": "http://registry.npmjs.org/color/-/color-0.11.4.tgz", - "integrity": "sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q=", - "dev": true, - "requires": { - "clone": "^1.0.2", - "color-convert": "^1.3.0", - "color-string": "^0.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "color-string": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-0.3.0.tgz", - "integrity": "sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE=", - "dev": true, - "requires": { - "color-name": "^1.0.0" - } - }, - "colormin": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colormin/-/colormin-1.1.2.tgz", - "integrity": "sha1-6i90IKcrlogaOKrlnsEkpvcpgTM=", - "dev": true, - "requires": { - "color": "^0.11.0", - "css-color-names": "0.0.4", - "has": "^1.0.1" - } - }, - "colors": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", - "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", - "dev": true - }, - "combine-lists": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/combine-lists/-/combine-lists-1.0.1.tgz", - "integrity": "sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y=", - "dev": true, - "requires": { - "lodash": "^4.5.0" - } - }, - "combined-stream": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", - "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", - "dev": true, - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "commander": { - "version": "2.17.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", - "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", - "dev": true - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, - "component-bind": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", - "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=", - "dev": true - }, - "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", - "dev": true - }, - "component-inherit": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", - "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - }, - "dependencies": { - "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "config-chain": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz", - "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==", - "dev": true, - "requires": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - } - }, - "connect": { - "version": "3.6.6", - "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.6.tgz", - "integrity": "sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ=", - "dev": true, - "requires": { - "debug": "2.6.9", - "finalhandler": "1.1.0", - "parseurl": "~1.3.2", - "utils-merge": "1.0.1" - }, - "dependencies": { - "finalhandler": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", - "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", - "dev": true, - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.1", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.2", - "statuses": "~1.3.1", - "unpipe": "~1.0.0" - } - }, - "statuses": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", - "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", - "dev": true - } - } - }, - "connect-history-api-fallback": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz", - "integrity": "sha1-sGhzk0vF40T+9hGhlqb6rgruAVo=", - "dev": true - }, - "console-browserify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", - "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", - "dev": true, - "requires": { - "date-now": "^0.1.4" - } - }, - "consolidate": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.14.5.tgz", - "integrity": "sha1-WiUEe8dvcwcmZ8jLUsmJiI9JTGM=", - "dev": true, - "requires": { - "bluebird": "^3.1.1" - } - }, - "constants-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", - "dev": true - }, - "content-disposition": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", - "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=", - "dev": true - }, - "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", - "dev": true - }, - "convert-source-map": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", - "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - } - }, - "cookie": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", - "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", - "dev": true - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", - "dev": true - }, - "copy-concurrently": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", - "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", - "dev": true, - "requires": { - "aproba": "^1.1.1", - "fs-write-stream-atomic": "^1.0.8", - "iferr": "^0.1.5", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.0" - } - }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true - }, - "copy-webpack-plugin": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-4.5.3.tgz", - "integrity": "sha512-VKCiNXQcc8zyznaepXfKpCH2cZD+/j3T3B+gsFY97P7qMlEsj34wr/sI9OCG7QPUUh7gAHVx3q8Q1rdQIDM4bA==", - "dev": true, - "requires": { - "cacache": "^10.0.4", - "find-cache-dir": "^1.0.0", - "globby": "^7.1.1", - "is-glob": "^4.0.0", - "loader-utils": "^1.1.0", - "minimatch": "^3.0.4", - "p-limit": "^1.0.0", - "serialize-javascript": "^1.4.0" - }, - "dependencies": { - "find-cache-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz", - "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^1.0.0", - "pkg-dir": "^2.0.0" - } - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "globby": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz", - "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=", - "dev": true, - "requires": { - "array-union": "^1.0.1", - "dir-glob": "^2.0.0", - "glob": "^7.1.2", - "ignore": "^3.3.5", - "pify": "^3.0.0", - "slash": "^1.0.0" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-glob": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", - "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "loader-utils": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", - "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", - "dev": true, - "requires": { - "big.js": "^3.1.3", - "emojis-list": "^2.0.0", - "json5": "^0.5.0" - } - }, - "pkg-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", - "dev": true, - "requires": { - "find-up": "^2.1.0" - } - } - } - }, - "core-js": { - "version": "2.5.7", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", - "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==" - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "cosmiconfig": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-2.2.2.tgz", - "integrity": "sha512-GiNXLwAFPYHy25XmTPpafYvn3CLAkJ8FLsscq78MQd1Kh0OU6Yzhn4eV2MVF4G9WEQZoWEGltatdR+ntGPMl5A==", - "dev": true, - "requires": { - "is-directory": "^0.3.1", - "js-yaml": "^3.4.3", - "minimist": "^1.2.0", - "object-assign": "^4.1.0", - "os-homedir": "^1.0.1", - "parse-json": "^2.2.0", - "require-from-string": "^1.1.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, - "create-ecdh": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", - "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "elliptic": "^6.0.0" - } - }, - "create-hash": { - "version": "1.2.0", - "resolved": "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "dev": true, - "requires": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "create-hmac": { - "version": "1.1.7", - "resolved": "http://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "dev": true, - "requires": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "cross-env": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-4.0.0.tgz", - "integrity": "sha1-Fgg4YtCCdaRiiwskOxIb7apV3YA=", - "dev": true, - "requires": { - "cross-spawn": "^5.1.0", - "is-windows": "^1.0.0" - } - }, - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "crypto-browserify": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", - "dev": true, - "requires": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", - "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0", - "randomfill": "^1.0.3" - } - }, - "css-color-names": { - "version": "0.0.4", - "resolved": "http://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", - "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=", - "dev": true - }, - "css-loader": { - "version": "0.28.11", - "resolved": "http://registry.npmjs.org/css-loader/-/css-loader-0.28.11.tgz", - "integrity": "sha512-wovHgjAx8ZIMGSL8pTys7edA1ClmzxHeY6n/d97gg5odgsxEgKjULPR0viqyC+FWMCL9sfqoC/QCUBo62tLvPg==", - "dev": true, - "requires": { - "babel-code-frame": "^6.26.0", - "css-selector-tokenizer": "^0.7.0", - "cssnano": "^3.10.0", - "icss-utils": "^2.1.0", - "loader-utils": "^1.0.2", - "lodash.camelcase": "^4.3.0", - "object-assign": "^4.1.1", - "postcss": "^5.0.6", - "postcss-modules-extract-imports": "^1.2.0", - "postcss-modules-local-by-default": "^1.2.0", - "postcss-modules-scope": "^1.1.0", - "postcss-modules-values": "^1.3.0", - "postcss-value-parser": "^3.3.0", - "source-list-map": "^2.0.0" - }, - "dependencies": { - "loader-utils": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", - "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", - "dev": true, - "requires": { - "big.js": "^3.1.3", - "emojis-list": "^2.0.0", - "json5": "^0.5.0" - } - } - } - }, - "css-select": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", - "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", - "dev": true, - "requires": { - "boolbase": "~1.0.0", - "css-what": "2.1", - "domutils": "1.5.1", - "nth-check": "~1.0.1" - }, - "dependencies": { - "domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", - "dev": true, - "requires": { - "dom-serializer": "0", - "domelementtype": "1" - } - } - } - }, - "css-selector-tokenizer": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.0.tgz", - "integrity": "sha1-5piEdK6MlTR3v15+/s/OzNnPTIY=", - "dev": true, - "requires": { - "cssesc": "^0.1.0", - "fastparse": "^1.1.1", - "regexpu-core": "^1.0.0" - }, - "dependencies": { - "regexpu-core": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz", - "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=", - "dev": true, - "requires": { - "regenerate": "^1.2.1", - "regjsgen": "^0.2.0", - "regjsparser": "^0.1.4" - } - } - } - }, - "css-what": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.0.tgz", - "integrity": "sha1-lGfQMsOM+u+58teVASUwYvh/ob0=", - "dev": true - }, - "cssesc": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-0.1.0.tgz", - "integrity": "sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=", - "dev": true - }, - "cssnano": { - "version": "3.10.0", - "resolved": "http://registry.npmjs.org/cssnano/-/cssnano-3.10.0.tgz", - "integrity": "sha1-Tzj2zqK5sX+gFJDyPx3GjqZcHDg=", - "dev": true, - "requires": { - "autoprefixer": "^6.3.1", - "decamelize": "^1.1.2", - "defined": "^1.0.0", - "has": "^1.0.1", - "object-assign": "^4.0.1", - "postcss": "^5.0.14", - "postcss-calc": "^5.2.0", - "postcss-colormin": "^2.1.8", - "postcss-convert-values": "^2.3.4", - "postcss-discard-comments": "^2.0.4", - "postcss-discard-duplicates": "^2.0.1", - "postcss-discard-empty": "^2.0.1", - "postcss-discard-overridden": "^0.1.1", - "postcss-discard-unused": "^2.2.1", - "postcss-filter-plugins": "^2.0.0", - "postcss-merge-idents": "^2.1.5", - "postcss-merge-longhand": "^2.0.1", - "postcss-merge-rules": "^2.0.3", - "postcss-minify-font-values": "^1.0.2", - "postcss-minify-gradients": "^1.0.1", - "postcss-minify-params": "^1.0.4", - "postcss-minify-selectors": "^2.0.4", - "postcss-normalize-charset": "^1.1.0", - "postcss-normalize-url": "^3.0.7", - "postcss-ordered-values": "^2.1.0", - "postcss-reduce-idents": "^2.2.2", - "postcss-reduce-initial": "^1.0.0", - "postcss-reduce-transforms": "^1.0.3", - "postcss-svgo": "^2.1.1", - "postcss-unique-selectors": "^2.0.2", - "postcss-value-parser": "^3.2.3", - "postcss-zindex": "^2.0.1" - } - }, - "csso": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/csso/-/csso-2.3.2.tgz", - "integrity": "sha1-3dUsWHAz9J6Utx/FVWnyUuj/X4U=", - "dev": true, - "requires": { - "clap": "^1.0.9", - "source-map": "^0.5.3" - } - }, - "currently-unhandled": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", - "dev": true, - "requires": { - "array-find-index": "^1.0.1" - } - }, - "custom-event": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", - "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", - "dev": true - }, - "cyclist": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz", - "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=", - "dev": true - }, - "d": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", - "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", - "requires": { - "es5-ext": "^0.10.9" - } - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, - "data-uri-to-buffer": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-1.2.0.tgz", - "integrity": "sha512-vKQ9DTQPN1FLYiiEEOQ6IBGFqvjCa5rSK3cWMy/Nespm5d/x3dGFT9UBZnkLxCwua/IXBi2TYnwTEpsOvhC4UQ==", - "dev": true - }, - "datatables.net": { - "version": "1.10.19", - "resolved": "https://registry.npmjs.org/datatables.net/-/datatables.net-1.10.19.tgz", - "integrity": "sha512-+ljXcI6Pj3PTGy5pesp3E5Dr3x3AV45EZe0o1r0gKENN2gafBKXodVnk2ypKwl2tTmivjxbkiqoWnipTefyBTA==", - "requires": { - "jquery": ">=1.7" - } - }, - "datatables.net-bs": { - "version": "1.10.19", - "resolved": "https://registry.npmjs.org/datatables.net-bs/-/datatables.net-bs-1.10.19.tgz", - "integrity": "sha512-5gxoI2n+duZP06+4xVC2TtH6zcY369/TRKTZ1DdSgDcDUl4OYQsrXCuaLJmbVzna/5Y5lrMmK7CxgvYgIynICA==", - "requires": { - "datatables.net": "1.10.19", - "jquery": ">=1.7" - } - }, - "datatables.net-buttons": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/datatables.net-buttons/-/datatables.net-buttons-1.5.4.tgz", - "integrity": "sha512-xfo/23sGVXQW0kj2jLH6PzkhnXv+yGPrUXh7/ZT7xvCL1sNt8MLLf0tPLyrWynyeaew+Qvx5NBZer4MLxmisyw==", - "requires": { - "datatables.net": "^1.10.15", - "jquery": ">=1.7" - } - }, - "datatables.net-responsive": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/datatables.net-responsive/-/datatables.net-responsive-2.2.3.tgz", - "integrity": "sha512-8D6VtZcyuH3FG0Hn5A4LPZQEOX3+HrRFM7HjpmsQc/nQDBbdeBLkJX4Sh/o1nzFTSneuT1Wh/lYZHVPpjcN+Sw==", - "requires": { - "datatables.net": "^1.10.15", - "jquery": ">=1.7" - } - }, - "datatables.net-responsive-bs": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/datatables.net-responsive-bs/-/datatables.net-responsive-bs-2.2.3.tgz", - "integrity": "sha512-tQZiqqjXGlTiRBlBP3lON7ULThiMc0sLh4hT5xLaHRWBniaQkIMNhIzX9RRybWjOEQcHS7LA/ZiwE2S7rYqq9w==", - "requires": { - "datatables.net-bs": "^1.10.15", - "datatables.net-responsive": "2.2.3", - "jquery": ">=1.7" - } - }, - "date-now": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", - "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", - "dev": true - }, - "dateformat": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", - "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", - "dev": true, - "requires": { - "get-stdin": "^4.0.1", - "meow": "^3.3.0" - } - }, - "de-indent": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", - "integrity": "sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0=", - "dev": true - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" - }, - "decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", - "requires": { - "mimic-response": "^1.0.0" - } - }, - "deep-eql": { - "version": "0.1.3", - "resolved": "http://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", - "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", - "dev": true, - "requires": { - "type-detect": "0.1.1" - }, - "dependencies": { - "type-detect": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", - "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=", - "dev": true - } - } - }, - "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true - }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - } - } - }, - "defined": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", - "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", - "dev": true - }, - "degenerator": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-1.0.4.tgz", - "integrity": "sha1-/PSQo37OJmRk2cxDGrmMWBnO0JU=", - "dev": true, - "requires": { - "ast-types": "0.x.x", - "escodegen": "1.x.x", - "esprima": "3.x.x" - }, - "dependencies": { - "esprima": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", - "dev": true - } - } - }, - "del": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/del/-/del-3.0.0.tgz", - "integrity": "sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=", - "dev": true, - "requires": { - "globby": "^6.1.0", - "is-path-cwd": "^1.0.0", - "is-path-in-cwd": "^1.0.0", - "p-map": "^1.1.1", - "pify": "^3.0.0", - "rimraf": "^2.2.8" - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true - }, - "des.js": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", - "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } - }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", - "dev": true - }, - "detect-indent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", - "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", - "dev": true, - "requires": { - "repeating": "^2.0.0" - } - }, - "di": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", - "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=", - "dev": true - }, - "diff": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", - "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=", - "dev": true - }, - "diffie-hellman": { - "version": "5.0.3", - "resolved": "http://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", - "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "miller-rabin": "^4.0.0", - "randombytes": "^2.0.0" - } - }, - "dir-glob": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz", - "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==", - "dev": true, - "requires": { - "arrify": "^1.0.1", - "path-type": "^3.0.0" - }, - "dependencies": { - "path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "dev": true, - "requires": { - "pify": "^3.0.0" - } - } - } - }, - "doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "dom-converter": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", - "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", - "dev": true, - "requires": { - "utila": "~0.4" - } - }, - "dom-serialize": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", - "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", - "dev": true, - "requires": { - "custom-event": "~1.0.0", - "ent": "~2.2.0", - "extend": "^3.0.0", - "void-elements": "^2.0.0" - } - }, - "dom-serializer": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", - "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", - "dev": true, - "requires": { - "domelementtype": "~1.1.1", - "entities": "~1.1.1" - }, - "dependencies": { - "domelementtype": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", - "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=", - "dev": true - } - } - }, - "domain-browser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", - "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", - "dev": true - }, - "domelementtype": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", - "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=", - "dev": true - }, - "domhandler": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", - "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", - "dev": true, - "requires": { - "domelementtype": "1" - } - }, - "domutils": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", - "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", - "dev": true, - "requires": { - "dom-serializer": "0", - "domelementtype": "1" - } - }, - "duplexer": { - "version": "0.1.1", - "resolved": "http://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", - "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", - "dev": true - }, - "duplexer3": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" - }, - "duplexify": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.1.tgz", - "integrity": "sha512-vM58DwdnKmty+FSPzT14K9JXb90H+j5emaR4KYbr2KTIz00WHGbWOe5ghQTx233ZCLZtrGDALzKwcjEtSt35mA==", - "dev": true, - "requires": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } - }, - "easings-css": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/easings-css/-/easings-css-1.0.0.tgz", - "integrity": "sha512-7Uq7NdazNfVtr0RNmPAys8it0zKCuaqxJStYKEl72D3j4gbvXhhaM7iWNbqhA4C94ygCye6VuyhzBRQC4szeBg==" - }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dev": true, - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "editorconfig": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.2.tgz", - "integrity": "sha512-GWjSI19PVJAM9IZRGOS+YKI8LN+/sjkSjNyvxL5ucqP9/IqtYNXBaQ/6c/hkPNYQHyOHra2KoXZI/JVpuqwmcQ==", - "dev": true, - "requires": { - "@types/node": "^10.11.7", - "@types/semver": "^5.5.0", - "commander": "^2.19.0", - "lru-cache": "^4.1.3", - "semver": "^5.6.0", - "sigmund": "^1.0.1" - }, - "dependencies": { - "commander": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", - "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", - "dev": true - } - } - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", - "dev": true - }, - "ejs": { - "version": "2.5.7", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.5.7.tgz", - "integrity": "sha1-zIcsFoiArjxxiXYv1f/ACJbJUYo=", - "dev": true - }, - "electron-to-chromium": { - "version": "1.3.79", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.79.tgz", - "integrity": "sha512-LQdY3j4PxuUl6xfxiFruTSlCniTrTrzAd8/HfsLEMi0PUpaQ0Iy+Pr4N4VllDYjs0Hyu2lkTbvzqlG+PX9NsNw==", - "dev": true - }, - "elliptic": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", - "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==", - "dev": true, - "requires": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.0" - } - }, - "emojis-list": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", - "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", - "dev": true - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "dev": true - }, - "end-of-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", - "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "engine.io": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-1.8.3.tgz", - "integrity": "sha1-jef5eJXSDTm4X4ju7nd7K9QrE9Q=", - "dev": true, - "requires": { - "accepts": "1.3.3", - "base64id": "1.0.0", - "cookie": "0.3.1", - "debug": "2.3.3", - "engine.io-parser": "1.3.2", - "ws": "1.1.2" - }, - "dependencies": { - "accepts": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.3.tgz", - "integrity": "sha1-w8p0NJOGSMPg2cHjKN1otiLChMo=", - "dev": true, - "requires": { - "mime-types": "~2.1.11", - "negotiator": "0.6.1" - } - }, - "debug": { - "version": "2.3.3", - "resolved": "http://registry.npmjs.org/debug/-/debug-2.3.3.tgz", - "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=", - "dev": true, - "requires": { - "ms": "0.7.2" - } - }, - "ms": { - "version": "0.7.2", - "resolved": "http://registry.npmjs.org/ms/-/ms-0.7.2.tgz", - "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", - "dev": true - } - } - }, - "engine.io-client": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-1.8.3.tgz", - "integrity": "sha1-F5jtk0USRkU9TG9jXXogH+lA1as=", - "dev": true, - "requires": { - "component-emitter": "1.2.1", - "component-inherit": "0.0.3", - "debug": "2.3.3", - "engine.io-parser": "1.3.2", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "parsejson": "0.0.3", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "ws": "1.1.2", - "xmlhttprequest-ssl": "1.5.3", - "yeast": "0.1.2" - }, - "dependencies": { - "debug": { - "version": "2.3.3", - "resolved": "http://registry.npmjs.org/debug/-/debug-2.3.3.tgz", - "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=", - "dev": true, - "requires": { - "ms": "0.7.2" - } - }, - "ms": { - "version": "0.7.2", - "resolved": "http://registry.npmjs.org/ms/-/ms-0.7.2.tgz", - "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", - "dev": true - } - } - }, - "engine.io-parser": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-1.3.2.tgz", - "integrity": "sha1-k3sHnwAH0Ik+xW1GyyILjLQ1Igo=", - "dev": true, - "requires": { - "after": "0.8.2", - "arraybuffer.slice": "0.0.6", - "base64-arraybuffer": "0.1.5", - "blob": "0.0.4", - "has-binary": "0.1.7", - "wtf-8": "1.0.0" - } - }, - "enhanced-resolve": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz", - "integrity": "sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "memory-fs": "^0.4.0", - "object-assign": "^4.0.1", - "tapable": "^0.2.7" - } - }, - "ent": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", - "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", - "dev": true - }, - "entities": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", - "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=", - "dev": true - }, - "eonasdan-bootstrap-datetimepicker": { - "version": "4.17.47", - "resolved": "https://registry.npmjs.org/eonasdan-bootstrap-datetimepicker/-/eonasdan-bootstrap-datetimepicker-4.17.47.tgz", - "integrity": "sha1-ekmXAEQGUnbnll79Fvgic1IZ5zU=", - "requires": { - "bootstrap": "^3.3", - "jquery": "^1.8.3 || ^2.0 || ^3.0", - "moment": "^2.10", - "moment-timezone": "^0.4.0" - } - }, - "errno": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", - "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", - "dev": true, - "requires": { - "prr": "~1.0.1" - } - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "error-stack-parser": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.0.2.tgz", - "integrity": "sha512-E1fPutRDdIj/hohG0UpT5mayXNCxXP9d+snxFsPU9X0XgccOumKraa3juDMwTUyi7+Bu5+mCGagjg4IYeNbOdw==", - "dev": true, - "requires": { - "stackframe": "^1.0.4" - } - }, - "es5-ext": { - "version": "0.10.46", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.46.tgz", - "integrity": "sha512-24XxRvJXNFwEMpJb3nOkiRJKRoupmjYmOPVlI65Qy2SrtxwOTB+g6ODjBKOtwEHbYrhWRty9xxOWLNdClT2djw==", - "requires": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.1", - "next-tick": "1" - } - }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "requires": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "es6-map": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", - "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14", - "es6-iterator": "~2.0.1", - "es6-set": "~0.1.5", - "es6-symbol": "~3.1.1", - "event-emitter": "~0.3.5" - } - }, - "es6-promise": { - "version": "3.0.2", - "resolved": "http://registry.npmjs.org/es6-promise/-/es6-promise-3.0.2.tgz", - "integrity": "sha1-AQ1YWEI6XxGJeWZfRkhqlcbuK7Y=" - }, - "es6-set": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", - "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14", - "es6-iterator": "~2.0.1", - "es6-symbol": "3.1.1", - "event-emitter": "~0.3.5" - } - }, - "es6-symbol": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", - "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", - "requires": { - "d": "1", - "es5-ext": "~0.10.14" - } - }, - "es6-weak-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", - "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.14", - "es6-iterator": "^2.0.1", - "es6-symbol": "^3.1.1" - } - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "escodegen": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", - "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", - "dev": true, - "requires": { - "esprima": "^2.7.1", - "estraverse": "^1.9.1", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.2.0" - }, - "dependencies": { - "estraverse": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", - "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", - "dev": true - }, - "source-map": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", - "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", - "dev": true, - "optional": true, - "requires": { - "amdefine": ">=0.0.4" - } - } - } - }, - "escope": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", - "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", - "dev": true, - "requires": { - "es6-map": "^0.1.3", - "es6-weak-map": "^2.0.1", - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } - }, - "eslint": { - "version": "3.19.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-3.19.0.tgz", - "integrity": "sha1-yPxiAcf0DdCJQbh8CFdnOGpnmsw=", - "dev": true, - "requires": { - "babel-code-frame": "^6.16.0", - "chalk": "^1.1.3", - "concat-stream": "^1.5.2", - "debug": "^2.1.1", - "doctrine": "^2.0.0", - "escope": "^3.6.0", - "espree": "^3.4.0", - "esquery": "^1.0.0", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "file-entry-cache": "^2.0.0", - "glob": "^7.0.3", - "globals": "^9.14.0", - "ignore": "^3.2.0", - "imurmurhash": "^0.1.4", - "inquirer": "^0.12.0", - "is-my-json-valid": "^2.10.0", - "is-resolvable": "^1.0.0", - "js-yaml": "^3.5.1", - "json-stable-stringify": "^1.0.0", - "levn": "^0.3.0", - "lodash": "^4.0.0", - "mkdirp": "^0.5.0", - "natural-compare": "^1.4.0", - "optionator": "^0.8.2", - "path-is-inside": "^1.0.1", - "pluralize": "^1.2.1", - "progress": "^1.1.8", - "require-uncached": "^1.0.2", - "shelljs": "^0.7.5", - "strip-bom": "^3.0.0", - "strip-json-comments": "~2.0.1", - "table": "^3.7.8", - "text-table": "~0.2.0", - "user-home": "^2.0.0" - }, - "dependencies": { - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - } - } - }, - "eslint-config-standard": { - "version": "6.2.1", - "resolved": "http://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-6.2.1.tgz", - "integrity": "sha1-06aKr8cZFjnn7kQec0hzkCY1QpI=", - "dev": true - }, - "eslint-friendly-formatter": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/eslint-friendly-formatter/-/eslint-friendly-formatter-2.0.7.tgz", - "integrity": "sha1-ZX+VoZr0mJY2r+uxzJ3mzrvQiO4=", - "dev": true, - "requires": { - "chalk": "^1.0.0", - "extend": "^3.0.0", - "minimist": "^1.2.0", - "text-table": "^0.2.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, - "eslint-loader": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/eslint-loader/-/eslint-loader-1.9.0.tgz", - "integrity": "sha512-40aN976qSNPyb9ejTqjEthZITpls1SVKtwguahmH1dzGCwQU/vySE+xX33VZmD8csU0ahVNCtFlsPgKqRBiqgg==", - "dev": true, - "requires": { - "loader-fs-cache": "^1.0.0", - "loader-utils": "^1.0.2", - "object-assign": "^4.0.1", - "object-hash": "^1.1.4", - "rimraf": "^2.6.1" - }, - "dependencies": { - "loader-utils": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", - "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", - "dev": true, - "requires": { - "big.js": "^3.1.3", - "emojis-list": "^2.0.0", - "json5": "^0.5.0" - } - } - } - }, - "eslint-plugin-html": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-html/-/eslint-plugin-html-2.0.3.tgz", - "integrity": "sha1-fImIOrDIX6XSi2ZqFKTpBqqQuJc=", - "dev": true, - "requires": { - "htmlparser2": "^3.8.2" - } - }, - "eslint-plugin-promise": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.8.0.tgz", - "integrity": "sha512-JiFL9UFR15NKpHyGii1ZcvmtIqa3UTwiDAGb8atSffe43qJ3+1czVGN6UtkklpcJ2DVnqvTMzEKRaJdBkAL2aQ==", - "dev": true - }, - "eslint-plugin-standard": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-2.3.1.tgz", - "integrity": "sha1-Z2W9Km2ezce98bFFrkuzDit7hvg=", - "dev": true - }, - "espree": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", - "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", - "dev": true, - "requires": { - "acorn": "^5.5.0", - "acorn-jsx": "^3.0.0" - } - }, - "esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", - "dev": true - }, - "esquery": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", - "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", - "dev": true, - "requires": { - "estraverse": "^4.0.0" - } - }, - "esrecurse": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", - "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", - "dev": true, - "requires": { - "estraverse": "^4.1.0" - } - }, - "estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", - "dev": true - }, - "esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", - "dev": true - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", - "dev": true - }, - "event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14" - } - }, - "eventemitter3": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz", - "integrity": "sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA==", - "dev": true - }, - "events": { - "version": "1.1.1", - "resolved": "http://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", - "dev": true - }, - "eventsource-polyfill": { - "version": "0.9.6", - "resolved": "https://registry.npmjs.org/eventsource-polyfill/-/eventsource-polyfill-0.9.6.tgz", - "integrity": "sha1-EODRh/ERsWfyj9q5GIQ859gY8Tw=", - "dev": true - }, - "evp_bytestokey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "dev": true, - "requires": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" - } - }, - "exit-hook": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", - "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", - "dev": true - }, - "expand-braces": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.2.tgz", - "integrity": "sha1-SIsdHSRRyz06axks/AMPRMWFX+o=", - "dev": true, - "requires": { - "array-slice": "^0.2.3", - "array-unique": "^0.2.1", - "braces": "^0.1.2" - }, - "dependencies": { - "braces": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-0.1.5.tgz", - "integrity": "sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY=", - "dev": true, - "requires": { - "expand-range": "^0.1.0" - } - }, - "expand-range": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz", - "integrity": "sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=", - "dev": true, - "requires": { - "is-number": "^0.1.1", - "repeat-string": "^0.2.2" - } - }, - "is-number": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-0.1.1.tgz", - "integrity": "sha1-aaevEWlj1HIG7JvZtIoUIW8eOAY=", - "dev": true - }, - "repeat-string": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-0.2.2.tgz", - "integrity": "sha1-x6jTI2BoNiBZp+RlH8aITosftK4=", - "dev": true - } - } - }, - "expand-brackets": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", - "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", - "dev": true, - "requires": { - "is-posix-bracket": "^0.1.0" - } - }, - "expand-range": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", - "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", - "dev": true, - "requires": { - "fill-range": "^2.1.0" - } - }, - "express": { - "version": "4.16.4", - "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz", - "integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==", - "dev": true, - "requires": { - "accepts": "~1.3.5", - "array-flatten": "1.1.1", - "body-parser": "1.18.3", - "content-disposition": "0.5.2", - "content-type": "~1.0.4", - "cookie": "0.3.1", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.1.1", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.2", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.4", - "qs": "6.5.2", - "range-parser": "~1.2.0", - "safe-buffer": "5.1.2", - "send": "0.16.2", - "serve-static": "1.13.2", - "setprototypeof": "1.1.0", - "statuses": "~1.4.0", - "type-is": "~1.6.16", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "extglob": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", - "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" - } - }, - "extract-text-webpack-plugin": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/extract-text-webpack-plugin/-/extract-text-webpack-plugin-2.1.2.tgz", - "integrity": "sha1-dW7076gVXDaBgz+8NNpTuUF0bWw=", - "dev": true, - "requires": { - "async": "^2.1.2", - "loader-utils": "^1.0.2", - "schema-utils": "^0.3.0", - "webpack-sources": "^1.0.1" - }, - "dependencies": { - "loader-utils": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", - "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", - "dev": true, - "requires": { - "big.js": "^3.1.3", - "emojis-list": "^2.0.0", - "json5": "^0.5.0" - } - } - } - }, - "extract-zip": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.7.tgz", - "integrity": "sha1-qEC0uK9kAyZMjbV/Txp0Mz74H+k=", - "dev": true, - "requires": { - "concat-stream": "1.6.2", - "debug": "2.6.9", - "mkdirp": "0.5.1", - "yauzl": "2.4.1" - } - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true - }, - "fast-deep-equal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", - "dev": true - }, - "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "fastparse": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.1.tgz", - "integrity": "sha1-0eJkOzipTXWDtHkGDmxK/8lAcfg=", - "dev": true - }, - "fd-slicer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", - "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", - "dev": true, - "requires": { - "pend": "~1.2.0" - } - }, - "figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5", - "object-assign": "^4.1.0" - } - }, - "file-entry-cache": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", - "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", - "dev": true, - "requires": { - "flat-cache": "^1.2.1", - "object-assign": "^4.0.1" - } - }, - "file-loader": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-0.11.2.tgz", - "integrity": "sha512-N+uhF3mswIFeziHQjGScJ/yHXYt3DiLBeC+9vWW+WjUBiClMSOlV1YrXQi+7KM2aA3Rn4Bybgv+uXFQbfkzpvg==", - "dev": true, - "requires": { - "loader-utils": "^1.0.2" - }, - "dependencies": { - "loader-utils": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", - "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", - "dev": true, - "requires": { - "big.js": "^3.1.3", - "emojis-list": "^2.0.0", - "json5": "^0.5.0" - } - } - } - }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true - }, - "filename-regex": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", - "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", - "dev": true - }, - "filesize": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/filesize/-/filesize-3.6.1.tgz", - "integrity": "sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg==", - "dev": true - }, - "fill-range": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", - "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", - "dev": true, - "requires": { - "is-number": "^2.1.0", - "isobject": "^2.0.0", - "randomatic": "^3.0.0", - "repeat-element": "^1.1.2", - "repeat-string": "^1.5.2" - } - }, - "finalhandler": { - "version": "1.1.1", - "resolved": "http://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", - "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", - "dev": true, - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.2", - "statuses": "~1.4.0", - "unpipe": "~1.0.0" - } - }, - "find-cache-dir": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-0.1.1.tgz", - "integrity": "sha1-yN765XyKUqinhPnjHFfHQumToLk=", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "mkdirp": "^0.5.1", - "pkg-dir": "^1.0.0" - } - }, - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "flat-cache": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", - "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", - "dev": true, - "requires": { - "circular-json": "^0.3.1", - "del": "^2.0.2", - "graceful-fs": "^4.1.2", - "write": "^0.2.1" - }, - "dependencies": { - "del": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", - "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", - "dev": true, - "requires": { - "globby": "^5.0.0", - "is-path-cwd": "^1.0.0", - "is-path-in-cwd": "^1.0.0", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "rimraf": "^2.2.8" - } - }, - "globby": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", - "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", - "dev": true, - "requires": { - "array-union": "^1.0.1", - "arrify": "^1.0.0", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, - "flatten": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.2.tgz", - "integrity": "sha1-2uRqnXj74lKSJYzB54CkHZXAN4I=", - "dev": true - }, - "flush-write-stream": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz", - "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.4" - } - }, - "follow-redirects": { - "version": "1.5.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.9.tgz", - "integrity": "sha512-Bh65EZI/RU8nx0wbYF9shkFZlqLP+6WT/5FnA3cE/djNSuKNHJEinGGZgu/cQEkeeb2GdFOgenAmn8qaqYke2w==", - "dev": true, - "requires": { - "debug": "=3.1.0" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, - "font-awesome": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/font-awesome/-/font-awesome-4.7.0.tgz", - "integrity": "sha1-j6jPBBGhoxr9B7BtKQK7n8gVoTM=" - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, - "for-own": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", - "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", - "dev": true, - "requires": { - "for-in": "^1.0.1" - } - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true - }, - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "formatio": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.2.0.tgz", - "integrity": "sha1-87IWfZBoxGmKjVH092CjmlTYGOs=", - "dev": true, - "requires": { - "samsam": "1.x" - } - }, - "forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", - "dev": true - }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "requires": { - "map-cache": "^0.2.2" - } - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", - "dev": true - }, - "friendly-errors-webpack-plugin": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-1.7.0.tgz", - "integrity": "sha512-K27M3VK30wVoOarP651zDmb93R9zF28usW4ocaK3mfQeIEI5BPht/EzZs5E8QLLwbLRJQMwscAjDxYPb1FuNiw==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "error-stack-parser": "^2.0.0", - "string-width": "^2.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, - "from2": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", - "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.0" - } - }, - "fs-extra": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz", - "integrity": "sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^2.1.0", - "klaw": "^1.0.0" - } - }, - "fs-write-stream-atomic": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", - "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "iferr": "^0.1.5", - "imurmurhash": "^0.1.4", - "readable-stream": "1 || 2" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fsevents": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz", - "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", - "dev": true, - "optional": true, - "requires": { - "nan": "^2.12.1", - "node-pre-gyp": "^0.12.0" - }, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "debug": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ms": "^2.1.1" - } - }, - "deep-extend": { - "version": "0.6.0", - "bundled": true, - "dev": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "glob": { - "version": "7.1.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.24", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ignore-walk": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true, - "dev": true - }, - "ini": { - "version": "1.3.5", - "bundled": true, - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true, - "dev": true - }, - "minipass": { - "version": "2.3.5", - "bundled": true, - "dev": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.2.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "needle": { - "version": "2.3.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "debug": "^4.1.0", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.12.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4" - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npm-bundled": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true - }, - "npm-packlist": { - "version": "1.4.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "rimraf": { - "version": "2.6.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "glob": "^7.1.3" - } - }, - "safe-buffer": { - "version": "5.1.2", - "bundled": true, - "dev": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "bundled": true, - "dev": true, - "optional": true - }, - "semver": { - "version": "5.7.0", - "bundled": true, - "dev": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "tar": { - "version": "4.4.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.3.4", - "minizlib": "^1.1.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.2" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "wide-align": { - "version": "1.1.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "yallist": { - "version": "3.0.3", - "bundled": true, - "dev": true - } - } - }, - "ftp": { - "version": "0.3.10", - "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", - "integrity": "sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=", - "dev": true, - "requires": { - "readable-stream": "1.1.x", - "xregexp": "2.0.0" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - } - } - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "fuzzysearch": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/fuzzysearch/-/fuzzysearch-1.0.3.tgz", - "integrity": "sha1-3/yA9tawQiPyImqnndGUIxCW0Ag=" - }, - "generate-function": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", - "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", - "dev": true, - "requires": { - "is-property": "^1.0.2" - } - }, - "generate-object-property": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", - "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", - "dev": true, - "requires": { - "is-property": "^1.0.0" - } - }, - "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", - "dev": true - }, - "get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", - "dev": true - }, - "get-stream": { - "version": "3.0.0", - "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" - }, - "get-uri": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.2.tgz", - "integrity": "sha512-ZD325dMZOgerGqF/rF6vZXyFGTAay62svjQIT+X/oU2PtxYpFxvSkbsdi+oxIrsNxlZVd4y8wUDqkaExWTI/Cw==", - "dev": true, - "requires": { - "data-uri-to-buffer": "1", - "debug": "2", - "extend": "3", - "file-uri-to-path": "1", - "ftp": "~0.3.10", - "readable-stream": "2" - } - }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, - "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-base": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", - "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", - "dev": true, - "requires": { - "glob-parent": "^2.0.0", - "is-glob": "^2.0.0" - } - }, - "glob-parent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "dev": true, - "requires": { - "is-glob": "^2.0.0" - } - }, - "globals": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", - "dev": true - }, - "globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", - "dev": true, - "requires": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, - "got": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/got/-/got-8.3.2.tgz", - "integrity": "sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw==", - "requires": { - "@sindresorhus/is": "^0.7.0", - "cacheable-request": "^2.1.1", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^3.0.0", - "into-stream": "^3.1.0", - "is-retry-allowed": "^1.1.0", - "isurl": "^1.0.0-alpha5", - "lowercase-keys": "^1.0.0", - "mimic-response": "^1.0.0", - "p-cancelable": "^0.4.0", - "p-timeout": "^2.0.1", - "pify": "^3.0.0", - "safe-buffer": "^5.1.1", - "timed-out": "^4.0.1", - "url-parse-lax": "^3.0.0", - "url-to-options": "^1.0.1" - } - }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "graceful-readlink": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", - "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", - "dev": true - }, - "growl": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", - "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", - "dev": true - }, - "gzip-size": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-4.1.0.tgz", - "integrity": "sha1-iuCWJX6r59acRb4rZ8RIEk/7UXw=", - "dev": true, - "requires": { - "duplexer": "^0.1.1", - "pify": "^3.0.0" - } - }, - "handlebars": { - "version": "4.0.12", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.12.tgz", - "integrity": "sha512-RhmTekP+FZL+XNhwS1Wf+bTTZpdLougwt5pcgA1tuz6Jcx0fpH/7z0qd71RKnZHBCxIRBHfBOnio4gViPemNzA==", - "dev": true, - "requires": { - "async": "^2.5.0", - "optimist": "^0.6.1", - "source-map": "^0.6.1", - "uglify-js": "^3.1.4" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true - }, - "har-validator": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz", - "integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==", - "dev": true, - "requires": { - "ajv": "^5.3.0", - "har-schema": "^2.0.0" - } - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "has-binary": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/has-binary/-/has-binary-0.1.7.tgz", - "integrity": "sha1-aOYesWIQyVRaClzOBqhzkS/h5ow=", - "dev": true, - "requires": { - "isarray": "0.0.1" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - } - } - }, - "has-cors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", - "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=", - "dev": true - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "has-symbol-support-x": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", - "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==" - }, - "has-to-string-tag-x": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", - "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", - "requires": { - "has-symbol-support-x": "^1.4.1" - } - }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "dependencies": { - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "hash-base": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", - "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "hash-sum": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz", - "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=", - "dev": true - }, - "hash.js": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.5.tgz", - "integrity": "sha512-eWI5HG9Np+eHV1KQhisXWwM+4EPPYe5dFX1UZZH7k/E3JzDEazVH+VGlZi6R94ZqImq+A3D1mCEtrFIfg/E7sA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "hasha": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/hasha/-/hasha-2.2.0.tgz", - "integrity": "sha1-eNfL/B5tZjA/55g3NlmEUXsvbuE=", - "dev": true, - "requires": { - "is-stream": "^1.0.1", - "pinkie-promise": "^2.0.0" - } - }, - "he": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", - "dev": true - }, - "hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "dev": true, - "requires": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "home-or-tmp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", - "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", - "dev": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.1" - } - }, - "hosted-git-info": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", - "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", - "dev": true - }, - "html-comment-regex": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz", - "integrity": "sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==", - "dev": true - }, - "html-entities": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz", - "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=", - "dev": true - }, - "html-minifier": { - "version": "3.5.20", - "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.20.tgz", - "integrity": "sha512-ZmgNLaTp54+HFKkONyLFEfs5dd/ZOtlquKaTnqIWFmx3Av5zG6ZPcV2d0o9XM2fXOTxxIf6eDcwzFFotke/5zA==", - "dev": true, - "requires": { - "camel-case": "3.0.x", - "clean-css": "4.2.x", - "commander": "2.17.x", - "he": "1.1.x", - "param-case": "2.1.x", - "relateurl": "0.2.x", - "uglify-js": "3.4.x" - } - }, - "html-webpack-plugin": { - "version": "2.30.1", - "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-2.30.1.tgz", - "integrity": "sha1-f5xCG36pHsRg9WUn1430hO51N9U=", - "dev": true, - "requires": { - "bluebird": "^3.4.7", - "html-minifier": "^3.2.3", - "loader-utils": "^0.2.16", - "lodash": "^4.17.3", - "pretty-error": "^2.0.2", - "toposort": "^1.0.0" - } - }, - "htmlparser2": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz", - "integrity": "sha1-G9+HrMoPP55T+k/M6w9LTLsAszg=", - "dev": true, - "requires": { - "domelementtype": "^1.3.0", - "domhandler": "^2.3.0", - "domutils": "^1.5.1", - "entities": "^1.1.1", - "inherits": "^2.0.1", - "readable-stream": "^2.0.2" - } - }, - "http-cache-semantics": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", - "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==" - }, - "http-errors": { - "version": "1.6.3", - "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - } - }, - "http-proxy": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz", - "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==", - "dev": true, - "requires": { - "eventemitter3": "^3.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - } - }, - "http-proxy-agent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-1.0.0.tgz", - "integrity": "sha1-zBzjjkU7+YSg93AtLdWcc9CBKEo=", - "dev": true, - "requires": { - "agent-base": "2", - "debug": "2", - "extend": "3" - } - }, - "http-proxy-middleware": { - "version": "0.17.4", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.17.4.tgz", - "integrity": "sha1-ZC6ISIUdZvCdTxJJEoRtuutBuDM=", - "dev": true, - "requires": { - "http-proxy": "^1.16.2", - "is-glob": "^3.1.0", - "lodash": "^4.17.2", - "micromatch": "^2.3.11" - }, - "dependencies": { - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, - "https-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", - "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", - "dev": true - }, - "https-proxy-agent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", - "integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=", - "dev": true, - "requires": { - "agent-base": "2", - "debug": "2", - "extend": "3" - } - }, - "iconv-lite": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", - "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "icss-replace-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", - "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=", - "dev": true - }, - "icss-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-2.1.0.tgz", - "integrity": "sha1-g/Cg7DeL8yRheLbCrZE28TWxyWI=", - "dev": true, - "requires": { - "postcss": "^6.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "ieee754": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz", - "integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==", - "dev": true - }, - "iferr": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", - "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", - "dev": true - }, - "ignore": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", - "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", - "dev": true - }, - "immediate": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", - "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=" - }, - "imports-loader": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/imports-loader/-/imports-loader-0.7.1.tgz", - "integrity": "sha1-8gS180cCoywdt9SNidXoZ6BEElM=", - "dev": true, - "requires": { - "loader-utils": "^1.0.2", - "source-map": "^0.5.6" - }, - "dependencies": { - "loader-utils": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", - "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", - "dev": true, - "requires": { - "big.js": "^3.1.3", - "emojis-list": "^2.0.0", - "json5": "^0.5.0" - } - } - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "indent-string": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", - "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "dev": true, - "requires": { - "repeating": "^2.0.0" - } - }, - "indexes-of": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", - "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", - "dev": true - }, - "indexof": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", - "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", - "dev": true - }, - "inject-loader": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/inject-loader/-/inject-loader-3.0.1.tgz", - "integrity": "sha512-0Kd4NqMJUhknG4ECiJ/mgyHJBpfBBWZ3IKHl2BLNQiFtMO7/xiv9mmHl7mGvE0iKrBeQAZdMcQP3sMXZN0cqeg==", - "dev": true, - "requires": { - "babel-core": "~6" - } - }, - "inquirer": { - "version": "0.12.0", - "resolved": "http://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz", - "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", - "dev": true, - "requires": { - "ansi-escapes": "^1.1.0", - "ansi-regex": "^2.0.0", - "chalk": "^1.0.0", - "cli-cursor": "^1.0.1", - "cli-width": "^2.0.0", - "figures": "^1.3.5", - "lodash": "^4.3.0", - "readline2": "^1.0.1", - "run-async": "^0.1.0", - "rx-lite": "^3.1.2", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.0", - "through": "^2.3.6" - } - }, - "interpret": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", - "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", - "dev": true - }, - "into-stream": { - "version": "3.1.0", - "resolved": "http://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", - "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=", - "requires": { - "from2": "^2.1.1", - "p-is-promise": "^1.1.0" - } - }, - "invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dev": true, - "requires": { - "loose-envify": "^1.0.0" - } - }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true - }, - "ip": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.0.1.tgz", - "integrity": "sha1-x+NWzeoiWucbNtcPLnGpK6TkJZA=", - "dev": true - }, - "ipaddr.js": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz", - "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4=", - "dev": true - }, - "is-absolute-url": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", - "integrity": "sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=", - "dev": true - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "requires": { - "binary-extensions": "^1.0.0" - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-builtin-module": { - "version": "1.0.0", - "resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", - "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", - "dev": true, - "requires": { - "builtin-modules": "^1.0.0" - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "is-directory": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", - "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", - "dev": true - }, - "is-dotfile": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", - "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", - "dev": true - }, - "is-equal-shallow": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", - "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", - "dev": true, - "requires": { - "is-primitive": "^2.0.0" - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-finite": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", - "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" - } - }, - "is-my-ip-valid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz", - "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==", - "dev": true - }, - "is-my-json-valid": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.19.0.tgz", - "integrity": "sha512-mG0f/unGX1HZ5ep4uhRaPOS8EkAY8/j6mDRMJrutq4CqhoJWYp7qAlonIPy3TV7p3ju4TK9fo/PbnoksWmsp5Q==", - "dev": true, - "requires": { - "generate-function": "^2.0.0", - "generate-object-property": "^1.1.0", - "is-my-ip-valid": "^1.0.0", - "jsonpointer": "^4.0.0", - "xtend": "^4.0.0" - } - }, - "is-number": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", - "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - }, - "is-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", - "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=" - }, - "is-path-cwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", - "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", - "dev": true - }, - "is-path-in-cwd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", - "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", - "dev": true, - "requires": { - "is-path-inside": "^1.0.0" - } - }, - "is-path-inside": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", - "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", - "dev": true, - "requires": { - "path-is-inside": "^1.0.1" - } - }, - "is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "is-posix-bracket": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", - "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", - "dev": true - }, - "is-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", - "dev": true - }, - "is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" - }, - "is-property": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", - "dev": true - }, - "is-resolvable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", - "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", - "dev": true - }, - "is-retry-allowed": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", - "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=" - }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true - }, - "is-svg": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-2.1.0.tgz", - "integrity": "sha1-z2EJDaDZ77yrhyLeum8DIgjbsOk=", - "dev": true, - "requires": { - "html-comment-regex": "^1.1.0" - } - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "isbinaryfile": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz", - "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==", - "dev": true, - "requires": { - "buffer-alloc": "^1.2.0" - } - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true - }, - "istanbul": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", - "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", - "dev": true, - "requires": { - "abbrev": "1.0.x", - "async": "1.x", - "escodegen": "1.8.x", - "esprima": "2.7.x", - "glob": "^5.0.15", - "handlebars": "^4.0.1", - "js-yaml": "3.x", - "mkdirp": "0.5.x", - "nopt": "3.x", - "once": "1.x", - "resolve": "1.1.x", - "supports-color": "^3.1.0", - "which": "^1.1.1", - "wordwrap": "^1.0.0" - }, - "dependencies": { - "async": { - "version": "1.5.2", - "resolved": "http://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, - "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "resolve": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", - "dev": true - } - } - }, - "istanbul-lib-coverage": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz", - "integrity": "sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ==", - "dev": true - }, - "istanbul-lib-instrument": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz", - "integrity": "sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A==", - "dev": true, - "requires": { - "babel-generator": "^6.18.0", - "babel-template": "^6.16.0", - "babel-traverse": "^6.18.0", - "babel-types": "^6.18.0", - "babylon": "^6.18.0", - "istanbul-lib-coverage": "^1.2.1", - "semver": "^5.3.0" - } - }, - "isurl": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", - "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", - "requires": { - "has-to-string-tag-x": "^1.2.0", - "is-object": "^1.0.1" - } - }, - "jquery": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.3.1.tgz", - "integrity": "sha512-Ubldcmxp5np52/ENotGxlLe6aGMvmF4R8S6tZjsP6Knsaxd/xp3Zrh50cG93lR6nPXyUFwzN3ZSOQI0wRJNdGg==" - }, - "jquery-mousewheel": { - "version": "3.1.13", - "resolved": "https://registry.npmjs.org/jquery-mousewheel/-/jquery-mousewheel-3.1.13.tgz", - "integrity": "sha1-BvAzXxbjU6aV5yBr9QUDy1I6buU=" - }, - "jquery-validation": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/jquery-validation/-/jquery-validation-1.18.0.tgz", - "integrity": "sha512-+MK0pvoegfLrJnwtCU6tx305Vgp9HWevpmdVwDf5TthmINkn0wqqLD0bpa75EERlHsBBjMmza//ppx5ZQPnW3Q==", - "requires": { - "jquery": "^1.7 || ^2.0 || ^3.1" - } - }, - "jquery.easing": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jquery.easing/-/jquery.easing-1.4.1.tgz", - "integrity": "sha1-R5gsWDa9dY/UhJSSPEoQHvbpPjs=" - }, - "js-base64": { - "version": "2.4.9", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.9.tgz", - "integrity": "sha512-xcinL3AuDJk7VSzsHgb9DvvIXayBbadtMZ4HFPx8rUszbW1MuNMlwYVC4zzCZ6e1sqZpnNS5ZFYOhXqA39T7LQ==", - "dev": true - }, - "js-beautify": { - "version": "1.8.7", - "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.8.7.tgz", - "integrity": "sha512-yhAMCTv0L9GNg6Gql7i+g4C1z9rQhfHXy4J0TGYFoBzzHR4reWYS573gkRrPuE58dYOH451LmBeAb8L1pLEfdA==", - "dev": true, - "requires": { - "config-chain": "~1.1.5", - "editorconfig": "^0.15.0", - "mkdirp": "~0.5.0", - "nopt": "~4.0.1" - }, - "dependencies": { - "nopt": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", - "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", - "dev": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - } - } - }, - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true - }, - "js-yaml": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.7.0.tgz", - "integrity": "sha1-XJZ93YN6m/3KXy3oQlOr6KHAO4A=", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^2.6.0" - } - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true - }, - "jsesc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", - "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", - "dev": true - }, - "json-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=" - }, - "json-loader": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz", - "integrity": "sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w==", - "dev": true - }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true - }, - "json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", - "dev": true - }, - "json-stable-stringify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "dev": true, - "requires": { - "jsonify": "~0.0.0" - } - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true - }, - "json3": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", - "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", - "dev": true - }, - "json5": { - "version": "0.5.1", - "resolved": "http://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", - "dev": true - }, - "jsonfile": { - "version": "2.4.0", - "resolved": "http://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", - "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true - }, - "jsonpointer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", - "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", - "dev": true - }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "dev": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, - "jszip": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.1.5.tgz", - "integrity": "sha512-5W8NUaFRFRqTOL7ZDDrx5qWHJyBXy6velVudIzQUSoqAAYqzSh2Z7/m0Rf1QbmQJccegD0r+YZxBjzqoBiEeJQ==", - "requires": { - "core-js": "~2.3.0", - "es6-promise": "~3.0.2", - "lie": "~3.1.0", - "pako": "~1.0.2", - "readable-stream": "~2.0.6" - }, - "dependencies": { - "core-js": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.3.0.tgz", - "integrity": "sha1-+rg/uwstjchfpjbEudNMdUIMbWU=" - } - } - }, - "karma": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/karma/-/karma-1.7.1.tgz", - "integrity": "sha512-k5pBjHDhmkdaUccnC7gE3mBzZjcxyxYsYVaqiL2G5AqlfLyBO5nw2VdNK+O16cveEPd/gIOWULH7gkiYYwVNHg==", - "dev": true, - "requires": { - "bluebird": "^3.3.0", - "body-parser": "^1.16.1", - "chokidar": "^1.4.1", - "colors": "^1.1.0", - "combine-lists": "^1.0.0", - "connect": "^3.6.0", - "core-js": "^2.2.0", - "di": "^0.0.1", - "dom-serialize": "^2.2.0", - "expand-braces": "^0.1.1", - "glob": "^7.1.1", - "graceful-fs": "^4.1.2", - "http-proxy": "^1.13.0", - "isbinaryfile": "^3.0.0", - "lodash": "^3.8.0", - "log4js": "^0.6.31", - "mime": "^1.3.4", - "minimatch": "^3.0.2", - "optimist": "^0.6.1", - "qjobs": "^1.1.4", - "range-parser": "^1.2.0", - "rimraf": "^2.6.0", - "safe-buffer": "^5.0.1", - "socket.io": "1.7.3", - "source-map": "^0.5.3", - "tmp": "0.0.31", - "useragent": "^2.1.12" - }, - "dependencies": { - "lodash": { - "version": "3.10.1", - "resolved": "http://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", - "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", - "dev": true - } - } - }, - "karma-coverage": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/karma-coverage/-/karma-coverage-1.1.2.tgz", - "integrity": "sha512-eQawj4Cl3z/CjxslYy9ariU4uDh7cCNFZHNWXWRpl0pNeblY/4wHR7M7boTYXWrn9bY0z2pZmr11eKje/S/hIw==", - "dev": true, - "requires": { - "dateformat": "^1.0.6", - "istanbul": "^0.4.0", - "lodash": "^4.17.0", - "minimatch": "^3.0.0", - "source-map": "^0.5.1" - } - }, - "karma-mocha": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/karma-mocha/-/karma-mocha-1.3.0.tgz", - "integrity": "sha1-7qrH/8DiAetjxGdEDStpx883eL8=", - "dev": true, - "requires": { - "minimist": "1.2.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, - "karma-phantomjs-launcher": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/karma-phantomjs-launcher/-/karma-phantomjs-launcher-1.0.4.tgz", - "integrity": "sha1-0jyjSAG9qYY60xjju0vUBisTrNI=", - "dev": true, - "requires": { - "lodash": "^4.0.1", - "phantomjs-prebuilt": "^2.1.7" - } - }, - "karma-phantomjs-shim": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/karma-phantomjs-shim/-/karma-phantomjs-shim-1.5.0.tgz", - "integrity": "sha512-t0h1x7btXROaGElv36TLpuoWqTnVZ/f+GJHH/qVerjbX6AENoM5brQoB9ISO3hQ6zO1k9rDSRLrY5ZZb83ANdg==", - "dev": true - }, - "karma-sinon-chai": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/karma-sinon-chai/-/karma-sinon-chai-1.3.4.tgz", - "integrity": "sha512-Oatu8tdkfWaSveM809euI6KGcNJRdoXFilz9ozSf+vPwrM73kncu54nsfkLcMqR/iht3PXASAGK9La5oU2xDKQ==", - "dev": true, - "requires": { - "lolex": "^1.6.0" - } - }, - "karma-sourcemap-loader": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/karma-sourcemap-loader/-/karma-sourcemap-loader-0.3.7.tgz", - "integrity": "sha1-kTIsd/jxPUb+0GKwQuEAnUxFBdg=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2" - } - }, - "karma-spec-reporter": { - "version": "0.0.30", - "resolved": "https://registry.npmjs.org/karma-spec-reporter/-/karma-spec-reporter-0.0.30.tgz", - "integrity": "sha1-0Qtci7RByxxq31Z4X4nTlfLpCTo=", - "dev": true, - "requires": { - "colors": "^1.1.2" - } - }, - "karma-webpack": { - "version": "2.0.13", - "resolved": "http://registry.npmjs.org/karma-webpack/-/karma-webpack-2.0.13.tgz", - "integrity": "sha512-2cyII34jfrAabbI2+4Rk4j95Nazl98FvZQhgSiqKUDarT317rxfv/EdzZ60CyATN4PQxJdO5ucR5bOOXkEVrXw==", - "dev": true, - "requires": { - "async": "^2.0.0", - "babel-runtime": "^6.0.0", - "loader-utils": "^1.0.0", - "lodash": "^4.0.0", - "source-map": "^0.5.6", - "webpack-dev-middleware": "^1.12.0" - }, - "dependencies": { - "loader-utils": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", - "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", - "dev": true, - "requires": { - "big.js": "^3.1.3", - "emojis-list": "^2.0.0", - "json5": "^0.5.0" - } - } - } - }, - "kew": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/kew/-/kew-0.7.0.tgz", - "integrity": "sha1-edk9LTM2PW/dKXCzNdkUGtWR15s=", - "dev": true - }, - "keyv": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", - "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==", - "requires": { - "json-buffer": "3.0.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - }, - "klaw": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", - "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.9" - } - }, - "lazy-cache": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", - "dev": true - }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" - } - }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, - "lie": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz", - "integrity": "sha1-mkNrLMd0bKWd56QfpGmz77dr2H4=", - "requires": { - "immediate": "~3.0.5" - } - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, - "loader-fs-cache": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/loader-fs-cache/-/loader-fs-cache-1.0.1.tgz", - "integrity": "sha1-VuC/CL2XCLJqdltoUJhAyN7J/bw=", - "dev": true, - "requires": { - "find-cache-dir": "^0.1.1", - "mkdirp": "0.5.1" - } - }, - "loader-runner": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.1.tgz", - "integrity": "sha512-By6ZFY7ETWOc9RFaAIb23IjJVcM4dvJC/N57nmdz9RSkMXvAXGI7SyVlAw3v8vjtDRlqThgVDVmTnr9fqMlxkw==", - "dev": true - }, - "loader-utils": { - "version": "0.2.17", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", - "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", - "dev": true, - "requires": { - "big.js": "^3.1.3", - "emojis-list": "^2.0.0", - "json5": "^0.5.0", - "object-assign": "^4.0.1" - } - }, - "localforage": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/localforage/-/localforage-1.7.3.tgz", - "integrity": "sha512-1TulyYfc4udS7ECSBT2vwJksWbkwwTX8BzeUIiq8Y07Riy7bDAAnxDaPU/tWyOVmQAcWJIEIFP9lPfBGqVoPgQ==", - "requires": { - "lie": "3.1.1" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - }, - "dependencies": { - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - } - } - }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" - }, - "lodash._arraycopy": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._arraycopy/-/lodash._arraycopy-3.0.0.tgz", - "integrity": "sha1-due3wfH7klRzdIeKVi7Qaj5Q9uE=", - "dev": true - }, - "lodash._arrayeach": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._arrayeach/-/lodash._arrayeach-3.0.0.tgz", - "integrity": "sha1-urFWsqkNPxu9XGU0AzSeXlkz754=", - "dev": true - }, - "lodash._baseassign": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", - "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", - "dev": true, - "requires": { - "lodash._basecopy": "^3.0.0", - "lodash.keys": "^3.0.0" - } - }, - "lodash._baseclone": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/lodash._baseclone/-/lodash._baseclone-3.3.0.tgz", - "integrity": "sha1-MDUZv2OT/n5C802LYw73eU41Qrc=", - "dev": true, - "requires": { - "lodash._arraycopy": "^3.0.0", - "lodash._arrayeach": "^3.0.0", - "lodash._baseassign": "^3.0.0", - "lodash._basefor": "^3.0.0", - "lodash.isarray": "^3.0.0", - "lodash.keys": "^3.0.0" - } - }, - "lodash._basecopy": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", - "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", - "dev": true - }, - "lodash._basecreate": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", - "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=", - "dev": true - }, - "lodash._basefor": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash._basefor/-/lodash._basefor-3.0.3.tgz", - "integrity": "sha1-dVC06SGO8J+tJDQ7YSAhx5tMIMI=", - "dev": true - }, - "lodash._bindcallback": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz", - "integrity": "sha1-5THCdkTPi1epnhftlbNcdIeJOS4=", - "dev": true - }, - "lodash._getnative": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", - "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", - "dev": true - }, - "lodash._isiterateecall": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", - "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", - "dev": true - }, - "lodash._stack": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/lodash._stack/-/lodash._stack-4.1.3.tgz", - "integrity": "sha1-dRqnbBuWSwR+dtFPxyoJP8teLdA=", - "dev": true - }, - "lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", - "dev": true - }, - "lodash.clone": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-3.0.3.tgz", - "integrity": "sha1-hGiMc9MrWpDKJWFpY/GJJSqZcEM=", - "dev": true, - "requires": { - "lodash._baseclone": "^3.0.0", - "lodash._bindcallback": "^3.0.0", - "lodash._isiterateecall": "^3.0.0" - } - }, - "lodash.create": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", - "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", - "dev": true, - "requires": { - "lodash._baseassign": "^3.0.0", - "lodash._basecreate": "^3.0.0", - "lodash._isiterateecall": "^3.0.0" - } - }, - "lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", - "dev": true - }, - "lodash.defaultsdeep": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/lodash.defaultsdeep/-/lodash.defaultsdeep-4.3.2.tgz", - "integrity": "sha1-bBpYbmxWR7DmTi15gUG4g2FYvoo=", - "dev": true, - "requires": { - "lodash._baseclone": "^4.0.0", - "lodash._stack": "^4.0.0", - "lodash.isplainobject": "^4.0.0", - "lodash.keysin": "^4.0.0", - "lodash.mergewith": "^4.0.0", - "lodash.rest": "^4.0.0" - }, - "dependencies": { - "lodash._baseclone": { - "version": "4.5.7", - "resolved": "https://registry.npmjs.org/lodash._baseclone/-/lodash._baseclone-4.5.7.tgz", - "integrity": "sha1-zkKt4IOE711i+nfDD2GkbmhvhDQ=", - "dev": true - } - } - }, - "lodash.isarguments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", - "dev": true - }, - "lodash.isarray": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", - "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", - "dev": true - }, - "lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", - "dev": true - }, - "lodash.keys": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", - "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", - "dev": true, - "requires": { - "lodash._getnative": "^3.0.0", - "lodash.isarguments": "^3.0.0", - "lodash.isarray": "^3.0.0" - } - }, - "lodash.keysin": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.keysin/-/lodash.keysin-4.2.0.tgz", - "integrity": "sha1-jMP7NcLZSsxEOhhj4C+kB5nqbyg=", - "dev": true - }, - "lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", - "dev": true - }, - "lodash.mergewith": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz", - "integrity": "sha512-eWw5r+PYICtEBgrBE5hhlT6aAa75f411bgDz/ZL2KZqYV03USvucsxcHUIlGTDTECs1eunpI7HOV7U+WLDvNdQ==", - "dev": true - }, - "lodash.rest": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/lodash.rest/-/lodash.rest-4.0.5.tgz", - "integrity": "sha1-lU73UEkmIDjJbR/Jiyj9r58Hcqo=", - "dev": true - }, - "lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", - "dev": true - }, - "log-symbols": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", - "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", - "dev": true, - "requires": { - "chalk": "^2.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "log4js": { - "version": "0.6.38", - "resolved": "http://registry.npmjs.org/log4js/-/log4js-0.6.38.tgz", - "integrity": "sha1-LElBFmldb7JUgJQ9P8hy5mKlIv0=", - "dev": true, - "requires": { - "readable-stream": "~1.0.2", - "semver": "~4.3.3" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "semver": { - "version": "4.3.6", - "resolved": "http://registry.npmjs.org/semver/-/semver-4.3.6.tgz", - "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", - "dev": true - } - } - }, - "lolex": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.6.0.tgz", - "integrity": "sha1-OpoCg0UqR9dDnnJzG54H1zhuSfY=", - "dev": true - }, - "longest": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", - "dev": true - }, - "loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, - "requires": { - "js-tokens": "^3.0.0 || ^4.0.0" - } - }, - "loud-rejection": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", - "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", - "dev": true, - "requires": { - "currently-unhandled": "^0.4.1", - "signal-exit": "^3.0.0" - } - }, - "lower-case": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", - "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=", - "dev": true - }, - "lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" - }, - "lru-cache": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", - "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "make-dir": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", - "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", - "dev": true, - "requires": { - "pify": "^3.0.0" - } - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true - }, - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", - "dev": true - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "requires": { - "object-visit": "^1.0.0" - } - }, - "material-colors": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/material-colors/-/material-colors-1.2.6.tgz", - "integrity": "sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg==" - }, - "math-expression-evaluator": { - "version": "1.2.17", - "resolved": "https://registry.npmjs.org/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz", - "integrity": "sha1-3oGf282E3M2PrlnGrreWFbnSZqw=", - "dev": true - }, - "math-random": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.1.tgz", - "integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=", - "dev": true - }, - "md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "dev": true, - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", - "dev": true - }, - "memory-fs": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", - "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", - "dev": true, - "requires": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - } - }, - "meow": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", - "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", - "dev": true, - "requires": { - "camelcase-keys": "^2.0.0", - "decamelize": "^1.1.2", - "loud-rejection": "^1.0.0", - "map-obj": "^1.0.1", - "minimist": "^1.1.3", - "normalize-package-data": "^2.3.4", - "object-assign": "^4.0.1", - "read-pkg-up": "^1.0.1", - "redent": "^1.0.0", - "trim-newlines": "^1.0.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", - "dev": true - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", - "dev": true - }, - "micromatch": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", - "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "dev": true, - "requires": { - "arr-diff": "^2.0.0", - "array-unique": "^0.2.1", - "braces": "^1.8.2", - "expand-brackets": "^0.1.4", - "extglob": "^0.3.1", - "filename-regex": "^2.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.1", - "kind-of": "^3.0.2", - "normalize-path": "^2.0.1", - "object.omit": "^2.0.0", - "parse-glob": "^3.0.4", - "regex-cache": "^0.4.2" - } - }, - "miller-rabin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", - "dev": true, - "requires": { - "bn.js": "^4.0.0", - "brorand": "^1.0.1" - } - }, - "mime": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", - "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", - "dev": true - }, - "mime-db": { - "version": "1.36.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz", - "integrity": "sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw==", - "dev": true - }, - "mime-types": { - "version": "2.1.20", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz", - "integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==", - "dev": true, - "requires": { - "mime-db": "~1.36.0" - } - }, - "mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", - "dev": true - }, - "mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" - }, - "minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true - }, - "minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", - "dev": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - }, - "mississippi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-2.0.0.tgz", - "integrity": "sha512-zHo8v+otD1J10j/tC+VNoGK9keCuByhKovAvdn74dmxJl9+mWHnx6EMsDN4lgRoMI/eYo2nchAxniIbUPb5onw==", - "dev": true, - "requires": { - "concat-stream": "^1.5.0", - "duplexify": "^3.4.2", - "end-of-stream": "^1.1.0", - "flush-write-stream": "^1.0.0", - "from2": "^2.1.0", - "parallel-transform": "^1.1.0", - "pump": "^2.0.1", - "pumpify": "^1.3.3", - "stream-each": "^1.1.0", - "through2": "^2.0.0" - } - }, - "mixin-deep": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", - "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", - "dev": true, - "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, - "requires": { - "minimist": "0.0.8" - } - }, - "mkpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/mkpath/-/mkpath-1.0.0.tgz", - "integrity": "sha1-67Opd+evHGg65v2hK1Raa6bFhT0=", - "dev": true - }, - "mocha": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.5.3.tgz", - "integrity": "sha512-/6na001MJWEtYxHOV1WLfsmR4YIynkUEhBwzsb+fk2qmQ3iqsi258l/Q2MWHJMImAcNpZ8DEdYAK72NHoIQ9Eg==", - "dev": true, - "requires": { - "browser-stdout": "1.3.0", - "commander": "2.9.0", - "debug": "2.6.8", - "diff": "3.2.0", - "escape-string-regexp": "1.0.5", - "glob": "7.1.1", - "growl": "1.9.2", - "he": "1.1.1", - "json3": "3.3.2", - "lodash.create": "3.1.1", - "mkdirp": "0.5.1", - "supports-color": "3.1.2" - }, - "dependencies": { - "commander": { - "version": "2.9.0", - "resolved": "http://registry.npmjs.org/commander/-/commander-2.9.0.tgz", - "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", - "dev": true, - "requires": { - "graceful-readlink": ">= 1.0.0" - } - }, - "debug": { - "version": "2.6.8", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", - "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "glob": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", - "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.2", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "supports-color": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", - "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "mocha-nightwatch": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/mocha-nightwatch/-/mocha-nightwatch-3.2.2.tgz", - "integrity": "sha1-kby5s73gV912d8eBJeSR5Y1mZHw=", - "dev": true, - "requires": { - "browser-stdout": "1.3.0", - "commander": "2.9.0", - "debug": "2.2.0", - "diff": "1.4.0", - "escape-string-regexp": "1.0.5", - "glob": "7.0.5", - "growl": "1.9.2", - "json3": "3.3.2", - "lodash.create": "3.1.1", - "mkdirp": "0.5.1", - "supports-color": "3.1.2" - }, - "dependencies": { - "commander": { - "version": "2.9.0", - "resolved": "http://registry.npmjs.org/commander/-/commander-2.9.0.tgz", - "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", - "dev": true, - "requires": { - "graceful-readlink": ">= 1.0.0" - } - }, - "debug": { - "version": "2.2.0", - "resolved": "http://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "0.7.1" - } - }, - "diff": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz", - "integrity": "sha1-fyjS657nsVqX79ic5j3P2qPMur8=", - "dev": true - }, - "glob": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.5.tgz", - "integrity": "sha1-tCAqaQmbu00pKnwblbZoK2fr3JU=", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.2", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "ms": { - "version": "0.7.1", - "resolved": "http://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - }, - "supports-color": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", - "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "moment": { - "version": "2.22.2", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.22.2.tgz", - "integrity": "sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y=" - }, - "moment-range": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/moment-range/-/moment-range-3.1.1.tgz", - "integrity": "sha1-XFLPn6sp253ZvNhtN+UrBKenJxo=", - "requires": { - "es6-symbol": "^3.1.0" - } - }, - "moment-timezone": { - "version": "0.4.1", - "resolved": "http://registry.npmjs.org/moment-timezone/-/moment-timezone-0.4.1.tgz", - "integrity": "sha1-gfWYw61eIs2teWtn7NjYjQ9bqgY=", - "requires": { - "moment": ">= 2.6.0" - } - }, - "move-concurrently": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", - "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", - "dev": true, - "requires": { - "aproba": "^1.1.1", - "copy-concurrently": "^1.0.0", - "fs-write-stream-atomic": "^1.0.8", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.3" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "mute-stream": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", - "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=", - "dev": true - }, - "nan": { - "version": "2.13.2", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.13.2.tgz", - "integrity": "sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw==", - "dev": true, - "optional": true - }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - } - } - }, - "native-promise-only": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/native-promise-only/-/native-promise-only-0.8.1.tgz", - "integrity": "sha1-IKMYwwy0X3H+et+/eyHJnBRy7xE=", - "dev": true - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "negotiator": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", - "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", - "dev": true - }, - "neo-async": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.0.tgz", - "integrity": "sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==", - "dev": true - }, - "netmask": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/netmask/-/netmask-1.0.6.tgz", - "integrity": "sha1-ICl+idhvb2QA8lDZ9Pa0wZRfzTU=", - "dev": true - }, - "next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" - }, - "nightwatch": { - "version": "0.9.21", - "resolved": "https://registry.npmjs.org/nightwatch/-/nightwatch-0.9.21.tgz", - "integrity": "sha1-nnlKdRS0/V9GYC02jlBRUjKrnpA=", - "dev": true, - "requires": { - "chai-nightwatch": "~0.1.x", - "ejs": "2.5.7", - "lodash.clone": "3.0.3", - "lodash.defaultsdeep": "4.3.2", - "minimatch": "3.0.3", - "mkpath": "1.0.0", - "mocha-nightwatch": "3.2.2", - "optimist": "0.6.1", - "proxy-agent": "2.0.0", - "q": "1.4.1" - }, - "dependencies": { - "minimatch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha1-Kk5AkLlrLbBqnX3wEFWmKnfJt3Q=", - "dev": true, - "requires": { - "brace-expansion": "^1.0.0" - } - }, - "q": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", - "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=", - "dev": true - } - } - }, - "no-case": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", - "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", - "dev": true, - "requires": { - "lower-case": "^1.1.1" - } - }, - "node-libs-browser": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", - "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==", - "dev": true, - "requires": { - "assert": "^1.1.1", - "browserify-zlib": "^0.2.0", - "buffer": "^4.3.0", - "console-browserify": "^1.1.0", - "constants-browserify": "^1.0.0", - "crypto-browserify": "^3.11.0", - "domain-browser": "^1.1.1", - "events": "^1.0.0", - "https-browserify": "^1.0.0", - "os-browserify": "^0.3.0", - "path-browserify": "0.0.0", - "process": "^0.11.10", - "punycode": "^1.2.4", - "querystring-es3": "^0.2.0", - "readable-stream": "^2.3.3", - "stream-browserify": "^2.0.1", - "stream-http": "^2.7.2", - "string_decoder": "^1.0.0", - "timers-browserify": "^2.0.4", - "tty-browserify": "0.0.0", - "url": "^0.11.0", - "util": "^0.10.3", - "vm-browserify": "0.0.4" - }, - "dependencies": { - "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true, - "requires": { - "abbrev": "1" - } - }, - "normalize-package-data": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "is-builtin-module": "^1.0.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - }, - "normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", - "dev": true - }, - "normalize-url": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", - "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", - "requires": { - "prepend-http": "^2.0.0", - "query-string": "^5.0.1", - "sort-keys": "^2.0.0" - } - }, - "nth-check": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz", - "integrity": "sha1-mSms32KPwsQQmN6rgqxYDPFJquQ=", - "dev": true, - "requires": { - "boolbase": "~1.0.0" - } - }, - "num2fraction": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", - "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", - "dev": true - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - }, - "object-component": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", - "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=", - "dev": true - }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "object-hash": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-1.3.0.tgz", - "integrity": "sha512-05KzQ70lSeGSrZJQXE5wNDiTkBJDlUT/myi6RX9dVIvz7a7Qh4oH93BQdiPMn27nldYvVQCKMUaM83AfizZlsQ==", - "dev": true - }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "requires": { - "isobject": "^3.0.0" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "object.omit": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", - "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", - "dev": true, - "requires": { - "for-own": "^0.1.4", - "is-extendable": "^0.1.1" - } - }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "requires": { - "isobject": "^3.0.1" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dev": true, - "requires": { - "ee-first": "1.1.1" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "1.1.0", - "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", - "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", - "dev": true - }, - "opener": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.1.tgz", - "integrity": "sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA==", - "dev": true - }, - "opn": { - "version": "4.0.2", - "resolved": "http://registry.npmjs.org/opn/-/opn-4.0.2.tgz", - "integrity": "sha1-erwi5kTf9jsKltWrfyeQwPAavJU=", - "dev": true, - "requires": { - "object-assign": "^4.0.1", - "pinkie-promise": "^2.0.0" - } - }, - "optimist": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "dev": true, - "requires": { - "minimist": "~0.0.1", - "wordwrap": "~0.0.2" - }, - "dependencies": { - "wordwrap": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", - "dev": true - } - } - }, - "optimize-css-assets-webpack-plugin": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-1.3.2.tgz", - "integrity": "sha1-6ydFbiHu+9gIDzHoNoxZaE5YWiw=", - "dev": true, - "requires": { - "cssnano": "^3.4.0", - "underscore": "^1.8.3", - "webpack-sources": "^0.1.0" - }, - "dependencies": { - "source-list-map": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-0.1.8.tgz", - "integrity": "sha1-xVCyq1Qn9rPyH1r+rYjE9Vh7IQY=", - "dev": true - }, - "webpack-sources": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-0.1.5.tgz", - "integrity": "sha1-qh86vw8NdNtxEcQOUAuE+WZkB1A=", - "dev": true, - "requires": { - "source-list-map": "~0.1.7", - "source-map": "~0.5.3" - } - } - } - }, - "optionator": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", - "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", - "dev": true, - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.4", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "wordwrap": "~1.0.0" - } - }, - "options": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz", - "integrity": "sha1-7CLTEoBrtT5zF3Pnza788cZDEo8=", - "dev": true - }, - "ora": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ora/-/ora-1.4.0.tgz", - "integrity": "sha512-iMK1DOQxzzh2MBlVsU42G80mnrvUhqsMh74phHtDlrcTZPK0pH6o7l7DRshK+0YsxDyEuaOkziVdvM3T0QTzpw==", - "dev": true, - "requires": { - "chalk": "^2.1.0", - "cli-cursor": "^2.1.0", - "cli-spinners": "^1.0.1", - "log-symbols": "^2.1.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", - "dev": true, - "requires": { - "restore-cursor": "^2.0.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "dev": true, - "requires": { - "mimic-fn": "^1.0.0" - } - }, - "restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "dev": true, - "requires": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "os-browserify": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", - "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", - "dev": true - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true - }, - "os-locale": { - "version": "1.4.0", - "resolved": "http://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "requires": { - "lcid": "^1.0.0" - } - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true - }, - "osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "dev": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "p-cancelable": { - "version": "0.4.1", - "resolved": "http://registry.npmjs.org/p-cancelable/-/p-cancelable-0.4.1.tgz", - "integrity": "sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ==" - }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" - }, - "p-is-promise": { - "version": "1.1.0", - "resolved": "http://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", - "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=" - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-map": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", - "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", - "dev": true - }, - "p-timeout": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz", - "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==", - "requires": { - "p-finally": "^1.0.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, - "pac-proxy-agent": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-1.1.0.tgz", - "integrity": "sha512-QBELCWyLYPgE2Gj+4wUEiMscHrQ8nRPBzYItQNOHWavwBt25ohZHQC4qnd5IszdVVrFbLsQ+dPkm6eqdjJAmwQ==", - "dev": true, - "requires": { - "agent-base": "2", - "debug": "2", - "extend": "3", - "get-uri": "2", - "http-proxy-agent": "1", - "https-proxy-agent": "1", - "pac-resolver": "~2.0.0", - "raw-body": "2", - "socks-proxy-agent": "2" - } - }, - "pac-resolver": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-2.0.0.tgz", - "integrity": "sha1-mbiNLxk/ve78HJpSnB8yYKtSd80=", - "dev": true, - "requires": { - "co": "~3.0.6", - "degenerator": "~1.0.2", - "ip": "1.0.1", - "netmask": "~1.0.4", - "thunkify": "~2.1.1" - }, - "dependencies": { - "co": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/co/-/co-3.0.6.tgz", - "integrity": "sha1-FEXyJsXrlWE45oyawwFn6n0ua9o=", - "dev": true - } - } - }, - "pako": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", - "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==" - }, - "papaparse": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/papaparse/-/papaparse-4.6.1.tgz", - "integrity": "sha512-X9Ws5tnEQKRCZRfoojX3KvRZbLY1BbL0wqSHF3CKGmxD8Zr4E0WaipUuFweffkCN8RSQzHKhb/F+ATYdNcz1rg==" - }, - "parallel-transform": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz", - "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=", - "dev": true, - "requires": { - "cyclist": "~0.2.2", - "inherits": "^2.0.3", - "readable-stream": "^2.1.5" - }, - "dependencies": { - "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "param-case": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", - "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", - "dev": true, - "requires": { - "no-case": "^2.2.0" - } - }, - "parse-asn1": { - "version": "5.1.1", - "resolved": "http://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", - "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==", - "dev": true, - "requires": { - "asn1.js": "^4.0.0", - "browserify-aes": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3" - } - }, - "parse-glob": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", - "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", - "dev": true, - "requires": { - "glob-base": "^0.3.0", - "is-dotfile": "^1.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.0" - } - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } - }, - "parsejson": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/parsejson/-/parsejson-0.0.3.tgz", - "integrity": "sha1-q343WfIJ7OmUN5c/fQ8fZK4OZKs=", - "dev": true, - "requires": { - "better-assert": "~1.0.0" - } - }, - "parseqs": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", - "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", - "dev": true, - "requires": { - "better-assert": "~1.0.0" - } - }, - "parseuri": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", - "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", - "dev": true, - "requires": { - "better-assert": "~1.0.0" - } - }, - "parseurl": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", - "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", - "dev": true - }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true - }, - "path-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", - "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", - "dev": true - }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", - "dev": true - }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, - "pbkdf2": { - "version": "3.0.17", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", - "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", - "dev": true, - "requires": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", - "dev": true - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true - }, - "phantomjs-prebuilt": { - "version": "2.1.16", - "resolved": "https://registry.npmjs.org/phantomjs-prebuilt/-/phantomjs-prebuilt-2.1.16.tgz", - "integrity": "sha1-79ISpKOWbTZHaE6ouniFSb4q7+8=", - "dev": true, - "requires": { - "es6-promise": "^4.0.3", - "extract-zip": "^1.6.5", - "fs-extra": "^1.0.0", - "hasha": "^2.2.0", - "kew": "^0.7.0", - "progress": "^1.1.8", - "request": "^2.81.0", - "request-progress": "^2.0.1", - "which": "^1.2.10" - }, - "dependencies": { - "es6-promise": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.5.tgz", - "integrity": "sha512-n6wvpdE43VFtJq+lUDYDBFUwV8TZbuGXLV4D6wKafg13ldznKsyEvatubnmUe31zcvelSzOHF+XbaT+Bl9ObDg==", - "dev": true - } - } - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "requires": { - "pinkie": "^2.0.0" - } - }, - "pkg-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", - "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", - "dev": true, - "requires": { - "find-up": "^1.0.0" - } - }, - "pluralize": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz", - "integrity": "sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU=", - "dev": true - }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "postcss-calc": { - "version": "5.3.1", - "resolved": "http://registry.npmjs.org/postcss-calc/-/postcss-calc-5.3.1.tgz", - "integrity": "sha1-d7rnypKK2FcW4v2kLyYb98HWW14=", - "dev": true, - "requires": { - "postcss": "^5.0.2", - "postcss-message-helpers": "^2.0.0", - "reduce-css-calc": "^1.2.6" - } - }, - "postcss-colormin": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-2.2.2.tgz", - "integrity": "sha1-ZjFBfV8OkJo9fsJrJMio0eT5bks=", - "dev": true, - "requires": { - "colormin": "^1.0.5", - "postcss": "^5.0.13", - "postcss-value-parser": "^3.2.3" - } - }, - "postcss-convert-values": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-2.6.1.tgz", - "integrity": "sha1-u9hZPFwf0uPRwyK7kl3K6Nrk1i0=", - "dev": true, - "requires": { - "postcss": "^5.0.11", - "postcss-value-parser": "^3.1.2" - } - }, - "postcss-discard-comments": { - "version": "2.0.4", - "resolved": "http://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-2.0.4.tgz", - "integrity": "sha1-vv6J+v1bPazlzM5Rt2uBUUvgDj0=", - "dev": true, - "requires": { - "postcss": "^5.0.14" - } - }, - "postcss-discard-duplicates": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-2.1.0.tgz", - "integrity": "sha1-uavye4isGIFYpesSq8riAmO5GTI=", - "dev": true, - "requires": { - "postcss": "^5.0.4" - } - }, - "postcss-discard-empty": { - "version": "2.1.0", - "resolved": "http://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-2.1.0.tgz", - "integrity": "sha1-0rS9nVztXr2Nyt52QMfXzX9PkrU=", - "dev": true, - "requires": { - "postcss": "^5.0.14" - } - }, - "postcss-discard-overridden": { - "version": "0.1.1", - "resolved": "http://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-0.1.1.tgz", - "integrity": "sha1-ix6vVU9ob7KIzYdMVWZ7CqNmjVg=", - "dev": true, - "requires": { - "postcss": "^5.0.16" - } - }, - "postcss-discard-unused": { - "version": "2.2.3", - "resolved": "http://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-2.2.3.tgz", - "integrity": "sha1-vOMLLMWR/8Y0Mitfs0ZLbZNPRDM=", - "dev": true, - "requires": { - "postcss": "^5.0.14", - "uniqs": "^2.0.0" - } - }, - "postcss-filter-plugins": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/postcss-filter-plugins/-/postcss-filter-plugins-2.0.3.tgz", - "integrity": "sha512-T53GVFsdinJhgwm7rg1BzbeBRomOg9y5MBVhGcsV0CxurUdVj1UlPdKtn7aqYA/c/QVkzKMjq2bSV5dKG5+AwQ==", - "dev": true, - "requires": { - "postcss": "^5.0.4" - } - }, - "postcss-load-config": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-1.2.0.tgz", - "integrity": "sha1-U56a/J3chiASHr+djDZz4M5Q0oo=", - "dev": true, - "requires": { - "cosmiconfig": "^2.1.0", - "object-assign": "^4.1.0", - "postcss-load-options": "^1.2.0", - "postcss-load-plugins": "^2.3.0" - } - }, - "postcss-load-options": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postcss-load-options/-/postcss-load-options-1.2.0.tgz", - "integrity": "sha1-sJixVZ3awt8EvAuzdfmaXP4rbYw=", - "dev": true, - "requires": { - "cosmiconfig": "^2.1.0", - "object-assign": "^4.1.0" - } - }, - "postcss-load-plugins": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/postcss-load-plugins/-/postcss-load-plugins-2.3.0.tgz", - "integrity": "sha1-dFdoEWWZrKLwCfrUJrABdQSdjZI=", - "dev": true, - "requires": { - "cosmiconfig": "^2.1.1", - "object-assign": "^4.1.0" - } - }, - "postcss-merge-idents": { - "version": "2.1.7", - "resolved": "http://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-2.1.7.tgz", - "integrity": "sha1-TFUwMTwI4dWzu/PSu8dH4njuonA=", - "dev": true, - "requires": { - "has": "^1.0.1", - "postcss": "^5.0.10", - "postcss-value-parser": "^3.1.1" - } - }, - "postcss-merge-longhand": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-2.0.2.tgz", - "integrity": "sha1-I9kM0Sewp3mUkVMyc5A0oaTz1lg=", - "dev": true, - "requires": { - "postcss": "^5.0.4" - } - }, - "postcss-merge-rules": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-2.1.2.tgz", - "integrity": "sha1-0d9d+qexrMO+VT8OnhDofGG19yE=", - "dev": true, - "requires": { - "browserslist": "^1.5.2", - "caniuse-api": "^1.5.2", - "postcss": "^5.0.4", - "postcss-selector-parser": "^2.2.2", - "vendors": "^1.0.0" - } - }, - "postcss-message-helpers": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-message-helpers/-/postcss-message-helpers-2.0.0.tgz", - "integrity": "sha1-pPL0+rbk/gAvCu0ABHjN9S+bpg4=", - "dev": true - }, - "postcss-minify-font-values": { - "version": "1.0.5", - "resolved": "http://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-1.0.5.tgz", - "integrity": "sha1-S1jttWZB66fIR0qzUmyv17vey2k=", - "dev": true, - "requires": { - "object-assign": "^4.0.1", - "postcss": "^5.0.4", - "postcss-value-parser": "^3.0.2" - } - }, - "postcss-minify-gradients": { - "version": "1.0.5", - "resolved": "http://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-1.0.5.tgz", - "integrity": "sha1-Xb2hE3NwP4PPtKPqOIHY11/15uE=", - "dev": true, - "requires": { - "postcss": "^5.0.12", - "postcss-value-parser": "^3.3.0" - } - }, - "postcss-minify-params": { - "version": "1.2.2", - "resolved": "http://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-1.2.2.tgz", - "integrity": "sha1-rSzgcTc7lDs9kwo/pZo1jCjW8fM=", - "dev": true, - "requires": { - "alphanum-sort": "^1.0.1", - "postcss": "^5.0.2", - "postcss-value-parser": "^3.0.2", - "uniqs": "^2.0.0" - } - }, - "postcss-minify-selectors": { - "version": "2.1.1", - "resolved": "http://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-2.1.1.tgz", - "integrity": "sha1-ssapjAByz5G5MtGkllCBFDEXNb8=", - "dev": true, - "requires": { - "alphanum-sort": "^1.0.2", - "has": "^1.0.1", - "postcss": "^5.0.14", - "postcss-selector-parser": "^2.0.0" - } - }, - "postcss-modules-extract-imports": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.0.tgz", - "integrity": "sha1-ZhQOzs447wa/DT41XWm/WdFB6oU=", - "dev": true, - "requires": { - "postcss": "^6.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-modules-local-by-default": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz", - "integrity": "sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk=", - "dev": true, - "requires": { - "css-selector-tokenizer": "^0.7.0", - "postcss": "^6.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-modules-scope": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz", - "integrity": "sha1-1upkmUx5+XtipytCb75gVqGUu5A=", - "dev": true, - "requires": { - "css-selector-tokenizer": "^0.7.0", - "postcss": "^6.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-modules-values": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz", - "integrity": "sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA=", - "dev": true, - "requires": { - "icss-replace-symbols": "^1.1.0", - "postcss": "^6.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-normalize-charset": { - "version": "1.1.1", - "resolved": "http://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-1.1.1.tgz", - "integrity": "sha1-757nEhLX/nWceO0WL2HtYrXLk/E=", - "dev": true, - "requires": { - "postcss": "^5.0.5" - } - }, - "postcss-normalize-url": { - "version": "3.0.8", - "resolved": "http://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-3.0.8.tgz", - "integrity": "sha1-EI90s/L82viRov+j6kWSJ5/HgiI=", - "dev": true, - "requires": { - "is-absolute-url": "^2.0.0", - "normalize-url": "^1.4.0", - "postcss": "^5.0.14", - "postcss-value-parser": "^3.2.3" - }, - "dependencies": { - "normalize-url": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", - "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", - "dev": true, - "requires": { - "object-assign": "^4.0.1", - "prepend-http": "^1.0.0", - "query-string": "^4.1.0", - "sort-keys": "^1.0.0" - } - }, - "prepend-http": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", - "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", - "dev": true - }, - "query-string": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", - "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", - "dev": true, - "requires": { - "object-assign": "^4.1.0", - "strict-uri-encode": "^1.0.0" - } - }, - "sort-keys": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", - "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", - "dev": true, - "requires": { - "is-plain-obj": "^1.0.0" - } - } - } - }, - "postcss-ordered-values": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-2.2.3.tgz", - "integrity": "sha1-7sbCpntsQSqNsgQud/6NpD+VwR0=", - "dev": true, - "requires": { - "postcss": "^5.0.4", - "postcss-value-parser": "^3.0.1" - } - }, - "postcss-reduce-idents": { - "version": "2.4.0", - "resolved": "http://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-2.4.0.tgz", - "integrity": "sha1-wsbSDMlYKE9qv75j92Cb9AkFmtM=", - "dev": true, - "requires": { - "postcss": "^5.0.4", - "postcss-value-parser": "^3.0.2" - } - }, - "postcss-reduce-initial": { - "version": "1.0.1", - "resolved": "http://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-1.0.1.tgz", - "integrity": "sha1-aPgGlfBF0IJjqHmtJA343WT2ROo=", - "dev": true, - "requires": { - "postcss": "^5.0.4" - } - }, - "postcss-reduce-transforms": { - "version": "1.0.4", - "resolved": "http://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-1.0.4.tgz", - "integrity": "sha1-/3b02CEkN7McKYpC0uFEQCV3GuE=", - "dev": true, - "requires": { - "has": "^1.0.1", - "postcss": "^5.0.8", - "postcss-value-parser": "^3.0.1" - } - }, - "postcss-selector-parser": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz", - "integrity": "sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A=", - "dev": true, - "requires": { - "flatten": "^1.0.2", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } - }, - "postcss-svgo": { - "version": "2.1.6", - "resolved": "http://registry.npmjs.org/postcss-svgo/-/postcss-svgo-2.1.6.tgz", - "integrity": "sha1-tt8YqmE7Zm4TPwittSGcJoSsEI0=", - "dev": true, - "requires": { - "is-svg": "^2.0.0", - "postcss": "^5.0.14", - "postcss-value-parser": "^3.2.3", - "svgo": "^0.7.0" - } - }, - "postcss-unique-selectors": { - "version": "2.0.2", - "resolved": "http://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-2.0.2.tgz", - "integrity": "sha1-mB1X0p3csz57Hf4f1DuGSfkzyh0=", - "dev": true, - "requires": { - "alphanum-sort": "^1.0.1", - "postcss": "^5.0.4", - "uniqs": "^2.0.0" - } - }, - "postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", - "dev": true - }, - "postcss-zindex": { - "version": "2.2.0", - "resolved": "http://registry.npmjs.org/postcss-zindex/-/postcss-zindex-2.2.0.tgz", - "integrity": "sha1-0hCd3AVbka9n/EyzsCWUZjnSryI=", - "dev": true, - "requires": { - "has": "^1.0.1", - "postcss": "^5.0.4", - "uniqs": "^2.0.0" - } - }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true - }, - "prepend-http": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=" - }, - "preserve": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", - "dev": true - }, - "pretty-error": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.1.tgz", - "integrity": "sha1-X0+HyPkeWuPzuoerTPXgOxoX8aM=", - "dev": true, - "requires": { - "renderkid": "^2.0.1", - "utila": "~0.4" - } - }, - "private": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", - "dev": true - }, - "process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", - "dev": true - }, - "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" - }, - "progress": { - "version": "1.1.8", - "resolved": "http://registry.npmjs.org/progress/-/progress-1.1.8.tgz", - "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", - "dev": true - }, - "promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", - "dev": true - }, - "proto-list": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=", - "dev": true - }, - "proxy-addr": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz", - "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==", - "dev": true, - "requires": { - "forwarded": "~0.1.2", - "ipaddr.js": "1.8.0" - } - }, - "proxy-agent": { - "version": "2.0.0", - "resolved": "http://registry.npmjs.org/proxy-agent/-/proxy-agent-2.0.0.tgz", - "integrity": "sha1-V+tTR6qAXXTsaByyVknbo5yTNJk=", - "dev": true, - "requires": { - "agent-base": "2", - "debug": "2", - "extend": "3", - "http-proxy-agent": "1", - "https-proxy-agent": "1", - "lru-cache": "~2.6.5", - "pac-proxy-agent": "1", - "socks-proxy-agent": "2" - }, - "dependencies": { - "lru-cache": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.6.5.tgz", - "integrity": "sha1-5W1jVBSO3o13B7WNFDIg/QjfD9U=", - "dev": true - } - } - }, - "prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", - "dev": true - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, - "psl": { - "version": "1.1.29", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz", - "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==", - "dev": true - }, - "public-encrypt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", - "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "parse-asn1": "^5.0.0", - "randombytes": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dev": true, - "requires": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - } - }, - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - }, - "q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", - "dev": true - }, - "qjobs": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", - "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", - "dev": true - }, - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "dev": true - }, - "query-string": { - "version": "5.1.1", - "resolved": "http://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", - "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", - "requires": { - "decode-uri-component": "^0.2.0", - "object-assign": "^4.1.0", - "strict-uri-encode": "^1.0.0" - } - }, - "querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", - "dev": true - }, - "querystring-es3": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", - "dev": true - }, - "randomatic": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.0.tgz", - "integrity": "sha512-KnGPVE0lo2WoXxIZ7cPR8YBpiol4gsSuOwDSg410oHh80ZMp5EiypNqL2K4Z77vJn6lB5rap7IkAmcUlalcnBQ==", - "dev": true, - "requires": { - "is-number": "^4.0.0", - "kind-of": "^6.0.0", - "math-random": "^1.0.1" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - } - } - }, - "randombytes": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", - "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "randomfill": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", - "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", - "dev": true, - "requires": { - "randombytes": "^2.0.5", - "safe-buffer": "^5.1.0" - } - }, - "range-parser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", - "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", - "dev": true - }, - "raw-body": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", - "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", - "dev": true, - "requires": { - "bytes": "3.0.0", - "http-errors": "1.6.3", - "iconv-lite": "0.4.23", - "unpipe": "1.0.0" - } - }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - } - }, - "readable-stream": { - "version": "2.0.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", - "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "~1.0.0", - "process-nextick-args": "~1.0.6", - "string_decoder": "~0.10.x", - "util-deprecate": "~1.0.1" - } - }, - "readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - }, - "dependencies": { - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - } - } - }, - "readline2": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz", - "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "mute-stream": "0.0.5" - } - }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "requires": { - "resolve": "^1.1.6" - } - }, - "redent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", - "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", - "dev": true, - "requires": { - "indent-string": "^2.1.0", - "strip-indent": "^1.0.1" - } - }, - "reduce-css-calc": { - "version": "1.3.0", - "resolved": "http://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz", - "integrity": "sha1-dHyRTgSWFKTJz7umKYca0dKSdxY=", - "dev": true, - "requires": { - "balanced-match": "^0.4.2", - "math-expression-evaluator": "^1.2.14", - "reduce-function-call": "^1.0.1" - }, - "dependencies": { - "balanced-match": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", - "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", - "dev": true - } - } - }, - "reduce-function-call": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/reduce-function-call/-/reduce-function-call-1.0.2.tgz", - "integrity": "sha1-WiAL+S4ON3UXUv5FsKszD9S2vpk=", - "dev": true, - "requires": { - "balanced-match": "^0.4.2" - }, - "dependencies": { - "balanced-match": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", - "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", - "dev": true - } - } - }, - "regenerate": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", - "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", - "dev": true - }, - "regenerator-runtime": { - "version": "0.10.5", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", - "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=" - }, - "regenerator-transform": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", - "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", - "dev": true, - "requires": { - "babel-runtime": "^6.18.0", - "babel-types": "^6.19.0", - "private": "^0.1.6" - } - }, - "regex-cache": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", - "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", - "dev": true, - "requires": { - "is-equal-shallow": "^0.1.3" - } - }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - } - }, - "regexpu-core": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", - "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", - "dev": true, - "requires": { - "regenerate": "^1.2.1", - "regjsgen": "^0.2.0", - "regjsparser": "^0.1.4" - } - }, - "regjsgen": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", - "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", - "dev": true - }, - "regjsparser": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", - "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", - "dev": true, - "requires": { - "jsesc": "~0.5.0" - }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true - } - } - }, - "relateurl": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", - "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", - "dev": true - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true - }, - "renderkid": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.2.tgz", - "integrity": "sha512-FsygIxevi1jSiPY9h7vZmBFUbAOcbYm9UwyiLNdVsLRs/5We9Ob5NMPbGYUTWiLq5L+ezlVdE0A8bbME5CWTpg==", - "dev": true, - "requires": { - "css-select": "^1.1.0", - "dom-converter": "~0.2", - "htmlparser2": "~3.3.0", - "strip-ansi": "^3.0.0", - "utila": "^0.4.0" - }, - "dependencies": { - "domhandler": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.1.0.tgz", - "integrity": "sha1-0mRvXlf2w7qxHPbLBdPArPdBJZQ=", - "dev": true, - "requires": { - "domelementtype": "1" - } - }, - "domutils": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.1.6.tgz", - "integrity": "sha1-vdw94Jm5ou+sxRxiPyj0FuzFdIU=", - "dev": true, - "requires": { - "domelementtype": "1" - } - }, - "htmlparser2": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.3.0.tgz", - "integrity": "sha1-zHDQWln2VC5D8OaFyYLhTJJKnv4=", - "dev": true, - "requires": { - "domelementtype": "1", - "domhandler": "2.1", - "domutils": "1.1", - "readable-stream": "1.0" - } - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - } - } - }, - "repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true - }, - "repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dev": true, - "requires": { - "is-finite": "^1.0.0" - } - }, - "request": { - "version": "2.88.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", - "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", - "dev": true, - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.0", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - } - }, - "request-progress": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-2.0.1.tgz", - "integrity": "sha1-XTa7V5YcZzqlt4jbyBQf3yO0Tgg=", - "dev": true, - "requires": { - "throttleit": "^1.0.0" - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-from-string": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-1.2.1.tgz", - "integrity": "sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg=", - "dev": true - }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true - }, - "require-uncached": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", - "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", - "dev": true, - "requires": { - "caller-path": "^0.1.0", - "resolve-from": "^1.0.0" - } - }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", - "dev": true - }, - "resolve": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", - "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", - "dev": true, - "requires": { - "path-parse": "^1.0.5" - } - }, - "resolve-from": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", - "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", - "dev": true - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true - }, - "responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", - "requires": { - "lowercase-keys": "^1.0.0" - } - }, - "restore-cursor": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", - "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", - "dev": true, - "requires": { - "exit-hook": "^1.0.0", - "onetime": "^1.0.0" - } - }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true - }, - "right-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", - "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", - "dev": true, - "requires": { - "align-text": "^0.1.1" - } - }, - "rimraf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", - "dev": true, - "requires": { - "glob": "^7.0.5" - } - }, - "ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dev": true, - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "run-async": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", - "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", - "dev": true, - "requires": { - "once": "^1.3.0" - } - }, - "run-queue": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", - "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", - "dev": true, - "requires": { - "aproba": "^1.1.1" - } - }, - "rx-lite": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", - "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=", - "dev": true - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "requires": { - "ret": "~0.1.10" - } - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "samsam": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz", - "integrity": "sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==", - "dev": true - }, - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "dev": true - }, - "schema-utils": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz", - "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=", - "dev": true, - "requires": { - "ajv": "^5.0.0" - } - }, - "select2": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/select2/-/select2-4.0.5.tgz", - "integrity": "sha1-eqxQaSVhmFs007guxV4ib4lg1Ao=", - "requires": { - "almond": "~0.3.1", - "jquery-mousewheel": "~3.1.13" - } - }, - "select2-bootstrap-theme": { - "version": "0.1.0-beta.10", - "resolved": "https://registry.npmjs.org/select2-bootstrap-theme/-/select2-bootstrap-theme-0.1.0-beta.10.tgz", - "integrity": "sha1-uUJuz8A79KI152oTI3dXQxBGmsA=" - }, - "selenium-server": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/selenium-server/-/selenium-server-3.14.0.tgz", - "integrity": "sha512-+CCi1ED+7f36xpeGUqB8bWHde0To+9ZtegBHwWkbd9NsZcvANrtr8wlRNqHSD8yGmC0F7rixbgwiJEK9mTCLww==", - "dev": true - }, - "semver": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", - "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", - "dev": true - }, - "send": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", - "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", - "dev": true, - "requires": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "~1.6.2", - "mime": "1.4.1", - "ms": "2.0.0", - "on-finished": "~2.3.0", - "range-parser": "~1.2.0", - "statuses": "~1.4.0" - } - }, - "serialize-javascript": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.5.0.tgz", - "integrity": "sha512-Ga8c8NjAAp46Br4+0oZ2WxJCwIzwP60Gq1YPgU+39PiTVxyed/iKE/zyZI6+UlVYH5Q4PaQdHhcegIFPZTUfoQ==", - "dev": true - }, - "serve-static": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", - "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", - "dev": true, - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.2", - "send": "0.16.2" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "set-value": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", - "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true - }, - "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true - }, - "sha.js": { - "version": "2.4.11", - "resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true - }, - "shelljs": { - "version": "0.7.8", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.8.tgz", - "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=", - "dev": true, - "requires": { - "glob": "^7.0.0", - "interpret": "^1.0.0", - "rechoir": "^0.6.2" - } - }, - "sigmund": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", - "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", - "dev": true - }, - "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true - }, - "sinon": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-2.4.1.tgz", - "integrity": "sha512-vFTrO9Wt0ECffDYIPSP/E5bBugt0UjcBQOfQUMh66xzkyPEnhl/vM2LRZi2ajuTdkH07sA6DzrM6KvdvGIH8xw==", - "dev": true, - "requires": { - "diff": "^3.1.0", - "formatio": "1.2.0", - "lolex": "^1.6.0", - "native-promise-only": "^0.8.1", - "path-to-regexp": "^1.7.0", - "samsam": "^1.1.3", - "text-encoding": "0.6.4", - "type-detect": "^4.0.0" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "path-to-regexp": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", - "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", - "dev": true, - "requires": { - "isarray": "0.0.1" - } - }, - "type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true - } - } - }, - "sinon-chai": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-2.14.0.tgz", - "integrity": "sha512-9stIF1utB0ywNHNT7RgiXbdmen8QDCRsrTjw+G9TgKt1Yexjiv8TOWZ6WHsTPz57Yky3DIswZvEqX8fpuHNDtQ==", - "dev": true - }, - "slash": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", - "dev": true - }, - "slice-ansi": { - "version": "0.0.4", - "resolved": "http://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", - "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", - "dev": true - }, - "smart-buffer": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-1.1.15.tgz", - "integrity": "sha1-fxFLW2X6s+KjWqd1uxLw0cZJvxY=", - "dev": true - }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "requires": { - "kind-of": "^3.2.0" - } - }, - "socket.io": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-1.7.3.tgz", - "integrity": "sha1-uK+cq6AJSeVo42nxMn6pvp6iRhs=", - "dev": true, - "requires": { - "debug": "2.3.3", - "engine.io": "1.8.3", - "has-binary": "0.1.7", - "object-assign": "4.1.0", - "socket.io-adapter": "0.5.0", - "socket.io-client": "1.7.3", - "socket.io-parser": "2.3.1" - }, - "dependencies": { - "debug": { - "version": "2.3.3", - "resolved": "http://registry.npmjs.org/debug/-/debug-2.3.3.tgz", - "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=", - "dev": true, - "requires": { - "ms": "0.7.2" - } - }, - "ms": { - "version": "0.7.2", - "resolved": "http://registry.npmjs.org/ms/-/ms-0.7.2.tgz", - "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", - "dev": true - }, - "object-assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz", - "integrity": "sha1-ejs9DpgGPUP0wD8uiubNUahog6A=", - "dev": true - } - } - }, - "socket.io-adapter": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-0.5.0.tgz", - "integrity": "sha1-y21LuL7IHhB4uZZ3+c7QBGBmu4s=", - "dev": true, - "requires": { - "debug": "2.3.3", - "socket.io-parser": "2.3.1" - }, - "dependencies": { - "debug": { - "version": "2.3.3", - "resolved": "http://registry.npmjs.org/debug/-/debug-2.3.3.tgz", - "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=", - "dev": true, - "requires": { - "ms": "0.7.2" - } - }, - "ms": { - "version": "0.7.2", - "resolved": "http://registry.npmjs.org/ms/-/ms-0.7.2.tgz", - "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", - "dev": true - } - } - }, - "socket.io-client": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-1.7.3.tgz", - "integrity": "sha1-sw6GqhDV7zVGYBwJzeR2Xjgdo3c=", - "dev": true, - "requires": { - "backo2": "1.0.2", - "component-bind": "1.0.0", - "component-emitter": "1.2.1", - "debug": "2.3.3", - "engine.io-client": "1.8.3", - "has-binary": "0.1.7", - "indexof": "0.0.1", - "object-component": "0.0.3", - "parseuri": "0.0.5", - "socket.io-parser": "2.3.1", - "to-array": "0.1.4" - }, - "dependencies": { - "debug": { - "version": "2.3.3", - "resolved": "http://registry.npmjs.org/debug/-/debug-2.3.3.tgz", - "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=", - "dev": true, - "requires": { - "ms": "0.7.2" - } - }, - "ms": { - "version": "0.7.2", - "resolved": "http://registry.npmjs.org/ms/-/ms-0.7.2.tgz", - "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", - "dev": true - } - } - }, - "socket.io-parser": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-2.3.1.tgz", - "integrity": "sha1-3VMgJRA85Clpcya+/WQAX8/ltKA=", - "dev": true, - "requires": { - "component-emitter": "1.1.2", - "debug": "2.2.0", - "isarray": "0.0.1", - "json3": "3.3.2" - }, - "dependencies": { - "component-emitter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.1.2.tgz", - "integrity": "sha1-KWWU8nU9qmOZbSrwjRWpURbJrsM=", - "dev": true - }, - "debug": { - "version": "2.2.0", - "resolved": "http://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "0.7.1" - } - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "ms": { - "version": "0.7.1", - "resolved": "http://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - } - } - }, - "socks": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/socks/-/socks-1.1.10.tgz", - "integrity": "sha1-W4t/x8jzQcU+0FbpKbe/Tei6e1o=", - "dev": true, - "requires": { - "ip": "^1.1.4", - "smart-buffer": "^1.0.13" - }, - "dependencies": { - "ip": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", - "dev": true - } - } - }, - "socks-proxy-agent": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-2.1.1.tgz", - "integrity": "sha512-sFtmYqdUK5dAMh85H0LEVFUCO7OhJJe1/z2x/Z6mxp3s7/QPf1RkZmpZy+BpuU0bEjcV9npqKjq9Y3kwFUjnxw==", - "dev": true, - "requires": { - "agent-base": "2", - "extend": "3", - "socks": "~1.1.5" - } - }, - "sort-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", - "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", - "requires": { - "is-plain-obj": "^1.0.0" - } - }, - "source-list-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", - "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "source-map-resolve": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", - "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", - "dev": true, - "requires": { - "atob": "^2.1.1", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "source-map-support": { - "version": "0.4.18", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", - "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", - "dev": true, - "requires": { - "source-map": "^0.5.6" - } - }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true - }, - "spdx-correct": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.2.tgz", - "integrity": "sha512-q9hedtzyXHr5S0A1vEPoK/7l8NpfkFYTq6iCY+Pno2ZbdZR6WexZFtqeVGkGxW3TEJMN914Z55EnAGMmenlIQQ==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.1.tgz", - "integrity": "sha512-TfOfPcYGBB5sDuPn3deByxPhmfegAhpDYKSOXZQN81Oyrrif8ZCodOLzK3AesELnCx03kikhyDwh0pfvvQvF8w==", - "dev": true - }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.0" - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "sshpk": { - "version": "1.15.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.1.tgz", - "integrity": "sha512-mSdgNUaidk+dRU5MhYtN9zebdzF2iG0cNPWy8HG+W8y+fT1JnSkh0fzzpjOa0L7P8i1Rscz38t0h4gPcKz43xA==", - "dev": true, - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, - "ssri": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.3.0.tgz", - "integrity": "sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.1" - } - }, - "stackframe": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.0.4.tgz", - "integrity": "sha512-to7oADIniaYwS3MhtCa/sQhrxidCCQiF/qp4/m5iN3ipf0Y7Xlri0f6eG29r08aL7JYl8n32AF3Q5GYBZ7K8vw==", - "dev": true - }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "statuses": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", - "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", - "dev": true - }, - "stream-browserify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", - "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", - "dev": true, - "requires": { - "inherits": "~2.0.1", - "readable-stream": "^2.0.2" - } - }, - "stream-each": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", - "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "stream-shift": "^1.0.0" - } - }, - "stream-http": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", - "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", - "dev": true, - "requires": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.3.6", - "to-arraybuffer": "^1.0.0", - "xtend": "^4.0.0" - }, - "dependencies": { - "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "stream-shift": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", - "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", - "dev": true - }, - "strict-uri-encode": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", - "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" - } - }, - "strip-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", - "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", - "dev": true, - "requires": { - "get-stdin": "^4.0.1" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - }, - "svgo": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-0.7.2.tgz", - "integrity": "sha1-n1dyQTlSE1xv779Ar+ak+qiLS7U=", - "dev": true, - "requires": { - "coa": "~1.0.1", - "colors": "~1.1.2", - "csso": "~2.3.1", - "js-yaml": "~3.7.0", - "mkdirp": "~0.5.1", - "sax": "~1.2.1", - "whet.extend": "~0.9.9" - } - }, - "sweetalert2": { - "version": "6.11.5", - "resolved": "https://registry.npmjs.org/sweetalert2/-/sweetalert2-6.11.5.tgz", - "integrity": "sha512-8Otu1SlWGS/u3e31cOg+uqrwyoQbByEScKp7UupmCfwEZE9St3coO1e6CXv83YzZtzdDgowdK1hBPKPW7SRp4Q==" - }, - "table": { - "version": "3.8.3", - "resolved": "http://registry.npmjs.org/table/-/table-3.8.3.tgz", - "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", - "dev": true, - "requires": { - "ajv": "^4.7.0", - "ajv-keywords": "^1.0.0", - "chalk": "^1.1.1", - "lodash": "^4.0.0", - "slice-ansi": "0.0.4", - "string-width": "^2.0.0" - }, - "dependencies": { - "ajv": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", - "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", - "dev": true, - "requires": { - "co": "^4.6.0", - "json-stable-stringify": "^1.0.1" - } - }, - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, - "tapable": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.8.tgz", - "integrity": "sha1-mTcqXJmb8t8WCvwNdL7U9HlIzSI=", - "dev": true - }, - "test-exclude": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-4.2.3.tgz", - "integrity": "sha512-SYbXgY64PT+4GAL2ocI3HwPa4Q4TBKm0cwAVeKOt/Aoc0gSpNRjJX8w0pA1LMKZ3LBmd8pYBqApFNQLII9kavA==", - "dev": true, - "requires": { - "arrify": "^1.0.1", - "micromatch": "^2.3.11", - "object-assign": "^4.1.0", - "read-pkg-up": "^1.0.1", - "require-main-filename": "^1.0.1" - } - }, - "text-encoding": { - "version": "0.6.4", - "resolved": "http://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz", - "integrity": "sha1-45mpgiV6J22uQou5KEXLcb3CbRk=", - "dev": true - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "throttleit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", - "integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=", - "dev": true - }, - "through": { - "version": "2.3.8", - "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "through2": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "dev": true, - "requires": { - "readable-stream": "^2.1.5", - "xtend": "~4.0.1" - }, - "dependencies": { - "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "thunkify": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/thunkify/-/thunkify-2.1.2.tgz", - "integrity": "sha1-+qDp0jDFGsyVyhOjYawFyn4EVT0=", - "dev": true - }, - "time-stamp": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-2.1.0.tgz", - "integrity": "sha512-lJbq6KsFhZJtN3fPUVje1tq/hHsJOKUUcUj/MGCiQR6qWBDcyi5kxL9J7/RnaEChCn0+L/DUN2WvemDrkk4i3Q==", - "dev": true - }, - "timed-out": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", - "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=" - }, - "timers-browserify": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz", - "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==", - "dev": true, - "requires": { - "setimmediate": "^1.0.4" - } - }, - "tmp": { - "version": "0.0.31", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.31.tgz", - "integrity": "sha1-jzirlDjhcxXl29izZX6L+yd65Kc=", - "dev": true, - "requires": { - "os-tmpdir": "~1.0.1" - } - }, - "to-array": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", - "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", - "dev": true - }, - "to-arraybuffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", - "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", - "dev": true - }, - "to-fast-properties": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", - "dev": true - }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - }, - "dependencies": { - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - } - } - }, - "toposort": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/toposort/-/toposort-1.0.7.tgz", - "integrity": "sha1-LmhELZ9k7HILjMieZEOsbKqVACk=", - "dev": true - }, - "tough-cookie": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", - "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", - "dev": true, - "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" - } - }, - "trim-newlines": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", - "dev": true - }, - "trim-right": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", - "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", - "dev": true - }, - "tryer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz", - "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==", - "dev": true - }, - "tty-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", - "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", - "dev": true - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true - }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2" - } - }, - "type-detect": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz", - "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI=", - "dev": true - }, - "type-is": { - "version": "1.6.16", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", - "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", - "dev": true, - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.18" - } - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "uglify-js": { - "version": "3.4.9", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz", - "integrity": "sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==", - "dev": true, - "requires": { - "commander": "~2.17.1", - "source-map": "~0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "uglify-to-browserify": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", - "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", - "dev": true, - "optional": true - }, - "ultron": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz", - "integrity": "sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po=", - "dev": true - }, - "underscore": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", - "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==", - "dev": true - }, - "union-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", - "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^0.4.3" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "set-value": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", - "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.1", - "to-object-path": "^0.3.0" - } - } - } - }, - "uniq": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", - "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", - "dev": true - }, - "uniqs": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", - "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=", - "dev": true - }, - "unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", - "dev": true, - "requires": { - "unique-slug": "^2.0.0" - } - }, - "unique-slug": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.1.tgz", - "integrity": "sha512-n9cU6+gITaVu7VGj1Z8feKMmfAjEAQGhwD9fE3zvpRRa0wEIx8ODYkVGfSc94M2OX00tUFV8wH3zYbm1I8mxFg==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4" - } - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", - "dev": true - }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "upath": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz", - "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==", - "dev": true - }, - "upper-case": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", - "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=", - "dev": true - }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true - }, - "url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", - "dev": true, - "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" - }, - "dependencies": { - "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", - "dev": true - } - } - }, - "url-loader": { - "version": "0.5.9", - "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-0.5.9.tgz", - "integrity": "sha512-B7QYFyvv+fOBqBVeefsxv6koWWtjmHaMFT6KZWti4KRw8YUD/hOU+3AECvXuzyVawIBx3z7zQRejXCDSO5kk1Q==", - "dev": true, - "requires": { - "loader-utils": "^1.0.2", - "mime": "1.3.x" - }, - "dependencies": { - "loader-utils": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", - "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", - "dev": true, - "requires": { - "big.js": "^3.1.3", - "emojis-list": "^2.0.0", - "json5": "^0.5.0" - } - }, - "mime": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.6.tgz", - "integrity": "sha1-WR2E02U6awtKO5343lqoEI5y5eA=", - "dev": true - } - } - }, - "url-parse-lax": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", - "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", - "requires": { - "prepend-http": "^2.0.0" - } - }, - "url-to-options": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", - "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=" - }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true - }, - "user-home": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz", - "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=", - "dev": true, - "requires": { - "os-homedir": "^1.0.0" - } - }, - "useragent": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz", - "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==", - "dev": true, - "requires": { - "lru-cache": "4.1.x", - "tmp": "0.0.x" - } - }, - "util": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", - "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", - "dev": true, - "requires": { - "inherits": "2.0.3" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "utila": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", - "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=", - "dev": true - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", - "dev": true - }, - "uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", - "dev": true - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", - "dev": true - }, - "vee-validate": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/vee-validate/-/vee-validate-2.2.6.tgz", - "integrity": "sha512-6161TmZpKmxSOfU4BCoeFXlFVcXWEU5e1bx82K3KMfja2sE5xNIEwZd75K8rRrsXd94aKyr+2sTXr7r4seYAKA==" - }, - "vendors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.2.tgz", - "integrity": "sha512-w/hry/368nO21AN9QljsaIhb9ZiZtZARoVH5f3CsFbawdLdayCgKRPup7CggujvySMxx0I91NOyxdVENohprLQ==", - "dev": true - }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "vm-browserify": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", - "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", - "dev": true, - "requires": { - "indexof": "0.0.1" - } - }, - "void-elements": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", - "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", - "dev": true - }, - "vue": { - "version": "2.5.17", - "resolved": "https://registry.npmjs.org/vue/-/vue-2.5.17.tgz", - "integrity": "sha512-mFbcWoDIJi0w0Za4emyLiW72Jae0yjANHbCVquMKijcavBGypqlF7zHRgMa5k4sesdv7hv2rB4JPdZfR+TPfhQ==" - }, - "vue-hot-reload-api": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.1.tgz", - "integrity": "sha512-AA86yKZ5uOKz87/q1UpngEXhbRkaYg1b7HMMVRobNV1IVKqZe8oLIzo6iMocVwZXnYitlGwf2k4ZRLOZlS8oPQ==", - "dev": true - }, - "vue-loader": { - "version": "11.3.4", - "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-11.3.4.tgz", - "integrity": "sha1-ZeEKRM4JLZBuFLvHKYHeyZ6wkNI=", - "dev": true, - "requires": { - "consolidate": "^0.14.0", - "hash-sum": "^1.0.2", - "js-beautify": "^1.6.3", - "loader-utils": "^1.1.0", - "lru-cache": "^4.0.1", - "postcss": "^5.0.21", - "postcss-load-config": "^1.1.0", - "postcss-selector-parser": "^2.0.0", - "source-map": "^0.5.6", - "vue-hot-reload-api": "^2.0.11", - "vue-style-loader": "^2.0.0", - "vue-template-es2015-compiler": "^1.2.2" - }, - "dependencies": { - "loader-utils": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", - "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", - "dev": true, - "requires": { - "big.js": "^3.1.3", - "emojis-list": "^2.0.0", - "json5": "^0.5.0" - } - } - } - }, - "vue-resource": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/vue-resource/-/vue-resource-1.5.1.tgz", - "integrity": "sha512-o6V4wNgeqP+9v9b2bPXrr20CGNQPEXjpbUWdZWq9GJhqVeAGcYoeTtn/D4q059ZiyN0DIrDv/ADrQUmlUQcsmg==", - "requires": { - "got": "^8.0.3" - } - }, - "vue-router": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-2.8.1.tgz", - "integrity": "sha512-MC4jacHBhTPKtmcfzvaj2N7g6jgJ/Z/eIjZdt+yUaUOM1iKC0OUIlO/xCtz6OZFFTNUJs/1YNro2GN/lE+nOXA==" - }, - "vue-select": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/vue-select/-/vue-select-2.6.4.tgz", - "integrity": "sha512-OZIzzGlYwro2QcgAmcn2c4LQDPrYIT3+iaf4WciKPIeFFjgzRti6FC5Qjr2XEPqd85wqtsifuYyxsyb/JoJ4CQ==" - }, - "vue-style-loader": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-2.0.5.tgz", - "integrity": "sha1-8O+smS/r4/EuST4zTtsTzSNaPSI=", - "dev": true, - "requires": { - "hash-sum": "^1.0.2", - "loader-utils": "^1.0.2" - }, - "dependencies": { - "loader-utils": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", - "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", - "dev": true, - "requires": { - "big.js": "^3.1.3", - "emojis-list": "^2.0.0", - "json5": "^0.5.0" - } - } - } - }, - "vue-template-compiler": { - "version": "2.5.17", - "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.5.17.tgz", - "integrity": "sha512-63uI4syCwtGR5IJvZM0LN5tVsahrelomHtCxvRkZPJ/Tf3ADm1U1wG6KWycK3qCfqR+ygM5vewUvmJ0REAYksg==", - "dev": true, - "requires": { - "de-indent": "^1.0.2", - "he": "^1.1.0" - } - }, - "vue-template-es2015-compiler": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.6.0.tgz", - "integrity": "sha512-x3LV3wdmmERhVCYy3quqA57NJW7F3i6faas++pJQWtknWT+n7k30F4TVdHvCLn48peTJFRvCpxs3UuFPqgeELg==", - "dev": true - }, - "vuejs-paginator": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/vuejs-paginator/-/vuejs-paginator-2.0.2.tgz", - "integrity": "sha512-i9geMcFiAZw650CQ19rCrxeCIZcxXfa2aP2IXb4WzxnNheRLOh2OSbsmNl7+KHiMsJiaRVQsCrVi5hSQ4YuggQ==", - "requires": { - "vue": "^2.0.0", - "vue-resource": "^1.0.3" - } - }, - "watch-size": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/watch-size/-/watch-size-2.0.0.tgz", - "integrity": "sha512-M92R89dNoTPWyCD+HuUEDdhaDnh9jxPGOwlDc0u51jAgmjUvzqaEMynXSr3BaWs+QdHYk4KzibPy1TFtjLmOZQ==" - }, - "watchpack": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", - "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==", - "dev": true, - "requires": { - "chokidar": "^2.0.2", - "graceful-fs": "^4.1.2", - "neo-async": "^2.5.0" - }, - "dependencies": { - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - } - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "chokidar": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", - "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.0", - "braces": "^2.3.0", - "fsevents": "^1.2.2", - "glob-parent": "^3.1.0", - "inherits": "^2.0.1", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "lodash.debounce": "^4.0.8", - "normalize-path": "^2.1.1", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0", - "upath": "^1.0.5" - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-glob": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", - "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - } - } - }, - "webpack": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-2.7.0.tgz", - "integrity": "sha512-MjAA0ZqO1ba7ZQJRnoCdbM56mmFpipOPUv/vQpwwfSI42p5PVDdoiuK2AL2FwFUVgT859Jr43bFZXRg/LNsqvg==", - "dev": true, - "requires": { - "acorn": "^5.0.0", - "acorn-dynamic-import": "^2.0.0", - "ajv": "^4.7.0", - "ajv-keywords": "^1.1.1", - "async": "^2.1.2", - "enhanced-resolve": "^3.3.0", - "interpret": "^1.0.0", - "json-loader": "^0.5.4", - "json5": "^0.5.1", - "loader-runner": "^2.3.0", - "loader-utils": "^0.2.16", - "memory-fs": "~0.4.1", - "mkdirp": "~0.5.0", - "node-libs-browser": "^2.0.0", - "source-map": "^0.5.3", - "supports-color": "^3.1.0", - "tapable": "~0.2.5", - "uglify-js": "^2.8.27", - "watchpack": "^1.3.1", - "webpack-sources": "^1.0.1", - "yargs": "^6.0.0" - }, - "dependencies": { - "ajv": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", - "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", - "dev": true, - "requires": { - "co": "^4.6.0", - "json-stable-stringify": "^1.0.1" - } - }, - "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", - "dev": true - }, - "uglify-js": { - "version": "2.8.29", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", - "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", - "dev": true, - "requires": { - "source-map": "~0.5.1", - "uglify-to-browserify": "~1.0.0", - "yargs": "~3.10.0" - }, - "dependencies": { - "yargs": { - "version": "3.10.0", - "resolved": "http://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", - "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "dev": true, - "requires": { - "camelcase": "^1.0.2", - "cliui": "^2.1.0", - "decamelize": "^1.0.0", - "window-size": "0.1.0" - } - } - } - } - } - }, - "webpack-bundle-analyzer": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-2.13.1.tgz", - "integrity": "sha512-rwxyfecTAxoarCC9VlHlIpfQCmmJ/qWD5bpbjkof+7HrNhTNZIwZITxN6CdlYL2axGmwNUQ+tFgcSOiNXMf/sQ==", - "dev": true, - "requires": { - "acorn": "^5.3.0", - "bfj-node4": "^5.2.0", - "chalk": "^2.3.0", - "commander": "^2.13.0", - "ejs": "^2.5.7", - "express": "^4.16.2", - "filesize": "^3.5.11", - "gzip-size": "^4.1.0", - "lodash": "^4.17.4", - "mkdirp": "^0.5.1", - "opener": "^1.4.3", - "ws": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "ws": { - "version": "4.1.0", - "resolved": "http://registry.npmjs.org/ws/-/ws-4.1.0.tgz", - "integrity": "sha512-ZGh/8kF9rrRNffkLFV4AzhvooEclrOH0xaugmqGsIfFgOE/pIz4fMc4Ef+5HSQqTEug2S9JZIWDR47duDSLfaA==", - "dev": true, - "requires": { - "async-limiter": "~1.0.0", - "safe-buffer": "~5.1.0" - } - } - } - }, - "webpack-dev-middleware": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-1.12.2.tgz", - "integrity": "sha512-FCrqPy1yy/sN6U/SaEZcHKRXGlqU0DUaEBL45jkUYoB8foVb6wCnbIJ1HKIx+qUFTW+3JpVcCJCxZ8VATL4e+A==", - "dev": true, - "requires": { - "memory-fs": "~0.4.1", - "mime": "^1.5.0", - "path-is-absolute": "^1.0.0", - "range-parser": "^1.0.3", - "time-stamp": "^2.0.0" - }, - "dependencies": { - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true - } - } - }, - "webpack-hot-middleware": { - "version": "2.24.3", - "resolved": "https://registry.npmjs.org/webpack-hot-middleware/-/webpack-hot-middleware-2.24.3.tgz", - "integrity": "sha512-pPlmcdoR2Fn6UhYjAhp1g/IJy1Yc9hD+T6O9mjRcWV2pFbBjIFoJXhP0CoD0xPOhWJuWXuZXGBga9ybbOdzXpg==", - "dev": true, - "requires": { - "ansi-html": "0.0.7", - "html-entities": "^1.2.0", - "querystring": "^0.2.0", - "strip-ansi": "^3.0.0" - } - }, - "webpack-merge": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.1.4.tgz", - "integrity": "sha512-TmSe1HZKeOPey3oy1Ov2iS3guIZjWvMT2BBJDzzT5jScHTjVC3mpjJofgueEzaEd6ibhxRDD6MIblDr8tzh8iQ==", - "dev": true, - "requires": { - "lodash": "^4.17.5" - } - }, - "webpack-sources": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.3.0.tgz", - "integrity": "sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA==", - "dev": true, - "requires": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "whet.extend": { - "version": "0.9.9", - "resolved": "https://registry.npmjs.org/whet.extend/-/whet.extend-0.9.9.tgz", - "integrity": "sha1-+HfVv2SMl+WqVC+twW1qJZucEaE=", - "dev": true - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", - "dev": true - }, - "window-size": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", - "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", - "dev": true - }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true - }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "write": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", - "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", - "dev": true, - "requires": { - "mkdirp": "^0.5.1" - } - }, - "ws": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-1.1.2.tgz", - "integrity": "sha1-iiRPoFJAHgjJiGz0SoUYnh/UBn8=", - "dev": true, - "requires": { - "options": ">=0.0.5", - "ultron": "1.0.x" - } - }, - "wtf-8": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wtf-8/-/wtf-8-1.0.0.tgz", - "integrity": "sha1-OS2LotDxw00e4tYw8V0O+2jhBIo=", - "dev": true - }, - "xmlhttprequest-ssl": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.3.tgz", - "integrity": "sha1-GFqIjATspGw+QHDZn3tJ3jUomS0=", - "dev": true - }, - "xregexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", - "integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=", - "dev": true - }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true - }, - "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", - "dev": true - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - }, - "yargs": { - "version": "6.6.0", - "resolved": "http://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz", - "integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=", - "dev": true, - "requires": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^4.2.0" - }, - "dependencies": { - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true - }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - } - }, - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", - "dev": true - } - } - }, - "yargs-parser": { - "version": "4.2.1", - "resolved": "http://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz", - "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=", - "dev": true, - "requires": { - "camelcase": "^3.0.0" - }, - "dependencies": { - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true - } - } - }, - "yauzl": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz", - "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=", - "dev": true, - "requires": { - "fd-slicer": "~1.0.1" - } - }, - "yeast": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", - "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=", - "dev": true - } - } -} diff --git a/commercialoperator/frontend/commercialoperator/package.json b/commercialoperator/frontend/commercialoperator/package.json deleted file mode 100755 index 35ed96096b..0000000000 --- a/commercialoperator/frontend/commercialoperator/package.json +++ /dev/null @@ -1,125 +0,0 @@ -{ - "name": "commercialoperator", - "version": "1.0.0", - "description": "A Vue.js project", - "author": "Brian Ndwiga ", - "private": true, - "scripts": { - "dev": "node build/dev-server.js", - "start": "node build/dev-server.js", - "build": "node build/build.js", - "unit": "cross-env BABEL_ENV=test karma start test/unit/karma.conf.js --single-run", - "e2e": "node test/e2e/runner.js", - "test": "npm run unit && npm run e2e", - "lint": "eslint --ext .js,.vue src test/unit/specs test/e2e/specs" - }, - "dependencies": { - "@riophae/vue-treeselect": "^0.1.0", - "babel-polyfill": "^6.26.0", - "bootstrap": "^3.3.7", - "datatables.net": "^1.10.15", - "datatables.net-bs": "^1.10.15", - "datatables.net-buttons": "^1.5.3", - "datatables.net-responsive": "^2.1.1", - "datatables.net-responsive-bs": "^2.1.1", - "eonasdan-bootstrap-datetimepicker": "^4.17.47", - "font-awesome": "^4.7.0", - "jquery": "^3.2.1", - "jquery-validation": "^1.16.0", - "jquery.easing": "^1.4.1", - "jszip": "^3.1.5", - "localforage": "^1.7.3", - "lodash": "^4.17.4", - "moment": "^2.18.1", - "moment-range": "^3.0.3", - "papaparse": "^4.3.7", - "select2": "^4.0.3", - "select2-bootstrap-theme": "0.1.0-beta.10", - "sweetalert2": "^6.11.5", - "vee-validate": "^2.2.6", - "vue": "^2.2.6", - "vue-resource": "^1.3.3", - "vue-router": "^2.3.1", - "vue-select": "^2.6.4", - "vuejs-paginator": "^2.0.2" - }, - "devDependencies": { - "autoprefixer": "^6.7.7", - "babel-core": "^6.24.1", - "babel-eslint": "^7.2.3", - "babel-loader": "^6.4.1", - "babel-helper-vue-jsx-merge-props": "^2.0.2", - "babel-plugin-syntax-jsx": "^6.18.0", - "babel-plugin-transform-vue-jsx": "^3.4.3", - "babel-plugin-istanbul": "^4.1.3", - "babel-plugin-transform-runtime": "^6.23.0", - "babel-preset-env": "^1.5.0", - "babel-preset-es2015": "^6.24.1", - "babel-preset-stage-2": "^6.24.1", - "babel-register": "^6.24.1", - "chai": "^3.5.0", - "chalk": "^1.1.3", - "chromedriver": "^2.29.0", - "connect-history-api-fallback": "^1.3.0", - "copy-webpack-plugin": "^4.0.1", - "cross-env": "^4.0.0", - "cross-spawn": "^5.1.0", - "css-loader": "^0.28.1", - "eslint": "^3.19.0", - "eslint-config-standard": "^6.2.1", - "eslint-friendly-formatter": "^2.0.7", - "eslint-loader": "^1.7.1", - "eslint-plugin-html": "^2.0.3", - "eslint-plugin-promise": "^3.5.0", - "eslint-plugin-standard": "^2.3.1", - "eventsource-polyfill": "^0.9.6", - "express": "^4.15.3", - "extract-text-webpack-plugin": "^2.1.0", - "file-loader": "^0.11.1", - "friendly-errors-webpack-plugin": "^1.6.1", - "html-webpack-plugin": "^2.28.0", - "http-proxy-middleware": "^0.17.4", - "imports-loader": "^0.7.1", - "inject-loader": "^3.0.0", - "karma": "^1.7.0", - "karma-coverage": "^1.1.1", - "karma-mocha": "^1.3.0", - "karma-phantomjs-launcher": "^1.0.4", - "karma-phantomjs-shim": "^1.4.0", - "karma-sinon-chai": "^1.3.1", - "karma-sourcemap-loader": "^0.3.7", - "karma-spec-reporter": "0.0.30", - "karma-webpack": "^2.0.3", - "lolex": "^1.6.0", - "mocha": "^3.4.1", - "nightwatch": "^0.9.15", - "opn": "^4.0.2", - "optimize-css-assets-webpack-plugin": "^1.3.2", - "ora": "^1.2.0", - "phantomjs-prebuilt": "^2.1.14", - "rimraf": "^2.6.1", - "selenium-server": "^3.4.0", - "semver": "^5.3.0", - "shelljs": "^0.7.7", - "sinon": "^2.2.0", - "sinon-chai": "^2.10.0", - "url-loader": "^0.5.8", - "vue-loader": "^11.3.4", - "vue-style-loader": "^2.0.5", - "vue-template-compiler": "^2.3.3", - "webpack": "^2.5.1", - "webpack-bundle-analyzer": "^2.8.2", - "webpack-dev-middleware": "^1.10.2", - "webpack-hot-middleware": "^2.18.0", - "webpack-merge": "^4.1.0" - }, - "engines": { - "node": ">= 4.0.0", - "npm": ">= 3.0.0" - }, - "browserslist": [ - "> 1%", - "last 2 versions", - "not ie <= 8" - ] -} diff --git a/commercialoperator/frontend/commercialoperator/src/App.vue b/commercialoperator/frontend/commercialoperator/src/App.vue deleted file mode 100755 index 85ce0f31de..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/App.vue +++ /dev/null @@ -1,22 +0,0 @@ - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/api.js b/commercialoperator/frontend/commercialoperator/src/api.js deleted file mode 100755 index 5453d54e32..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/api.js +++ /dev/null @@ -1,78 +0,0 @@ -var site_url = location.origin - -module.exports = { - organisations: '/api/organisations.json', - filtered_organisations: '/api/filtered_organisations', - organisation_requests: '/api/organisation_requests.json', - organisation_contacts: '/api/organisation_contacts.json', - organisation_access_group_members: '/api/organisation_access_group_members', - users: '/api/users.json', - profile: '/api/profile', - department_users: '/api/department_users', - filtered_users: '/api/filtered_users', - referral_recipient_groups: '/api/referrals/user_group_list', - //other - countries: "https://restcountries.eu/rest/v1/?fullText=true", - proposal_type:"/api/proposal_type", - proposals:"/api/proposal.json", - proposal_park:"/api/proposal_park.json", - proposal_submit:"/api/proposal_submit.json", - //list_proposals:"/api/proposal/list_proposal.json", - approvals:"/api/approvals.json", - referrals:"/api/referrals.json", - compliances:"/api/compliances.json", - proposal_standard_requirements:"/api/proposal_standard_requirements.json", - proposal_requirements:"/api/proposal_requirements.json", - amendment_request:"/api/amendment_request.json", - regions:"/api/regions.json", - park_treeview:"/api/park_treeview", - marine_treeview:"/api/marine_treeview", - tclass_container_land:"/api/tclass_container_land", - tclass_container_marine:"/api/tclass_container_marine", - activity_matrix:"/api/activity_matrix.json", - application_types:"/api/application_types.json", - access_types:"/api/access_types.json", - parks:"/api/parks.json", - vehicles:"/api/vehicles.json", - vessels:"/api/vessels.json", - assessments:"/api/assessments.json", - - // used in internal and external dashboards - proposals_paginated_external: "/api/proposal_paginated/proposals_external/?format=datatables", - approvals_paginated_external: "/api/approval_paginated/approvals_external/?format=datatables", - compliances_paginated_external: "/api/compliance_paginated/compliances_external/?format=datatables", - proposals_paginated_internal: "/api/proposal_paginated/proposals_internal/?format=datatables", - referrals_paginated_internal: "/api/proposal_paginated/referrals_internal/?format=datatables", - qaofficer_paginated_internal: "/api/proposal_paginated/qaofficer_internal/?format=datatables", - booking_paginated_internal: "/api/booking_paginated/bookings_external/?format=datatables", - parkbooking_paginated_internal: "/api/parkbooking_paginated/parkbookings_external/?format=datatables", - //filter_list: "/api/proposal_paginated/filter_list.json", - filter_list: "/api/proposal/filter_list.json", - filter_list_approvals: "/api/approvals/filter_list.json", - filter_list_compliances: "/api/compliances/filter_list.json", - filter_list_referrals: "/api/referrals/filter_list.json", - filter_list_parks: "/api/parks/filter_list.json", - - //approvals_paginated:"/api/approvals/user_list_paginated/?format=datatables", - //compliances_paginated:"/api/compliances/user_list_paginated/?format=datatables", - //list_proposals:"/api/list_proposal/?format=datatables", - //list_referrals:"/api/list_proposal/referral_list/?format=datatables", - - discard_proposal:function (id) { - return `/api/proposal/${id}.json`; - }, - discard_vessel:function (id) { - return `/api/vessels/${id}.json`; - }, - discard_vehicle:function (id) { - return `/api/vehicles/${id}.json`; - }, - site_url: site_url, - //dep_name: 'Department of Biodiversity, Conservation and Attractions', - //dep_name_short: 'DBCA', - system_name: 'Commercial Operator Licensing System', - //system_name_short: 'DAS', - payment_help_url: 'https://parks.dpaw.wa.gov.au/for-business/training-accreditation-insurance-fees', - proposal_type_help_url: ' https://parks.dbca.wa.gov.au/for-business/commercial-operations-licensing', - -} diff --git a/commercialoperator/frontend/commercialoperator/src/assets/ans.json b/commercialoperator/frontend/commercialoperator/src/assets/ans.json deleted file mode 100755 index 19de89ebf6..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/assets/ans.json +++ /dev/null @@ -1,86 +0,0 @@ -[ - { - "activity": "yes" - }, - { - "project_details": [ - { - "project_proposal": "", - "project_title": "rtgrt", - "project_duration": "rftgstvrg", - "background_summary": "long text", - "conservation_outcomes": "", - "main_objectives": "objecti ve text" - } - ] - }, - { - "approvals_and_permits": [ - { - "requires_permits": "yes", - "permits_acknowledgement": "on", - "permits": "", - "aec_approval_number": "", - "aec_name": "", - "aec_application_and_approval": "" - } - ] - }, - { - "financial_basis": [ - { - "financial_details_other": "", - "grant_details": "", - "financial_basis": "grant", - "contract_details": "" - } - ] - }, - { - "personnel_details": [ - { - "qualification_attachment": "", - "ap_change_acknowledgement": "", - "authorised_persons": "", - "authorised_persons_acknowledgement": "", - "qualifications": "faddsad", - "ap_unavailable_explanation": "" - } - ] - }, - { - "project_description": [ - { - "research_fauna_release_quarantine": "", - "project_description": "research", - "research_fauna_hold_length": "", - "monitoring_survey_details": "", - "monitoring_plan": "", - "research_animal_husbandry": "", - "monitoring_conditional_requirement": "", - "research_fauna_activities": "", - "research_fauna_release_risk_assessment": "", - "monitoring_plan_acknowledgement": "", - "monitoring_approval_type": "", - "research_fauna_release_site": "", - "survey_survey_details": "", - "research_lab_details": "", - "research_details": "", - "research_fauna_disposal": "", - "research_lab_other_details": "", - "research_fauna_final_fate": "", - "research_fauna_post_release_monitoring": "", - "survey_num_survey_locations": "", - "survey_locations_calm_land": "", - "monitoring_monitoring_plan": "", - "research_type": "", - "research_num_research_locations": "", - "research_fauna_release_site_transportation": "", - "monitoring_locations_calm_land": "", - "research_fauna_stored": "", - "monitoring_num_monitoring_locations": "", - "research_fauna_retained_specimen": "" - } - ] - } -] diff --git a/commercialoperator/frontend/commercialoperator/src/assets/data.json b/commercialoperator/frontend/commercialoperator/src/assets/data.json deleted file mode 100755 index 972d820270..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/assets/data.json +++ /dev/null @@ -1,11396 +0,0 @@ -[ - { - "children": [ - { - "type": "text", - "name": "project_title", - "label": "Project title" - }, - { - "type": "text", - "name": "project_duration", - "label": "Total duration of the project" - }, - { - "type": "file", - "name": "project_proposal", - "label": "Project Proposal" - }, - { - "type": "text_area", - "name": "background_summary", - "label": "Background summary" - }, - { - "type": "text_area", - "name": "main_objectives", - "label": "Main Objectives" - }, - { - "type": "text_area", - "name": "conservation_outcomes", - "label": "Conservation outcomes" - } - ], - "type": "section", - "name": "project_details", - "label": "Project Details" - }, - { - "children": [ - { - "conditions": { - "yes": [ - { - "type": "file", - "name": "permits", - "label": "Please provide detail and attach any applications made or permissions granted." - }, - { - "type": "declaration", - "name": "permits_acknowledgement", - "label": "I acknowledge that should other permissions/approvals be required it may affect the processing time for this Regulation 17 licence" - } - ] - }, - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - }, - { - "value": "unsure", - "label": "Unsure" - } - ], - "type": "select", - "name": "requires_permits", - "label": "Does this project require any other approvals, permits, licences, etc under any other state or federal legislation?" - }, - { - "type": "text", - "name": "aec_name", - "label": "If activity has been (or is being) assessed by an Animal Ethics Committee (AEC) provide committee name." - }, - { - "type": "text", - "name": "aec_approval_number", - "label": "Provide AEC approval number." - }, - { - "type": "file", - "name": "aec_application_and_approval", - "label": "Attach a copy of the AEC project application and approval." - } - ], - "type": "section", - "name": "approvals_and_permits", - "label": "Approvals and Permits" - }, - { - "children": [ - { - "conditions": { - "other": [ - { - "type": "text_area", - "name": "financial_details_other", - "label": "Provide details of who is funding the project or how the project is being funded" - } - ], - "contract": [ - { - "type": "text_area", - "name": "contract_details", - "label": "Provide details of the Client, including name, address and contact details" - } - ], - "grant": [ - { - "type": "text_area", - "name": "grant_details", - "label": "Provide details of the grant or sponsorship, including name, address and contact details of the organisation funding the project" - } - ] - }, - "options": [ - { - "value": "grant", - "label": "Grant / Sponsored" - }, - { - "value": "contract", - "label": "Contract / Consulting" - }, - { - "value": "other", - "label": "Other - Please provide details" - } - ], - "type": "radiobuttons", - "name": "financial_basis", - "label": "How is your project funded?" - } - ], - "type": "section", - "name": "financial_basis", - "label": "Financial Basis" - }, - { - "children": [ - { - "type": "text", - "name": "qualifications", - "label": "Provide relevant qualifications and/or experience details specific to this project" - }, - { - "type": "file", - "name": "qualification_attachment", - "label": "Qualification Attachment(s)" - }, - { - "type": "declaration", - "name": "authorised_persons_acknowledgement", - "label": "I acknowledge that I am legally responsible for the actions of anyone involved in the take of fauna activities under this licence." - }, - { - "name": "authorised_persons", - "isLicenceField": true, - "isRepeatable": true, - "label": "Authorised Person", - "type": "group", - "children": [ - { - "isLicenceField": true, - "type": "text", - "name": "ap_surname", - "label": "Surname" - }, - { - "isLicenceField": true, - "type": "text", - "name": "ap_given_names", - "label": "Given name(s)" - }, - { - "type": "date", - "name": "ap_dob", - "label": "Date of birth" - }, - { - "name": "ap_association", - "type": "select", - "label": "Association to applicant", - "conditions": { - "other": [ - { - "type": "text", - "name": "ap_association_other_details", - "label": "Details" - } - ] - }, - "options": [ - { - "value": "volunteer", - "label": "Volunteer" - }, - { - "value": "contractor", - "label": "Contractor" - }, - { - "value": "staff", - "label": "Staff / Employee" - }, - { - "value": "student", - "label": "Student" - }, - { - "value": "other", - "label": "Other - Please provide details" - } - ], - "defaultBlank": true - }, - { - "name": "ap_role", - "type": "select", - "label": "Role", - "conditions": { - "handler": [ - { - "type": "label", - "name": "ap_handler_type", - "label": "Handler Type" - }, - { - "type": "checkbox", - "name": "ap_biopsy", - "label": "Biopsy" - }, - { - "type": "checkbox", - "name": "ap_chipping", - "label": "Chipping" - }, - { - "type": "checkbox", - "name": "ap_collaring", - "label": "Collaring" - }, - { - "type": "checkbox", - "name": "ap_anasthaesia", - "label": "Anasthaesia" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "ap_handler_other_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "ap_handler_other", - "label": "Other" - } - ] - }, - "options": [ - { - "value": "handler", - "label": "Handler" - }, - { - "value": "scribe", - "label": "Scribe" - }, - { - "value": "assistant", - "label": "Assistant" - } - ], - "defaultBlank": true - }, - { - "type": "file", - "name": "ap_qualification", - "label": "Provide relevant qualification / experience (relative to activity)" - } - ] - }, - { - "type": "text_area", - "name": "ap_unavailable_explanation", - "label": "If a list of authorised persons is not currently available, please explain:" - }, - { - "type": "declaration", - "name": "ap_change_acknowledgement", - "label": "I acknowledge that I will make changes in this system to authorised persons throughout licence duration if changes are required" - } - ], - "type": "section", - "name": "personnel_details", - "label": "Personnel Details" - }, - { - "children": [ - { - "name": "project_description", - "type": "select", - "label": "Which of the following describes your project?", - "conditions": { - "monitoring": [ - { - "conditions": { - "yes": [ - { - "type": "text", - "name": "monitoring_approval_type", - "label": "Provide approval type and number." - } - ] - }, - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "monitoring_conditional_requirement", - "label": "Is the monitoring being done as a conditional requirement of an approval?" - }, - { - "conditions": { - "yes": [ - { - "type": "file", - "name": "monitoring_plan", - "label": "Please attach monitoring plan.", - "isRepeatable":true - }, - { - "type": "declaration", - "name": "monitoring_plan_acknowledgement", - "label": "I acknowledge that should additional monitoring plans be required it may affect the processing time for this Regulation 17 licence." - } - ] - }, - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "monitoring_monitoring_plan", - "label": "Is there a monitoring plan?" - }, - { - "type": "number", - "name": "monitoring_num_monitoring_locations", - "label": "How many locations will be monitored?" - }, - { - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - }, - { - "value": "unsure", - "label": "Unsure" - } - ], - "type": "radiobuttons", - "name": "monitoring_locations_calm_land", - "label": "Are any locations on CALM Act land?" - }, - { - "name": "monitoring_survey_details", - "isRepeatable": true, - "help_text": "If multiple monitoring locations; provide details separately for each location and add an additional location after the methods section for the first location.", - "label": "Monitoring Details", - "type": "group", - "children": [ - { - "type": "text_area", - "name": "monitoring_address", - "label": "Location / Address" - }, - { - "type": "text", - "name": "monitoring_coordinates", - "label": "Coordinate / GPS", - "help_text": "If multiple monitoring locations; provide details separately for each location and add an additional location after the methods section for the first location." - }, - { - "children": [ - { - "type": "date", - "name": "monitoring_field_session_start_date", - "label": "Start Date" - }, - { - "type": "date", - "name": "monitoring_field_session_end_date", - "label": "End Date" - } - ], - "isRepeatable": true, - "type": "group", - "name": "monitoring_field_session", - "label": "Field session" - }, - { - "type": "text", - "name": "monitoring_field_dates_unknown", - "label": "If field dates are unknown, use anticipated field dates in the start and end date above and explain below." - }, - { - "name": "monitoring_interval_regularity", - "type": "select", - "label": "Interval Regularity", - "conditions": { - "other": [ - { - "type": "text", - "name": "monitoring_regular_intervals_other", - "label": "Please Specify" - } - ] - }, - "options": [ - { - "value": "not_regular_intervals", - "label": "Not regular intervals" - }, - { - "value": "weekly", - "label": "Weekly" - }, - { - "value": "fortnightly", - "label": "Fortnightly" - }, - { - "value": "monthly", - "label": "Monthly" - }, - { - "value": "quarterly", - "label": "Quarterly/Seasonally" - }, - { - "value": "biannually", - "label": "Biannually/Six-monthly" - }, - { - "value": "annually", - "label": "Annually" - }, - { - "value": "biennually", - "label": "Biennially/Every two years" - }, - { - "value": "other", - "label": "Other" - } - ], - "defaultBlank": false - }, - { - "conditions": { - "yes": [ - { - "children": [ - { - "type": "text", - "name": "monitoring_tft_group_name", - "label": "Group name" - }, - { - "speciesType": "fauna", - "type": "species", - "name": "monitoring_tft_scientific_name", - "label": "Scientific or common name" - } - ], - "isRepeatable": true, - "type": "group", - "name": "monitoring_targeted_fauna", - "label": "Targeted Fauna Type" - } - ] - }, - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "monitoring_targeting_species_or_fauna", - "label": "Is the monitoring targeting a species or fauna group?" - }, - { - "conditions": { - "yes": [ - { - "children": [ - { - "type": "text", - "name": "monitoring_threatened_group_name", - "label": "Group name" - }, - { - "speciesType": "fauna", - "type": "species", - "name": "monitoring_threatened_scientific_name", - "label": "Scientific or common name" - } - ], - "isRepeatable": true, - "type": "group", - "name": "monitoring_threatened_fauna", - "label": "Threatened Fauna" - } - ] - }, - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - }, - { - "value": "unknown", - "label": "Unknown" - } - ], - "type": "radiobuttons", - "name": "monitoring_threatened_priority_fauna", - "label": "Will your activity possibly interact with any threatened or priority fauna (including non-target species)?" - }, - { - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "monitoring_standard_operating_procedures", - "label": "Will your activities be in accordance with Parks and Wildlife standard operating procedures?" - }, - { - "conditions": { - "yes": [ - { - "type": "text", - "name": "monitoring_sops_details", - "label": "Provide details" - }, - { - "type": "file", - "name": "monitoring_sops_documents", - "label": "Attach a copy of the relevent document(s)" - } - ] - }, - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "monitoring_sops", - "label": "Will your activities be in accordance with any other SOPs, protocols, guidelines or manuals?" - }, - { - "conditions": { - "capture": [ - { - "conditions": { - "net": [ - { - "type": "number", - "name": "monitoring_num_net_sites", - "label": "What is the number of sites where nets will be used?" - }, - { - "type": "number", - "name": "monitoring_num_net_days", - "label": "How many days/nights will nets be used?" - }, - { - "type": "number", - "name": "monitoring_num_net_sessions", - "label": "How many sessions will nets be used?" - }, - { - "type": "number", - "name": "monitoring_num_nets_per_session", - "label": "Total number of nets per session?" - }, - { - "type": "number", - "name": "monitoring_max_num_nets_per_session_per_site", - "label": "Maximum total number of nets per site per session?" - }, - { - "type": "text_area", - "name": "monitoring_different_num_nets_per_session_or_site_explanation", - "label": "If the number of nets differs between sessions or sites then explain" - }, - { - "type": "label", - "name": "monitoring_nets", - "label": "Nets" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "monitoring_dip_make", - "label": "Make" - }, - { - "type": "text", - "name": "monitoring_dip_size", - "label": "Size" - }, - { - "type": "number", - "name": "monitoring_num_dips", - "label": "Number of nets" - }, - { - "type": "text", - "name": "monitoring_dip_placement", - "label": "Net Placement" - }, - { - "type": "text", - "name": "monitoring_dip_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "monitoring_dip_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "monitoring_dip", - "label": "Dip" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "monitoring_sweep_make", - "label": "Make" - }, - { - "type": "text", - "name": "monitoring_sweep_size", - "label": "Size" - }, - { - "type": "number", - "name": "monitoring_num_sweeps", - "label": "Number of nets" - }, - { - "type": "text", - "name": "monitoring_sweep_placement", - "label": "Net Placement" - }, - { - "type": "text", - "name": "monitoring_sweep_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "monitoring_sweep_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "monitoring_sweep", - "label": "Sweep" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "monitoring_gill_make", - "label": "Make" - }, - { - "type": "text", - "name": "monitoring_gill_size", - "label": "Size" - }, - { - "type": "number", - "name": "monitoring_num_gills", - "label": "Number of nets" - }, - { - "type": "text", - "name": "monitoring_gill_placement", - "label": "Net Placement" - }, - { - "type": "text", - "name": "monitoring_gill_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "monitoring_gill_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "monitoring_gill", - "label": "Gill" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "monitoring_seine_make", - "label": "Make" - }, - { - "type": "text", - "name": "monitoring_seine_size", - "label": "Size" - }, - { - "type": "number", - "name": "monitoring_num_seines", - "label": "Number of nets" - }, - { - "type": "text", - "name": "monitoring_seine_placement", - "label": "Net Placement" - }, - { - "type": "text", - "name": "monitoring_seine_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "monitoring_seine_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "monitoring_seine", - "label": "Seine" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "monitoring_cast_make", - "label": "Make" - }, - { - "type": "text", - "name": "monitoring_cast_size", - "label": "Size" - }, - { - "type": "number", - "name": "monitoring_num_casts", - "label": "Number of nets" - }, - { - "type": "text", - "name": "monitoring_cast_placement", - "label": "Net Placement" - }, - { - "type": "text", - "name": "monitoring_cast_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "monitoring_cast_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "monitoring_cast", - "label": "Cast" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "monitoring_plankton_make", - "label": "Make" - }, - { - "type": "text", - "name": "monitoring_plankton_size", - "label": "Size" - }, - { - "type": "number", - "name": "monitoring_num_planktons", - "label": "Number of nets" - }, - { - "type": "text", - "name": "monitoring_plankton_placement", - "label": "Net Placement" - }, - { - "type": "text", - "name": "monitoring_plankton_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "monitoring_plankton_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "monitoring_plankton", - "label": "Plankton" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "monitoring_mist_make", - "label": "Make" - }, - { - "type": "text", - "name": "monitoring_mist_size", - "label": "Size" - }, - { - "type": "number", - "name": "monitoring_num_mists", - "label": "Number of nets" - }, - { - "type": "text", - "name": "monitoring_mist_placement", - "label": "Net Placement" - }, - { - "type": "text", - "name": "monitoring_mist_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "monitoring_mist_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "monitoring_mist", - "label": "Mist" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "monitoring_harp_make", - "label": "Make" - }, - { - "type": "text", - "name": "monitoring_harp_size", - "label": "Size" - }, - { - "type": "number", - "name": "monitoring_num_harps", - "label": "Number of nets" - }, - { - "type": "text", - "name": "monitoring_harp_placement", - "label": "Net Placement" - }, - { - "type": "text", - "name": "monitoring_harp_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "monitoring_harp_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "monitoring_harp", - "label": "Harp" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "monitoring_cannon_make", - "label": "Make" - }, - { - "type": "text", - "name": "monitoring_cannon_size", - "label": "Size" - }, - { - "type": "number", - "name": "monitoring_num_cannons", - "label": "Number of nets" - }, - { - "type": "text", - "name": "monitoring_cannon_placement", - "label": "Net Placement" - }, - { - "type": "text", - "name": "monitoring_cannon_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "monitoring_cannon_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "monitoring_cannon", - "label": "Cannon" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "monitoring_net_type_other", - "label": "Enter details" - }, - { - "type": "text", - "name": "monitoring_net_other_make", - "label": "Make" - }, - { - "type": "text", - "name": "monitoring_net_other_size", - "label": "Size" - }, - { - "type": "number", - "name": "monitoring_net_other_num_nets", - "label": "Number of nets" - }, - { - "type": "text", - "name": "monitoring_net_other_placement", - "label": "Net Placement" - }, - { - "type": "text", - "name": "monitoring_net_other_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "monitoring_net_other_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "monitoring_net_other", - "label": "Other" - } - ], - "other": [ - { - "type": "text_area", - "name": "monitoring_other_capture_methodology", - "label": "Provide details of your fauna capture methodology if it doesn\u2019t fit within previous questions for trap, net or hand capture techniques." - } - ], - "trap": [ - { - "type": "number", - "name": "monitoring_num_trap_sites", - "label": "What is the number of trap sites?" - }, - { - "type": "number", - "name": "monitoring_num_traps_open_days", - "label": "How many days/nights will traps be open?" - }, - { - "type": "number", - "name": "monitoring_num_trap_sessions", - "label": "How many trapping sessions?" - }, - { - "type": "number", - "name": "monitoring_num_traps_per_session", - "label": "Total number of traps per session?" - }, - { - "type": "number", - "name": "monitoring_max_num_traps_per_session_per_site", - "label": "Maximum total number of traps per site per session?" - }, - { - "type": "text_area", - "name": "monitoring_different_num_traps_per_session_or_site_explanation", - "label": "If the number of traps differs between sessions or sites, enter the highest number in the questions above, and explain differences below." - }, - { - "type": "label", - "name": "monitoring_traps", - "label": "Traps" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "monitoring_cage_make", - "label": "Make" - }, - { - "type": "text", - "name": "monitoring_cage_size", - "label": "Size" - }, - { - "type": "number", - "name": "monitoring_num_cages", - "label": "Number of traps" - }, - { - "type": "text", - "name": "monitoring_cage_placement", - "label": "Cage Placement" - }, - { - "type": "text", - "name": "monitoring_cage_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "monitoring_cage_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "monitoring_cage", - "label": "Cage" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "monitoring_box_make", - "label": "Make" - }, - { - "type": "text", - "name": "monitoring_box_size", - "label": "Size" - }, - { - "type": "number", - "name": "monitoring_num_boxs", - "label": "Number of traps" - }, - { - "type": "text", - "name": "monitoring_box_placement", - "label": "Box Placement" - }, - { - "type": "text", - "name": "monitoring_box_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "monitoring_box_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "monitoring_box", - "label": "Box" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "monitoring_dry_pit_make", - "label": "Make" - }, - { - "type": "text", - "name": "monitoring_dry_pit_size", - "label": "Size" - }, - { - "type": "number", - "name": "monitoring_num_dry_pits", - "label": "Number of traps" - }, - { - "type": "text", - "name": "monitoring_dry_pit_placement", - "label": "Dry Pit Placement" - }, - { - "type": "text", - "name": "monitoring_dry_pit_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "monitoring_dry_pit_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "monitoring_dry_pit", - "label": "Dry Pit" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "monitoring_wet_pit_make", - "label": "Make" - }, - { - "type": "text", - "name": "monitoring_wet_pit_size", - "label": "Size" - }, - { - "type": "number", - "name": "monitoring_num_wet_pits", - "label": "Number of traps" - }, - { - "type": "text", - "name": "monitoring_wet_pit_placement", - "label": "Wet Pit Placement" - }, - { - "type": "text", - "name": "monitoring_wet_pit_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "monitoring_wet_pit_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "monitoring_wet_pit", - "label": "Wet Pit" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "monitoring_funnel_make", - "label": "Make" - }, - { - "type": "text", - "name": "monitoring_funnel_size", - "label": "Size" - }, - { - "type": "number", - "name": "monitoring_num_funnels", - "label": "Number of traps" - }, - { - "type": "text", - "name": "monitoring_funnel_placement", - "label": "Funnel Placement" - }, - { - "type": "text", - "name": "monitoring_funnel_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "monitoring_funnel_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "monitoring_funnel", - "label": "Funnel" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "monitoring_litter_make", - "label": "Make" - }, - { - "type": "text", - "name": "monitoring_litter_size", - "label": "Size" - }, - { - "type": "number", - "name": "monitoring_num_litters", - "label": "Number of traps" - }, - { - "type": "text", - "name": "monitoring_litter_placement", - "label": "Litter Placement" - }, - { - "type": "text", - "name": "monitoring_litter_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "monitoring_litter_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "monitoring_litter", - "label": "Litter" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "monitoring_trap_type_other", - "label": "Enter details" - }, - { - "type": "text", - "name": "monitoring_trap_other_make", - "label": "Make" - }, - { - "type": "text", - "name": "monitoring_trap_other_size", - "label": "Size" - }, - { - "type": "number", - "name": "monitoring_trap_other_num_traps", - "label": "Number of traps" - }, - { - "type": "text", - "name": "monitoring_trap_other_placement", - "label": "Trap Placement" - }, - { - "type": "text", - "name": "monitoring_trap_other_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "monitoring_trap_other_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "monitoring_trap_other", - "label": "Other" - } - ] - }, - "options": [ - { - "value": "trap", - "label": "Trap" - }, - { - "value": "net", - "label": "Net" - }, - { - "value": "other", - "label": "Other" - } - ], - "type": "radiobuttons", - "name": "monitoring_capture_method", - "label": "Capture Method" - }, - { - "type": "label", - "name": "monitoring_fate", - "label": "What will be the fate(s) of the fauna captured?" - }, - { - "conditions": { - "on": [ - { - "options": [ - { - "value": "immediately", - "label": "Immediately after species idenfication" - }, - { - "value": "after_transmitter_attachment", - "label": "After attachment of transmitter" - }, - { - "value": "after_morphometrics", - "label": "After morphometrics and physical condition taken" - }, - { - "value": "after_samples", - "label": "After samples taken" - }, - { - "value": "after_marking", - "label": "After marking" - }, - { - "value": "after_temp_holding", - "label": "After temporary holding (< 24 hours)" - } - ], - "type": "select", - "name": "monitoring_release_schedule", - "label": "Release Schedule" - }, - { - "type": "label", - "name": "monitoring_pre_release_occurences", - "label": "Which of the following will occur before release?" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "monitoring_prerelease_transmitter_type", - "label": "Transmitter type, make and model, and construction material" - }, - { - "type": "text_area", - "name": "monitoring_prerelease_method_attachment", - "label": "Method of attachment to animal" - }, - { - "type": "text", - "name": "monitoring_prerelease_transmitter_max_weight", - "label": "Maximum weight of transmitter and attachment materials" - }, - { - "type": "text", - "name": "monitoring_prerelease_mim_body_weight", - "label": "Minimum body weight of animal to which transmitter will be attached" - }, - { - "type": "text", - "name": "monitoring_prerelease_transmitter_attachment_length", - "label": "How long will the transmitter remain attached to the animal?" - }, - { - "conditions": { - "yes": [ - { - "type": "declaration", - "name": "monitoring_prerelease_acknowledge", - "label": "I acknowledge that every attempt will be made to recapture the animal to remove the transmitter, and will notify Wildlife Licensing if this cannot be done." - } - ], - "no": [ - { - "type": "text_area", - "name": "monitoring_prerelease_detach_details", - "label": "Provide details of how the transmitter will detach from the animal" - } - ] - }, - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "monitoring_prerelease_recapture_remove", - "label": "Does the animal need to be recaptured to remove the transmitter?" - } - ] - }, - "type": "checkbox", - "name": "monitoring_release_transmitter", - "label": "Attachment of transmitter" - }, - { - "conditions": { - "on": [ - { - "type": "label", - "name": "monitoring_mophometrics_recorded", - "label": "What morphometrics and condition details will be recorded?" - }, - { - "type": "checkbox", - "name": "monitoring_mophometric_length", - "label": "Length" - }, - { - "type": "checkbox", - "name": "monitoring_mophometric_sex", - "label": "Sex" - }, - { - "type": "checkbox", - "name": "monitoring_mophometric_age", - "label": "Age" - }, - { - "type": "checkbox", - "name": "monitoring_mophometric_body_condition", - "label": "Body condition" - }, - { - "type": "checkbox", - "name": "monitoring_mophometric_reproductive_condition", - "label": "Reproductive condition" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "monitoring_mophometric_other_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "monitoring_mophometric_other", - "label": "Other" - }, - { - "type": "text_area", - "name": "monitoring_mophometric_other_details", - "label": "Provide any other details relating to measurements and condition" - } - ] - }, - "type": "checkbox", - "name": "monitoring_mophometrics", - "label": "Mophometrics and physical condition analysis" - }, - { - "conditions": { - "on": [ - { - "type": "label", - "name": "monitoring_samples", - "label": "What samples will be taken?" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "monitoring_tissue_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "monitoring_tissue", - "label": "Tissue" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "monitoring_scale_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "monitoring_scale", - "label": "Scale" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "monitoring_hair_feather_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "monitoring_hair_feather", - "label": "Hair / feather" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "monitoring_blood_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "monitoring_blood", - "label": "Blood" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "monitoring_swabs_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "monitoring_swabs", - "label": "Swabs" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "monitoring_samples_other_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "monitoring_samples_other", - "label": "Other" - } - ] - }, - "type": "checkbox", - "name": "monitoring_sampling", - "label": "Sampling" - }, - { - "conditions": { - "on": [ - { - "conditions": { - "permanent": [ - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "monitoring_tags_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "monitoring_tags", - "label": "Tags" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "monitoring_microchips_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "monitoring_microchips", - "label": "Microchips / implants" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "monitoring_bands_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "monitoring_bands", - "label": "Bands" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "monitoring_ear_punching_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "monitoring_ear_punching", - "label": "Ear punching" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "monitoring_marking_other_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "monitoring_marking_other", - "label": "Other" - } - ] - }, - "options": [ - { - "value": "temporary", - "label": "Temporary" - }, - { - "value": "permanent", - "label": "Permanent" - } - ], - "type": "select", - "name": "monitoring_marking", - "label": "What marking will be done and why?" - } - ] - }, - "type": "checkbox", - "name": "monitoring_marking", - "label": "Marking" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "monitoring_why_temporarily_held", - "label": "Why will/may the fauna be temporarily held?" - }, - { - "type": "text_area", - "name": "monitoring_how_temporarily_held", - "label": "How will the fauna be held?" - }, - { - "type": "text_area", - "name": "monitoring_where_temporarily_held", - "label": "Where will the fauna be held?" - }, - { - "type": "text_area", - "name": "monitoring_transported_details", - "label": "If fauna will be transported, provide details?" - }, - { - "conditions": { - "other": [ - { - "type": "text_area", - "name": "monitoring_fauna_release_other_details", - "label": "Please provide details" - } - ] - }, - "options": [ - { - "value": "at_capture_site", - "label": "At capture site" - }, - { - "value": "near_capture_site", - "label": "Near capture site into suitable habitat" - }, - { - "value": "other", - "label": "Other" - } - ], - "type": "select", - "name": "monitoring_where_fauna_released", - "label": "Where will the fauna be released?" - } - ] - }, - "type": "checkbox", - "name": "monitoring_temporary_holding", - "label": "Temporary Holding" - } - ] - }, - "type": "checkbox", - "name": "monitoring_release", - "label": "Release" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "monitoring_why_fauna_retained", - "label": "Why does the fauna need to be retained?" - }, - { - "type": "text_area", - "name": "monitoring_what_fauna_retained", - "label": "What fauna could be retained?" - }, - { - "type": "number", - "name": "monitoring_num_fauna_retained", - "label": "If fauna is to be retained, how many animals?" - }, - { - "conditions": { - "yes": [ - { - "type": "text_area", - "name": "monitoring_euthanise_method", - "label": "Method" - } - ] - }, - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "monitoring_fauna_euthanised", - "label": "Will fauna be euthanised?" - }, - { - "type": "text", - "name": "monitoring_where_specimen_stored", - "label": "Where will the specimen(s) be held/lodged/stored?" - }, - { - "type": "text_area", - "name": "monitoring_mesuem_storage_details", - "label": "If specimen is to be deposited at the WA Museum, will the Museum be contacted prior to the fauna being retained or did the Museum request the specimen?" - } - ] - }, - "type": "checkbox", - "name": "monitoring_retain", - "label": "Retain" - }, - { - "type": "text_area", - "name": "monitoring_unforseen_injury_dealings", - "label": "Describe how unforeseen injuries or other related issues will be dealt with." - }, - { - "type": "text_area", - "name": "monitoring_hygiene_disease_considerations", - "label": "Provide details of field hygiene and wildlife disease considerations." - }, - { - "type": "text_area", - "name": "monitoring_fauna_capture_other_details", - "label": "Provide other details relating to fauna capture." - } - ], - "other": [ - { - "type": "label", - "name": "monitoring_non_capture_method", - "label": "Please select any non-capture survey method you will be using" - }, - { - "conditions": { - "on": [ - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "monitoring_transmitter_type", - "label": "Transmitter type, make and model, and construction material" - }, - { - "type": "text", - "name": "monitoring_transmitter_max_weight", - "label": "Maximum weight of transmitter and attachment materials" - }, - { - "type": "text", - "name": "monitoring_transmitter_attachment_method", - "label": "Method of attachment to animal" - }, - { - "type": "text", - "name": "monitoring_transmitter_min_distance", - "label": "What will be the minimum distance from the animal??" - }, - { - "type": "number", - "name": "monitoring_transmitter_num_attachment_attempts", - "label": "How many attempts to attach will be made per individual animal?" - }, - { - "type": "text", - "name": "monitoring_transmitter_attachment_length", - "label": "How long will the transmitter remain attached to the animal?" - } - ] - }, - "type": "checkbox", - "name": "monitoring_transmitter", - "label": "Transmitter" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "monitoring_what_samples", - "label": "What samples will be collected?" - }, - { - "type": "text_area", - "name": "monitoring_sample_how_collected", - "label": "How will samples be collected?" - }, - { - "type": "text", - "name": "monitoring_samples_min_distance", - "label": "What will be the minimum distance from the animal?" - }, - { - "type": "number", - "name": "monitoring_samples_num_attachment_attempts", - "label": "How many attempts to attach will be made per individual animal?" - } - ] - }, - "type": "checkbox", - "name": "monitoring_samples", - "label": "Samples" - } - ] - }, - "type": "checkbox", - "name": "monitoring_transmitters_samples", - "label": "Attachment of transmitters and collection of samples from a distance" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "monitoring_visual_observation_details", - "label": "Please provide Details" - } - ] - }, - "type": "checkbox", - "name": "monitoring_visual_observation", - "label": "Visual observation" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "monitoring_aural_details", - "label": "Please provide Details" - }, - { - "conditions": { - "yes": [ - { - "type": "text_area", - "name": "monitoring_call_playback_details", - "label": "Please provide Details" - } - ] - }, - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "monitoring_call_playback", - "label": "Will call play-back be used?" - } - ] - }, - "type": "checkbox", - "name": "monitoring_aural", - "label": "Aural" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "monitoring_bird_census_details", - "label": "Please provide Details" - } - ] - }, - "type": "checkbox", - "name": "monitoring_bird_census", - "label": "Bird Census" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "monitoring_spotlighting_details", - "label": "Please provide Details" - } - ] - }, - "type": "checkbox", - "name": "monitoring_spotlighting", - "label": "Spotlighting / head torching" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "monitoring_hair_tubes_details", - "label": "Please provide Details" - } - ] - }, - "type": "checkbox", - "name": "monitoring_hair_tubes", - "label": "Hair tubes / sticky wicket" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "monitoring_secondary_signs_details", - "label": "Please provide Details" - } - ] - }, - "type": "checkbox", - "name": "monitoring_secondary_signs", - "label": "Secondary signs / evidence" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "monitoring_habitat_assessment_details", - "label": "Please provide Details" - } - ] - }, - "type": "checkbox", - "name": "monitoring_habitat_assessment", - "label": "Habitat Assessment" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "monitoring_non_capture_other_details", - "label": "Please provide Details" - } - ] - }, - "type": "checkbox", - "name": "monitoring_non_capture_other", - "label": "Other" - } - ], - "remote_sensing": [ - { - "type": "label", - "name": "monitoring_remote_sensing_apparatus", - "label": "What remote sensing apparatus will you be using?" - }, - { - "conditions": { - "on": [ - { - "conditions": { - "yes": [ - { - "type": "text", - "name": "monitoring_what_bait", - "label": "What bait will be used?" - }, - { - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "monitoring_bait_consumable", - "label": "Will the bait be consumable?" - }, - { - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "monitoring_bait_replenished", - "label": "Will the bait be replenished?" - } - ] - }, - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "monitoring_camera_baited", - "label": "Will cameras be baited with an attractant/lure?" - }, - { - "children": [ - { - "type": "text", - "name": "monitoring_camera_make", - "label": "Make" - }, - { - "type": "number", - "name": "monitoring_num_cameras", - "label": "Number of devices" - }, - { - "type": "text_area", - "name": "monitoring_camera_placement", - "label": "Camera Placement" - }, - { - "type": "text", - "name": "monitoring_camera_situ", - "label": "How long in situ" - }, - { - "type": "text", - "name": "monitoring_camera_other_details", - "label": "Other details" - } - ], - "isRepeatable": true, - "type": "group", - "name": "monitoring_camera_information", - "label": "Camera Information" - } - ] - }, - "type": "checkbox", - "name": "monitoring_camera", - "label": "Camera" - }, - { - "conditions": { - "on": [ - { - "children": [ - { - "type": "text", - "name": "monitoring_ubd_make", - "label": "Make" - }, - { - "type": "number", - "name": "monitoring_num_ubds", - "label": "Number of devices" - }, - { - "type": "text", - "name": "monitoring_ubd_placement", - "label": "Ultrasonic bat detector Placement" - }, - { - "type": "text", - "name": "monitoring_ubd_situ", - "label": "How long in situ" - }, - { - "type": "text", - "name": "monitoring_ubd_other_details", - "label": "Other details" - } - ], - "isRepeatable": true, - "type": "group", - "name": "monitoring_ultrasonic_bat_detector_information", - "label": "Ultrasonic Bat Detector Information" - } - ] - }, - "type": "checkbox", - "name": "monitoring_ultrasonic_bat_detector", - "label": "Ultrasonic bat detector" - }, - { - "conditions": { - "on": [ - { - "children": [ - { - "type": "text", - "name": "monitoring_ac_make", - "label": "Make" - }, - { - "type": "number", - "name": "monitoring_num_acs", - "label": "Number of devices" - }, - { - "type": "text", - "name": "monitoring_ac_placement", - "label": "Acoustic recorder Placement" - }, - { - "type": "text", - "name": "monitoring_ac_situ", - "label": "How long in situ" - }, - { - "type": "text", - "name": "monitoring_ac_other_details", - "label": "Other details" - } - ], - "isRepeatable": true, - "type": "group", - "name": "monitoring_acoustic_call_recorder_information", - "label": "Acoustic recorder Information" - } - ] - }, - "type": "checkbox", - "name": "monitoring_acoustic_call_recorder", - "label": "Acoustic recorder" - }, - { - "conditions": { - "on": [ - { - "children": [ - { - "type": "text", - "name": "monitoring_aerial_make", - "label": "Make" - }, - { - "type": "number", - "name": "monitoring_num_aerials", - "label": "Number of devices" - }, - { - "type": "text", - "name": "monitoring_aerial_placement", - "label": "Aerial Placement" - }, - { - "type": "text", - "name": "monitoring_aerial_situ", - "label": "How long in situ" - }, - { - "type": "text", - "name": "monitoring_aerial_other_details", - "label": "Other details" - } - ], - "type": "group", - "name": "monitoring_aerial_information", - "label": "Aerial Information" - } - ] - }, - "type": "checkbox", - "name": "monitoring_aerial", - "label": "Aerial" - }, - { - "type": "text_area", - "name": "monitoring_remote_sensing_other_details", - "label": "Provide any other details relating to remote sensing." - } - ] - }, - "options": [ - { - "value": "capture", - "label": "Capture" - }, - { - "value": "remote_sensing", - "label": "Remote Sensing" - }, - { - "value": "other", - "label": "Other non-capture" - } - ], - "type": "radiobuttons", - "name": "monitoring_method", - "label": "What monitoring method will you be using?" - } - ] - } - ], - "survey": [ - { - "type": "number", - "name": "survey_num_survey_locations", - "label": "How many locations will be surveyed?" - }, - { - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - }, - { - "value": "unsure", - "label": "Unsure" - } - ], - "type": "radiobuttons", - "name": "survey_locations_calm_land", - "label": "Are any locations on CALM Act land?" - }, - { - "name": "survey_survey_details", - "isRepeatable": true, - "help_text": "If multiple survey locations; provide details separately for each location and add an additional location after the methods section for the first location.", - "label": "Survey Details", - "type": "group", - "children": [ - { - "type": "text_area", - "name": "survey_address", - "label": "Location / Address" - }, - { - "type": "text", - "name": "survey_coordinates", - "label": "Coordinate / GPS" - }, - { - "children": [ - { - "type": "date", - "name": "survey_field_session_start_date", - "label": "Start Date" - }, - { - "type": "date", - "name": "survey_field_session_end_date", - "label": "End Date" - } - ], - "isRepeatable": true, - "type": "group", - "name": "survey_field_session", - "label": "Field session" - }, - { - "type": "text", - "name": "survey_field_dates_unknown", - "label": "If field dates are unknown, use anticipated field dates in the start and end date above and explain below." - }, - { - "name": "survey_interval_regularity", - "type": "select", - "label": "Interval Regularity", - "conditions": { - "other": [ - { - "type": "text", - "name": "survey_regular_intervals_other", - "label": "Please Specify" - } - ] - }, - "options": [ - { - "value": "not_regular_intervals", - "label": "Not regular intervals" - }, - { - "value": "weekly", - "label": "Weekly" - }, - { - "value": "fortnightly", - "label": "Fortnightly" - }, - { - "value": "monthly", - "label": "Monthly" - }, - { - "value": "quarterly", - "label": "Quarterly/Seasonally" - }, - { - "value": "biannually", - "label": "Biannually/Six-monthly" - }, - { - "value": "annually", - "label": "Annually" - }, - { - "value": "biennually", - "label": "Biennially/Every two years" - }, - { - "value": "other", - "label": "Other" - } - ], - "defaultBlank": false - }, - { - "conditions": { - "yes": [ - { - "children": [ - { - "type": "text", - "name": "survey_tf_group_name", - "label": "Group name" - }, - { - "speciesType": "fauna", - "type": "species", - "name": "survey_tf_scientific_name", - "label": "Scientific or common name" - } - ], - "isRepeatable": true, - "type": "group", - "name": "survey_threatened_fauna", - "label": "Threatened Fauna" - } - ] - }, - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - }, - { - "value": "unknown", - "label": "Unknown" - } - ], - "type": "radiobuttons", - "name": "survey_threatened_priority_fauna", - "label": "Will your activity possibly interact with any threatened or priority fauna (including non-target species)?" - }, - { - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "survey_standard_operating_procedures", - "label": "Will your activities be in accordance with Parks and Wildlife standard operating procedures?" - }, - { - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "survey_epa_statements", - "label": "Will your activities be in accordance with EPA Guidance Statements, Position Statements or Technical Reports?" - }, - { - "conditions": { - "yes": [ - { - "type": "text", - "name": "survey_sops_details", - "label": "Provide details" - }, - { - "type": "file", - "name": "survey_sops_documents", - "label": "Attach a copy of the relevent document(s)" - } - ] - }, - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "survey_sops", - "label": "Will your activities be in accordance with any other SOPs, protocols, guidelines or manuals?" - }, - { - "type": "label", - "name": "survey_survey_type", - "label": "What survey type will you be conducting?" - }, - { - "conditions": { - "on": [ - { - "conditions": { - "capture": [ - { - "conditions": { - "net": [ - { - "type": "number", - "name": "survey_level_1_num_net_sites", - "label": "What is the number of sites where nets will be used?" - }, - { - "type": "number", - "name": "survey_level_1_num_net_days", - "label": "How many days/nights will nets be used?" - }, - { - "type": "number", - "name": "survey_level_1_num_net_sessions", - "label": "How many sessions will nets be used?" - }, - { - "type": "number", - "name": "survey_level_1_num_nets_per_session", - "label": "Total number of nets per session?" - }, - { - "type": "number", - "name": "survey_level_1_max_num_nets_per_session_per_site", - "label": "Maximum total number of nets per site per session?" - }, - { - "type": "text_area", - "name": "survey_level_1_different_num_nets_per_session_or_site_explanation", - "label": "If the number of nets differs between sessions or sites then explain" - }, - { - "type": "label", - "name": "survey_level_1_nets", - "label": "Nets" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_level_1_sweep_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_level_1_sweep_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_level_1_num_sweeps", - "label": "Number of nets" - }, - { - "type": "text", - "name": "survey_level_1_sweep_placement", - "label": "Net Placement" - }, - { - "type": "text", - "name": "survey_level_1_sweep_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_level_1_sweep_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_sweep", - "label": "Sweep" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_level_1_mist_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_level_1_mist_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_level_1_num_mists", - "label": "Number of nets" - }, - { - "type": "text", - "name": "survey_level_1_mist_placement", - "label": "Net Placement" - }, - { - "type": "text", - "name": "survey_level_1_mist_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_level_1_mist_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_mist", - "label": "Mist" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_level_1_harp_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_level_1_harp_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_level_1_num_harps", - "label": "Number of nets" - }, - { - "type": "text", - "name": "survey_level_1_harp_placement", - "label": "Net Placement" - }, - { - "type": "text", - "name": "survey_level_1_harp_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_level_1_harp_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_harp", - "label": "Harp" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_level_1_net_type_other", - "label": "Enter details" - }, - { - "type": "text", - "name": "survey_level_1_net_other_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_level_1_net_other_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_level_1_net_other_num_nets", - "label": "Number of nets" - }, - { - "type": "text", - "name": "survey_level_1_net_other_placement", - "label": "Net Placement" - }, - { - "type": "text", - "name": "survey_level_1_net_other_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_level_1_net_other_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_net_other", - "label": "Other" - } - ], - "other": [ - { - "type": "text_area", - "name": "survey_level_1_other_capture_methodology", - "label": "Provide details of your fauna capture methodology if it doesn\u2019t fit within previous questions for trap, net or hand capture techniques." - } - ], - "trap": [ - { - "type": "number", - "name": "survey_level_1_num_trap_sites", - "label": "What is the number of trap sites?" - }, - { - "type": "number", - "name": "survey_level_1_num_traps_open_days", - "label": "How many days/nights will traps be open?" - }, - { - "type": "number", - "name": "survey_level_1_num_trap_sessions", - "label": "How many trapping sessions?" - }, - { - "type": "number", - "name": "survey_level_1_num_traps_per_session", - "label": "Total number of traps per session?" - }, - { - "type": "number", - "name": "survey_level_1_max_num_traps_per_session_per_site", - "label": "Maximum total number of traps per site per session?" - }, - { - "type": "text_area", - "name": "survey_level_1_different_num_traps_per_session_or_site_explanation", - "label": "If the number of traps differs between sessions or sites, enter the highest number in the questions above, and explain differences below." - }, - { - "type": "label", - "name": "survey_level_1_traps", - "label": "Traps" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_level_1_cage_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_level_1_cage_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_level_1_num_cages", - "label": "Number of traps" - }, - { - "type": "text", - "name": "survey_level_1_cage_placement", - "label": "Cage Placement" - }, - { - "type": "text", - "name": "survey_level_1_cage_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_level_1_cage_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_cage", - "label": "Cage" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_level_1_box_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_level_1_box_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_level_1_num_boxs", - "label": "Number of traps" - }, - { - "type": "text", - "name": "survey_level_1_box_placement", - "label": "Box Placement" - }, - { - "type": "text", - "name": "survey_level_1_box_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_level_1_box_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_box", - "label": "Box" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_level_1_dry_pit_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_level_1_dry_pit_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_level_1_num_dry_pits", - "label": "Number of traps" - }, - { - "type": "text", - "name": "survey_level_1_dry_pit_placement", - "label": "Dry Pit Placement" - }, - { - "type": "text", - "name": "survey_level_1_dry_pit_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_level_1_dry_pit_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_dry_pit", - "label": "Dry Pit" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_level_1_funnel_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_level_1_funnel_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_level_1_num_funnels", - "label": "Number of traps" - }, - { - "type": "text", - "name": "survey_level_1_funnel_placement", - "label": "Funnel Placement" - }, - { - "type": "text", - "name": "survey_level_1_funnel_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_level_1_funnel_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_funnel", - "label": "Funnel" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_level_1_trap_type_other", - "label": "Enter details" - }, - { - "type": "text", - "name": "survey_level_1_trap_other_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_level_1_trap_other_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_level_1_trap_other_num_traps", - "label": "Number of traps" - }, - { - "type": "text", - "name": "survey_level_1_trap_other_placement", - "label": "Trap Placement" - }, - { - "type": "text", - "name": "survey_level_1_trap_other_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_level_1_trap_other_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_trap_other", - "label": "Other" - } - ], - "hand": [ - { - "type": "label", - "name": "survey_level_1_hand_capture_techniques", - "label": "What hand capture techniques will you be using?" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_1_hook_and_bag_details", - "label": "Please Provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_hook_and_bag", - "label": "Hook and Bag" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_1_Noose_details", - "label": "Please Provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_noose", - "label": "Noose" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_1_foraging_details", - "label": "Please Provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_foraging", - "label": "Foraging" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_1_raking_details", - "label": "Please Provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_raking", - "label": "Raking" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_1_sieving_details", - "label": "Please Provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_sieving", - "label": "Sieving" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_1_excavation_details", - "label": "Please Provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_excavation", - "label": "Excavation" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_1_excavation_details", - "label": "Please Provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_other_hand_capture_techniques", - "label": "Other" - } - ] - }, - "options": [ - { - "value": "trap", - "label": "Trap" - }, - { - "value": "net", - "label": "Net" - }, - { - "value": "hand", - "label": "Hand" - }, - { - "value": "other", - "label": "Other" - } - ], - "type": "radiobuttons", - "name": "survey_level_1_capture_method", - "label": "Capture Method" - }, - { - "type": "label", - "name": "survey_level_1_fate", - "label": "What will be the fate(s) of the fauna captured?" - }, - { - "conditions": { - "on": [ - { - "options": [ - { - "value": "immediately", - "label": "Immediately after species idenfication" - }, - { - "value": "after_morphometrics", - "label": "After morphometrics and physical condition taken" - }, - { - "value": "after_samples", - "label": "After samples taken" - }, - { - "value": "after_marking", - "label": "After marking" - }, - { - "value": "after_temp_holding", - "label": "After temporary holding (< 24 hours)" - } - ], - "type": "select", - "name": "survey_level_1_release_schedule", - "label": "Release Schedule" - }, - { - "type": "label", - "name": "survey_level_1_pre_release_occurences", - "label": "Which of the following will occur before release?" - }, - { - "conditions": { - "on": [ - { - "type": "label", - "name": "survey_level_1_mophometrics_recorded", - "label": "What morphometrics and condition details will be recorded?" - }, - { - "type": "checkbox", - "name": "survey_level_1_mophometric_length", - "label": "Length" - }, - { - "type": "checkbox", - "name": "survey_level_1_mophometric_sex", - "label": "Sex" - }, - { - "type": "checkbox", - "name": "survey_level_1_mophometric_age", - "label": "Age" - }, - { - "type": "checkbox", - "name": "survey_level_1_mophometric_body_condition", - "label": "Body condition" - }, - { - "type": "checkbox", - "name": "survey_level_1_mophometric_reproductive_condition", - "label": "Reproductive condition" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_1_mophometric_other_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_mophometric_other", - "label": "Other" - }, - { - "type": "text_area", - "name": "survey_level_1_mophometric_other_details", - "label": "Provide any other details relating to measurements and condition" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_mophometrics", - "label": "Mophometrics and physical condition analysis" - }, - { - "conditions": { - "on": [ - { - "type": "label", - "name": "survey_level_1_samples", - "label": "What samples will be taken?" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_1_tissue_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_tissue", - "label": "Tissue" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_1_scale_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_scale", - "label": "Scale" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_1_hair_feather_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_hair_feather", - "label": "Hair / feather" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_1_blood_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_blood", - "label": "Blood" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_1_swabs_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_swabs", - "label": "Swabs" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_1_samples_other_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_samples_other", - "label": "Other" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_sampling", - "label": "Sampling" - }, - { - "conditions": { - "on": [ - { - "conditions": { - "permanent": [ - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_1_tags_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_tags", - "label": "Tags" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_1_microchips_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_microchips", - "label": "Microchips / implants" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_1_bands_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_bands", - "label": "Bands" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_1_ear_punching_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_ear_punching", - "label": "Ear punching" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_1_marking_other_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_marking_other", - "label": "Other" - } - ] - }, - "options": [ - { - "value": "temporary", - "label": "Temporary" - }, - { - "value": "permanent", - "label": "Permanent" - } - ], - "type": "select", - "name": "survey_level_1_marking", - "label": "What marking will be done and why?" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_marking", - "label": "Marking" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_1_why_temporarily_held", - "label": "Why will/may the fauna be temporarily held?" - }, - { - "type": "text_area", - "name": "survey_level_1_how_temporarily_held", - "label": "How will the fauna be held?" - }, - { - "type": "text_area", - "name": "survey_level_1_where_temporarily_held", - "label": "Where will the fauna be held?" - }, - { - "type": "text_area", - "name": "survey_level_1_transported_details", - "label": "If fauna will be transported, provide details?" - }, - { - "conditions": { - "other": [ - { - "type": "text_area", - "name": "survey_level_1_fauna_release_other_details", - "label": "Please provide details" - } - ] - }, - "options": [ - { - "value": "at_capture_site", - "label": "At capture site" - }, - { - "value": "near_capture_site", - "label": "Near capture site into suitable habitat" - }, - { - "value": "other", - "label": "Other" - } - ], - "type": "select", - "name": "survey_level_1_where_fauna_released", - "label": "Where will the fauna be released?" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_temporary_holding", - "label": "Temporary Holding" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_release", - "label": "Release" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_1_why_fauna_retained", - "label": "Why does the fauna need to be retained?" - }, - { - "type": "text_area", - "name": "survey_level_1_what_fauna_retained", - "label": "What fauna could be retained?" - }, - { - "type": "number", - "name": "survey_level_1_num_fauna_retained", - "label": "If fauna is to be retained, how many animals?" - }, - { - "conditions": { - "yes": [ - { - "type": "text_area", - "name": "survey_level_1_euthanise_method", - "label": "Method" - } - ] - }, - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "survey_level_1_fauna_euthanised", - "label": "Will fauna be euthanised?" - }, - { - "type": "text", - "name": "survey_level_1_where_specimen_stored", - "label": "Where will the specimen(s) be held/lodged/stored?" - }, - { - "type": "text_area", - "name": "survey_level_1_mesuem_storage_details", - "label": "If specimen is to be deposited at the WA Museum, will the Museum be contacted prior to the fauna being retained or did the Museum request the specimen?" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_retain", - "label": "Retain" - }, - { - "type": "text_area", - "name": "survey_level_1_unforseen_injury_dealings", - "label": "Describe how unforeseen injuries or other related issues will be dealt with." - }, - { - "type": "text_area", - "name": "survey_level_1_hygiene_disease_considerations", - "label": "Provide details of field hygiene and wildlife disease considerations." - }, - { - "type": "text_area", - "name": "survey_level_1_fauna_capture_other_details", - "label": "Provide other details relating to fauna capture." - } - ], - "other": [ - { - "type": "label", - "name": "survey_level_1_non_capture_method", - "label": "Please select any non-capture survey method you will be using" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_1_aural_survey_details", - "label": "Please provide Details" - }, - { - "conditions": { - "yes": [ - { - "type": "text_area", - "name": "survey_level_1_call_playback_details", - "label": "Please provide Details" - } - ] - }, - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "survey_level_1_call_playback", - "label": "Will call play-back be used?" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_aural_survey", - "label": "Aural survey" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_1_bird_census_details", - "label": "Please provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_bird_census", - "label": "Bird Census" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_1_spotlighting_details", - "label": "Please provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_spotlighting", - "label": "Spotlighting / head torching" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_1_hair_tubes_details", - "label": "Please provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_hair_tubes", - "label": "Hair tubes / sticky wicket" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_1_secondary_signs_details", - "label": "Please provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_secondary_signs", - "label": "Secondary signs / evidence" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_1_habitat_assessment_details", - "label": "Please provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_habitat_assessment", - "label": "Habitat Assessment" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_1_non_capture_other_details", - "label": "Please provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_non_capture_other", - "label": "Other" - } - ], - "remote_sensing": [ - { - "type": "label", - "name": "survey_level_1_remote_sensing_apparatus", - "label": "What remote sensing apparatus will you be using?" - }, - { - "conditions": { - "on": [ - { - "conditions": { - "yes": [ - { - "type": "text", - "name": "survey_level_1_what_bait", - "label": "What bait will be used?" - }, - { - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "survey_level_1_bait_consumable", - "label": "Will the bait be consumable?" - }, - { - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "survey_level_1_bait_replenished", - "label": "Will the bait be replenished?" - } - ] - }, - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "survey_level_1_camera_baited", - "label": "Will cameras be baited with an attractant/lure?" - }, - { - "children": [ - { - "type": "text", - "name": "survey_level_1_camera_make", - "label": "Make" - }, - { - "type": "number", - "name": "survey_level_1_num_cameras", - "label": "Number of devices" - }, - { - "type": "text_area", - "name": "survey_level_1_camera_placement", - "label": "Camera Placement" - }, - { - "type": "text", - "name": "survey_level_1_camera_situ", - "label": "How long in situ" - }, - { - "type": "text", - "name": "survey_level_1_camera_other_details", - "label": "Other details" - } - ], - "isRepeatable": true, - "type": "group", - "name": "survey_level_1_camera_information", - "label": "Camera Information" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_camera", - "label": "Camera" - }, - { - "conditions": { - "on": [ - { - "children": [ - { - "type": "text", - "name": "survey_level_1_ubd_make", - "label": "Make" - }, - { - "type": "number", - "name": "survey_level_1_num_ubds", - "label": "Number of devices" - }, - { - "type": "text", - "name": "survey_level_1_ubd_placement", - "label": "Ultrasonic bat detector Placement" - }, - { - "type": "text", - "name": "survey_level_1_ubd_situ", - "label": "How long in situ" - }, - { - "type": "text", - "name": "survey_level_1_ubd_other_details", - "label": "Other details" - } - ], - "isRepeatable": true, - "type": "group", - "name": "survey_level_1_ultrasonic_bat_detector_information", - "label": "Ultrasonic Bat Detector Information" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_ultrasonic_bat_detector", - "label": "Ultrasonic bat detector" - }, - { - "conditions": { - "on": [ - { - "children": [ - { - "type": "text", - "name": "survey_level_1_acr_make", - "label": "Make" - }, - { - "type": "number", - "name": "survey_level_1_num_acrs", - "label": "Number of devices" - }, - { - "type": "text", - "name": "survey_level_1_acr_placement", - "label": "Acoustic call recorder Placement" - }, - { - "type": "text", - "name": "survey_level_1_acr_situ", - "label": "How long in situ" - }, - { - "type": "text", - "name": "survey_level_1_acr_other_details", - "label": "Other details" - } - ], - "isRepeatable": true, - "type": "group", - "name": "survey_level_1_acoustic_call_recorder_information", - "label": "Acoustic call recorder Information" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_acoustic_call_recorder", - "label": "Acoustic call recorder" - }, - { - "conditions": { - "on": [ - { - "children": [ - { - "type": "text", - "name": "survey_level_1_aerial_make", - "label": "Make" - }, - { - "type": "number", - "name": "survey_level_1_num_aerials", - "label": "Number of devices" - }, - { - "type": "text", - "name": "survey_level_1_aerial_placement", - "label": "Aerial Placement" - }, - { - "type": "text", - "name": "survey_level_1_aerial_situ", - "label": "How long in situ" - }, - { - "type": "text", - "name": "survey_level_1_aerial_other_details", - "label": "Other details" - } - ], - "type": "group", - "name": "survey_level_1_aerial_information", - "label": "Aerial Information" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_aerial", - "label": "Aerial" - }, - { - "type": "text_area", - "name": "survey_level_1_remote_sensing_other_details", - "label": "Provide any other details relating to remote sensing." - } - ] - }, - "options": [ - { - "value": "capture", - "label": "Capture" - }, - { - "value": "remote_sensing", - "label": "Remote Sensing" - }, - { - "value": "other", - "label": "Other non-capture" - } - ], - "type": "radiobuttons", - "name": "survey_level_1_survey_method", - "label": "What survey method will you be using?" - } - ] - }, - "type": "checkbox", - "name": "survey_level_1_reconnaissance", - "label": "Level 1 / reconnaissance" - }, - { - "conditions": { - "on": [ - { - "conditions": { - "capture": [ - { - "conditions": { - "net": [ - { - "type": "number", - "name": "survey_level_2_num_net_sites", - "label": "What is the number of sites where nets will be used?" - }, - { - "type": "number", - "name": "survey_level_2_num_net_days", - "label": "How many days/nights will nets be used?" - }, - { - "type": "number", - "name": "survey_level_2_num_net_sessions", - "label": "How many sessions will nets be used?" - }, - { - "type": "number", - "name": "survey_level_2_num_nets_per_session", - "label": "Total number of nets per session?" - }, - { - "type": "number", - "name": "survey_level_2_max_num_nets_per_session_per_site", - "label": "Maximum total number of nets per site per session?" - }, - { - "type": "text_area", - "name": "survey_level_2_different_num_nets_per_session_or_site_explanation", - "label": "If the number of nets differs between sessions or sites then explain" - }, - { - "type": "label", - "name": "survey_level_2_nets", - "label": "Nets" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_level_2_sweep_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_level_2_sweep_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_level_2_num_sweeps", - "label": "Number of nets" - }, - { - "type": "text", - "name": "survey_level_2_sweep_placement", - "label": "Net Placement" - }, - { - "type": "text", - "name": "survey_level_2_sweep_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_level_2_sweep_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_2_sweep", - "label": "Sweep" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_level_2_mist_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_level_2_mist_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_level_2_num_mists", - "label": "Number of nets" - }, - { - "type": "text", - "name": "survey_level_2_mist_placement", - "label": "Net Placement" - }, - { - "type": "text", - "name": "survey_level_2_mist_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_level_2_mist_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_2_mist", - "label": "Mist" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_level_2_harp_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_level_2_harp_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_level_2_num_harps", - "label": "Number of nets" - }, - { - "type": "text", - "name": "survey_level_2_harp_placement", - "label": "Net Placement" - }, - { - "type": "text", - "name": "survey_level_2_harp_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_level_2_harp_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_2_harp", - "label": "Harp" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_level_2_net_type_other", - "label": "Enter details" - }, - { - "type": "text", - "name": "survey_level_2_net_other_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_level_2_net_other_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_level_2_net_other_num_nets", - "label": "Number of nets" - }, - { - "type": "text", - "name": "survey_level_2_net_other_placement", - "label": "Net Placement" - }, - { - "type": "text", - "name": "survey_level_2_net_other_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_level_2_net_other_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_2_net_other", - "label": "Other" - } - ], - "other": [ - { - "type": "text_area", - "name": "survey_level_2_other_capture_methodology", - "label": "Provide details of your fauna capture methodology if it doesn\u2019t fit within previous questions for trap, net or hand capture techniques." - } - ], - "trap": [ - { - "type": "number", - "name": "survey_level_2_num_trap_sites", - "label": "What is the number of trap sites?" - }, - { - "type": "number", - "name": "survey_level_2_num_traps_open_days", - "label": "How many days/nights will traps be open?" - }, - { - "type": "number", - "name": "survey_level_2_num_trap_sessions", - "label": "How many trapping sessions?" - }, - { - "type": "number", - "name": "survey_level_2_num_traps_per_session", - "label": "Total number of traps per session?" - }, - { - "type": "number", - "name": "survey_level_2_max_num_traps_per_session_per_site", - "label": "Maximum total number of traps per site per session?" - }, - { - "type": "text_area", - "name": "survey_level_2_different_num_traps_per_session_or_site_explanation", - "label": "If the number of traps differs between sessions or sites, enter the highest number in the questions above, and explain differences below." - }, - { - "type": "label", - "name": "survey_level_2_traps", - "label": "Traps" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_level_2_cage_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_level_2_cage_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_level_2_num_cages", - "label": "Number of traps" - }, - { - "type": "text", - "name": "survey_level_2_cage_placement", - "label": "Cage Placement" - }, - { - "type": "text", - "name": "survey_level_2_cage_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_level_2_cage_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_2_cage", - "label": "Cage" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_level_2_box_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_level_2_box_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_level_2_num_boxs", - "label": "Number of traps" - }, - { - "type": "text", - "name": "survey_level_2_box_placement", - "label": "Box Placement" - }, - { - "type": "text", - "name": "survey_level_2_box_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_level_2_box_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_2_box", - "label": "Box" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_level_2_dry_pit_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_level_2_dry_pit_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_level_2_num_dry_pits", - "label": "Number of traps" - }, - { - "type": "text", - "name": "survey_level_2_dry_pit_placement", - "label": "Dry Pit Placement" - }, - { - "type": "text", - "name": "survey_level_2_dry_pit_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_level_2_dry_pit_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_2_dry_pit", - "label": "Dry Pit" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_level_2_funnel_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_level_2_funnel_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_level_2_num_funnels", - "label": "Number of traps" - }, - { - "type": "text", - "name": "survey_level_2_funnel_placement", - "label": "Funnel Placement" - }, - { - "type": "text", - "name": "survey_level_2_funnel_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_level_2_funnel_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_2_funnel", - "label": "Funnel" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_level_2_trap_type_other", - "label": "Enter details" - }, - { - "type": "text", - "name": "survey_level_2_trap_other_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_level_2_trap_other_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_level_2_trap_other_num_traps", - "label": "Number of traps" - }, - { - "type": "text", - "name": "survey_level_2_trap_other_placement", - "label": "Trap Placement" - }, - { - "type": "text", - "name": "survey_level_2_trap_other_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_level_2_trap_other_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_2_trap_other", - "label": "Other" - } - ], - "hand": [ - { - "type": "label", - "name": "survey_level_2_hand_capture_techniques", - "label": "What hand capture techniques will you be using?" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_2_hook_and_bag_details", - "label": "Please Provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_2_hook_and_bag", - "label": "Hook and Bag" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_2_Noose_details", - "label": "Please Provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_2_noose", - "label": "Noose" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_2_foraging_details", - "label": "Please Provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_2_foraging", - "label": "Foraging" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_2_raking_details", - "label": "Please Provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_2_raking", - "label": "Raking" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_2_sieving_details", - "label": "Please Provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_2_sieving", - "label": "Sieving" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_2_excavation_details", - "label": "Please Provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_2_excavation", - "label": "Excavation" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_2_excavation_details", - "label": "Please Provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_2_other_hand_capture_techniques", - "label": "Other" - } - ] - }, - "options": [ - { - "value": "trap", - "label": "Trap" - }, - { - "value": "net", - "label": "Net" - }, - { - "value": "hand", - "label": "Hand" - }, - { - "value": "other", - "label": "Other" - } - ], - "type": "radiobuttons", - "name": "survey_level_2_capture_method", - "label": "Capture Method" - }, - { - "type": "label", - "name": "survey_level_2_fate", - "label": "What will be the fate(s) of the fauna captured?" - }, - { - "conditions": { - "on": [ - { - "options": [ - { - "value": "immediately", - "label": "Immediately after species idenfication" - }, - { - "value": "after_morphometrics", - "label": "After morphometrics and physical condition taken" - }, - { - "value": "after_samples", - "label": "After samples taken" - }, - { - "value": "after_marking", - "label": "After marking" - }, - { - "value": "after_temp_holding", - "label": "After temporary holding (< 24 hours)" - } - ], - "type": "select", - "name": "survey_level_2_release_schedule", - "label": "Release Schedule" - }, - { - "type": "label", - "name": "survey_level_2_pre_release_occurences", - "label": "Which of the following will occur before release?" - }, - { - "conditions": { - "on": [ - { - "type": "label", - "name": "survey_level_2_mophometrics_recorded", - "label": "What morphometrics and condition details will be recorded?" - }, - { - "type": "checkbox", - "name": "survey_level_2_mophometric_length", - "label": "Length" - }, - { - "type": "checkbox", - "name": "survey_level_2_mophometric_sex", - "label": "Sex" - }, - { - "type": "checkbox", - "name": "survey_level_2_mophometric_age", - "label": "Age" - }, - { - "type": "checkbox", - "name": "survey_level_2_mophometric_body_condition", - "label": "Body condition" - }, - { - "type": "checkbox", - "name": "survey_level_2_mophometric_reproductive_condition", - "label": "Reproductive condition" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_2_mophometric_other_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_2_mophometric_other", - "label": "Other" - }, - { - "type": "text_area", - "name": "survey_level_2_mophometric_other_details", - "label": "Provide any other details relating to measurements and condition" - } - ] - }, - "type": "checkbox", - "name": "survey_level_2_mophometrics", - "label": "Mophometrics and physical condition analysis" - }, - { - "conditions": { - "on": [ - { - "type": "label", - "name": "survey_level_2_samples", - "label": "What samples will be taken?" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_2_tissue_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_2_tissue", - "label": "Tissue" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_2_scale_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_2_scale", - "label": "Scale" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_2_hair_feather_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_2_hair_feather", - "label": "Hair / feather" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_2_blood_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_2_blood", - "label": "Blood" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_2_swabs_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_2_swabs", - "label": "Swabs" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_2_samples_other_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_2_samples_other", - "label": "Other" - } - ] - }, - "type": "checkbox", - "name": "survey_level_2_sampling", - "label": "Sampling" - }, - { - "conditions": { - "on": [ - { - "conditions": { - "permanent": [ - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_2_tags_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_2_tags", - "label": "Tags" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_2_microchips_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_2_microchips", - "label": "Microchips / implants" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_2_bands_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_2_bands", - "label": "Bands" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_2_ear_punching_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_2_ear_punching", - "label": "Ear punching" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_2_marking_other_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_2_marking_other", - "label": "Other" - } - ] - }, - "options": [ - { - "value": "temporary", - "label": "Temporary" - }, - { - "value": "permanent", - "label": "Permanent" - } - ], - "type": "select", - "name": "survey_level_2_marking", - "label": "What marking will be done and why?" - } - ] - }, - "type": "checkbox", - "name": "survey_level_2_marking", - "label": "Marking" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_2_why_temporarily_held", - "label": "Why will/may the fauna be temporarily held?" - }, - { - "type": "text_area", - "name": "survey_level_2_how_temporarily_held", - "label": "How will the fauna be held?" - }, - { - "type": "text_area", - "name": "survey_level_2_where_temporarily_held", - "label": "Where will the fauna be held?" - }, - { - "type": "text_area", - "name": "survey_level_2_transported_details", - "label": "If fauna will be transported, provide details?" - }, - { - "conditions": { - "other": [ - { - "type": "text_area", - "name": "survey_level_2_fauna_release_other_details", - "label": "Please provide details" - } - ] - }, - "options": [ - { - "value": "at_capture_site", - "label": "At capture site" - }, - { - "value": "near_capture_site", - "label": "Near capture site into suitable habitat" - }, - { - "value": "other", - "label": "Other" - } - ], - "type": "select", - "name": "survey_level_2_where_fauna_released", - "label": "Where will the fauna be released?" - } - ] - }, - "type": "checkbox", - "name": "survey_level_2_temporary_holding", - "label": "Temporary Holding" - } - ] - }, - "type": "checkbox", - "name": "survey_level_2_release", - "label": "Release" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_2_why_fauna_retained", - "label": "Why does the fauna need to be retained?" - }, - { - "type": "text_area", - "name": "survey_level_2_what_fauna_retained", - "label": "What fauna could be retained?" - }, - { - "type": "number", - "name": "survey_level_2_num_fauna_retained", - "label": "If fauna is to be retained, how many animals?" - }, - { - "conditions": { - "yes": [ - { - "type": "text_area", - "name": "survey_level_2_euthanise_method", - "label": "Method" - } - ] - }, - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "survey_level_2_fauna_euthanised", - "label": "Will fauna be euthanised?" - }, - { - "type": "text", - "name": "survey_level_2_where_specimen_stored", - "label": "Where will the specimen(s) be held/lodged/stored?" - }, - { - "type": "text_area", - "name": "survey_level_2_mesuem_storage_details", - "label": "If specimen is to be deposited at the WA Museum, will the Museum be contacted prior to the fauna being retained or did the Museum request the specimen?" - } - ] - }, - "type": "checkbox", - "name": "survey_level_2_retain", - "label": "Retain" - }, - { - "type": "text_area", - "name": "survey_level_2_unforseen_injury_dealings", - "label": "Describe how unforeseen injuries or other related issues will be dealt with." - }, - { - "type": "text_area", - "name": "survey_level_2_hygiene_disease_considerations", - "label": "Provide details of field hygiene and wildlife disease considerations." - }, - { - "type": "text_area", - "name": "survey_level_2_fauna_capture_other_details", - "label": "Provide other details relating to fauna capture." - } - ], - "other": [ - { - "type": "label", - "name": "survey_level_2_non_capture_method", - "label": "Please select any non-capture survey method you will be using" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_2_aural_survey_details", - "label": "Please provide Details" - }, - { - "conditions": { - "yes": [ - { - "type": "text_area", - "name": "survey_level_2_call_playback_details", - "label": "Please provide Details" - } - ] - }, - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "survey_level_2_call_playback", - "label": "Will call play-back be used?" - } - ] - }, - "type": "checkbox", - "name": "survey_level_2_aural_survey", - "label": "Aural survey" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_2_bird_census_details", - "label": "Please provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_2_bird_census", - "label": "Bird Census" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_2_spotlighting_details", - "label": "Please provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_2_spotlighting", - "label": "Spotlighting / head torching" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_2_hair_tubes_details", - "label": "Please provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_2_hair_tubes", - "label": "Hair tubes / sticky wicket" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_2_secondary_signs_details", - "label": "Please provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_2_secondary_signs", - "label": "Secondary signs / evidence" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_2_habitat_assessment_details", - "label": "Please provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_2_habitat_assessment", - "label": "Habitat Assessment" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_level_2_non_capture_other_details", - "label": "Please provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_level_2_non_capture_other", - "label": "Other" - } - ], - "remote_sensing": [ - { - "type": "label", - "name": "survey_level_2_remote_sensing_apparatus", - "label": "What remote sensing apparatus will you be using?" - }, - { - "conditions": { - "on": [ - { - "conditions": { - "yes": [ - { - "type": "text", - "name": "survey_level_2_what_bait", - "label": "What bait will be used?" - }, - { - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "survey_level_2_bait_consumable", - "label": "Will the bait be consumable?" - }, - { - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "survey_level_2_bait_replenished", - "label": "Will the bait be replenished?" - } - ] - }, - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "survey_level_2_camera_baited", - "label": "Will cameras be baited with an attractant/lure?" - }, - { - "children": [ - { - "type": "text", - "name": "survey_level_2_camera_make", - "label": "Make" - }, - { - "type": "number", - "name": "survey_level_2_num_cameras", - "label": "Number of devices" - }, - { - "type": "text_area", - "name": "survey_level_2_camera_placement", - "label": "Camera Placement" - }, - { - "type": "text", - "name": "survey_level_2_camera_situ", - "label": "How long in situ" - }, - { - "type": "text", - "name": "survey_level_2_camera_other_details", - "label": "Other details" - } - ], - "isRepeatable": true, - "type": "group", - "name": "survey_level_2_camera_information", - "label": "Camera Information" - } - ] - }, - "type": "checkbox", - "name": "survey_level_2_camera", - "label": "Camera" - }, - { - "conditions": { - "on": [ - { - "children": [ - { - "type": "text", - "name": "survey_level_2_ubd_make", - "label": "Make" - }, - { - "type": "number", - "name": "survey_level_2_num_ubds", - "label": "Number of devices" - }, - { - "type": "text", - "name": "survey_level_2_ubd_placement", - "label": "Ultrasonic bat detector Placement" - }, - { - "type": "text", - "name": "survey_level_2_ubd_situ", - "label": "How long in situ" - }, - { - "type": "text", - "name": "survey_level_2_ubd_other_details", - "label": "Other details" - } - ], - "isRepeatable": true, - "type": "group", - "name": "survey_level_2_ultrasonic_bat_detector_information", - "label": "Ultrasonic Bat Detector Information" - } - ] - }, - "type": "checkbox", - "name": "survey_level_2_ultrasonic_bat_detector", - "label": "Ultrasonic bat detector" - }, - { - "conditions": { - "on": [ - { - "children": [ - { - "type": "text", - "name": "survey_level_2_acr_make", - "label": "Make" - }, - { - "type": "number", - "name": "survey_level_2_num_acrs", - "label": "Number of devices" - }, - { - "type": "text", - "name": "survey_level_2_acr_placement", - "label": "Acoustic call recorder Placement" - }, - { - "type": "text", - "name": "survey_level_2_acr_situ", - "label": "How long in situ" - }, - { - "type": "text", - "name": "survey_level_2_acr_other_details", - "label": "Other details" - } - ], - "isRepeatable": true, - "type": "group", - "name": "survey_level_2_acoustic_call_recorder_information", - "label": "Acoustic call recorder Information" - } - ] - }, - "type": "checkbox", - "name": "survey_level_2_acoustic_call_recorder", - "label": "Acoustic call recorder" - }, - { - "conditions": { - "on": [ - { - "children": [ - { - "type": "text", - "name": "survey_level_2_aerial_make", - "label": "Make" - }, - { - "type": "number", - "name": "survey_level_2_num_aerials", - "label": "Number of devices" - }, - { - "type": "text", - "name": "survey_level_2_aerial_placement", - "label": "Aerial Placement" - }, - { - "type": "text", - "name": "survey_level_2_aerial_situ", - "label": "How long in situ" - }, - { - "type": "text", - "name": "survey_level_2_aerial_other_details", - "label": "Other details" - } - ], - "type": "group", - "name": "survey_level_2_aerial_information", - "label": "Aerial Information" - } - ] - }, - "type": "checkbox", - "name": "survey_level_2_aerial", - "label": "Aerial" - }, - { - "type": "text_area", - "name": "survey_level_2_remote_sensing_other_details", - "label": "Provide any other details relating to remote sensing." - } - ] - }, - "options": [ - { - "value": "capture", - "label": "Capture" - }, - { - "value": "remote_sensing", - "label": "Remote Sensing" - }, - { - "value": "other", - "label": "Other non-capture" - } - ], - "type": "radiobuttons", - "name": "survey_level_2_survey_method", - "label": "What survey method will you be using?" - } - ] - }, - "type": "checkbox", - "name": "survey_comprehensive", - "label": "Level 2 / detailed or comprehensive" - }, - { - "conditions": { - "on": [ - { - "conditions": { - "capture": [ - { - "conditions": { - "other": [ - { - "type": "text_area", - "name": "survey_sre_other_capture_methodology", - "label": "Provide details of your fauna capture methodology if it doesn\u2019t fit within previous questions for trap, net or hand capture techniques." - } - ], - "trap": [ - { - "type": "number", - "name": "survey_sre_num_trap_sites", - "label": "What is the number of trap sites?" - }, - { - "type": "number", - "name": "survey_sre_num_traps_open_days", - "label": "How many days/nights will traps be open?" - }, - { - "type": "number", - "name": "survey_sre_num_trap_sessions", - "label": "How many trapping sessions?" - }, - { - "type": "number", - "name": "survey_sre_num_traps_per_session", - "label": "Total number of traps per session?" - }, - { - "type": "number", - "name": "survey_sre_max_num_traps_per_session_per_site", - "label": "Maximum total number of traps per site per session?" - }, - { - "type": "text_area", - "name": "survey_sre_different_num_traps_per_session_or_site_explanation", - "label": "If the number of traps differs between sessions or sites, enter the highest number in the questions above, and explain differences below." - }, - { - "type": "label", - "name": "survey_sre_traps", - "label": "Traps" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_sre_dry_pit_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_sre_dry_pit_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_sre_num_dry_pits", - "label": "Number of traps" - }, - { - "type": "text", - "name": "survey_sre_dry_pit_placement", - "label": "Dry Pit Placement" - }, - { - "type": "text", - "name": "survey_sre_dry_pit_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_sre_dry_pit_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_sre_dry_pit", - "label": "Dry Pit" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_sre_wet_pit_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_sre_wet_pit_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_sre_num_wet_pits", - "label": "Number of traps" - }, - { - "type": "text", - "name": "survey_sre_wet_pit_placement", - "label": "Wet Pit Placement" - }, - { - "type": "text", - "name": "survey_sre_wet_pit_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_sre_wet_pit_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_sre_wet_pit", - "label": "Wet pit" - } - ], - "hand": [ - { - "type": "label", - "name": "survey_sre_hand_capture_techniques", - "label": "What hand capture techniques will you be using?" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_sre_hook_and_bag_details", - "label": "Please Provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_sre_hook_and_bag", - "label": "Hook and Bag" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_sre_Noose_details", - "label": "Please Provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_sre_noose", - "label": "Noose" - } - ] - }, - "options": [ - { - "value": "trap", - "label": "Trap" - }, - { - "value": "hand", - "label": "Hand" - }, - { - "value": "other", - "label": "Other" - } - ], - "type": "radiobuttons", - "name": "survey_sre_capture_method", - "label": "Capture Method" - }, - { - "type": "label", - "name": "survey_sre_fate", - "label": "What will be the fate(s) of the fauna captured?" - }, - { - "conditions": { - "on": [ - { - "options": [ - { - "value": "immediately", - "label": "Immediately after species idenfication" - }, - { - "value": "after_morphometrics", - "label": "After morphometrics and physical condition taken" - }, - { - "value": "after_samples", - "label": "After samples taken" - }, - { - "value": "after_marking", - "label": "After marking" - }, - { - "value": "after_temp_holding", - "label": "After temporary holding (< 24 hours)" - } - ], - "type": "select", - "name": "survey_sre_release_schedule", - "label": "Release Schedule" - }, - { - "type": "label", - "name": "survey_sre_pre_release_occurences", - "label": "Which of the following will occur before release?" - }, - { - "conditions": { - "on": [ - { - "type": "label", - "name": "survey_sre_mophometrics_recorded", - "label": "What morphometrics and condition details will be recorded?" - }, - { - "type": "checkbox", - "name": "survey_sre_mophometric_length", - "label": "Length" - }, - { - "type": "checkbox", - "name": "survey_sre_mophometric_sex", - "label": "Sex" - }, - { - "type": "checkbox", - "name": "survey_sre_mophometric_age", - "label": "Age" - }, - { - "type": "checkbox", - "name": "survey_sre_mophometric_body_condition", - "label": "Body condition" - }, - { - "type": "checkbox", - "name": "survey_sre_mophometric_reproductive_condition", - "label": "Reproductive condition" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_sre_mophometric_other_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_sre_mophometric_other", - "label": "Other" - }, - { - "type": "text_area", - "name": "survey_sre_mophometric_other_details", - "label": "Provide any other details relating to measurements and condition" - } - ] - }, - "type": "checkbox", - "name": "survey_sre_mophometrics", - "label": "Mophometrics and physical condition analysis" - }, - { - "conditions": { - "on": [ - { - "type": "label", - "name": "survey_sre_samples", - "label": "What samples will be taken?" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_sre_tissue_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_sre_tissue", - "label": "Tissue" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_sre_scale_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_sre_scale", - "label": "Scale" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_sre_hair_feather_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_sre_hair_feather", - "label": "Hair / feather" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_sre_blood_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_sre_blood", - "label": "Blood" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_sre_swabs_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_sre_swabs", - "label": "Swabs" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_sre_samples_other_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_sre_samples_other", - "label": "Other" - } - ] - }, - "type": "checkbox", - "name": "survey_sre_sampling", - "label": "Sampling" - }, - { - "conditions": { - "on": [ - { - "conditions": { - "permanent": [ - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_sre_tags_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_sre_tags", - "label": "Tags" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_sre_microchips_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_sre_microchips", - "label": "Microchips / implants" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_sre_bands_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_sre_bands", - "label": "Bands" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_sre_ear_punching_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_sre_ear_punching", - "label": "Ear punching" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_sre_marking_other_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_sre_marking_other", - "label": "Other" - } - ] - }, - "options": [ - { - "value": "temporary", - "label": "Temporary" - }, - { - "value": "permanent", - "label": "Permanent" - } - ], - "type": "select", - "name": "survey_sre_marking", - "label": "What marking will be done and why?" - } - ] - }, - "type": "checkbox", - "name": "survey_sre_marking", - "label": "Marking" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_sre_why_temporarily_held", - "label": "Why will/may the fauna be temporarily held?" - }, - { - "type": "text_area", - "name": "survey_sre_how_temporarily_held", - "label": "How will the fauna be held?" - }, - { - "type": "text_area", - "name": "survey_sre_where_temporarily_held", - "label": "Where will the fauna be held?" - }, - { - "type": "text_area", - "name": "survey_sre_transported_details", - "label": "If fauna will be transported, provide details?" - }, - { - "conditions": { - "other": [ - { - "type": "text_area", - "name": "survey_sre_fauna_release_other_details", - "label": "Please provide details" - } - ] - }, - "options": [ - { - "value": "at_capture_site", - "label": "At capture site" - }, - { - "value": "near_capture_site", - "label": "Near capture site into suitable habitat" - }, - { - "value": "other", - "label": "Other" - } - ], - "type": "select", - "name": "survey_sre_where_fauna_released", - "label": "Where will the fauna be released?" - } - ] - }, - "type": "checkbox", - "name": "survey_sre_temporary_holding", - "label": "Temporary Holding" - } - ] - }, - "type": "checkbox", - "name": "survey_sre_release", - "label": "Release" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_sre_why_fauna_retained", - "label": "Why does the fauna need to be retained?" - }, - { - "type": "text_area", - "name": "survey_sre_what_fauna_retained", - "label": "What fauna could be retained?" - }, - { - "type": "number", - "name": "survey_sre_num_fauna_retained", - "label": "If fauna is to be retained, how many animals?" - }, - { - "conditions": { - "yes": [ - { - "type": "text_area", - "name": "survey_sre_euthanise_method", - "label": "Method" - } - ] - }, - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "survey_sre_fauna_euthanised", - "label": "Will fauna be euthanised?" - }, - { - "type": "text", - "name": "survey_sre_where_specimen_stored", - "label": "Where will the specimen(s) be held/lodged/stored?" - }, - { - "type": "text_area", - "name": "survey_sre_mesuem_storage_details", - "label": "If specimen is to be deposited at the WA Museum, will the Museum be contacted prior to the fauna being retained or did the Museum request the specimen?" - } - ] - }, - "type": "checkbox", - "name": "survey_sre_retain", - "label": "Retain" - }, - { - "type": "text_area", - "name": "survey_sre_prevent_vertebre_by_catch", - "label": "Describe measures that will be used to prevent/minimise vertebrate by-catch" - }, - { - "type": "text_area", - "name": "survey_sre_hygiene_disease_considerations", - "label": "Provide details of field hygiene and wildlife disease considerations." - }, - { - "type": "text_area", - "name": "survey_sre_fauna_capture_other_details", - "label": "Provide other details relating to fauna capture." - } - ], - "other": [ - { - "type": "label", - "name": "survey_sre_non_capture_method", - "label": "Please select any non-capture survey method you will be using" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_sre_secondary_signs_details", - "label": "Please provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_sre_secondary_signs", - "label": "Secondary signs / evidence" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_sre_habitat_assessment_details", - "label": "Please provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_sre_habitat_assessment", - "label": "Habitat Assessment" - } - ] - }, - "options": [ - { - "value": "capture", - "label": "Capture" - }, - { - "value": "other", - "label": "Other non-capture" - } - ], - "type": "radiobuttons", - "name": "survey_sre_survey_method", - "label": "What survey method will you be using?" - } - ] - }, - "type": "checkbox", - "name": "survey_sre", - "label": "Short range endemic (SRE)" - }, - { - "conditions": { - "on": [ - { - "conditions": { - "litter_trap": [ - { - "type": "number", - "name": "survey_subterranean_num_trap_sites", - "label": "What is the number of trap sites?" - }, - { - "type": "number", - "name": "survey_subterranean_num_trap_bores", - "label": "What is the number of bores?" - }, - { - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "survey_subterranean_trap_bores_existing", - "label": "Are the bores existing? (yes/no)?" - }, - { - "type": "number", - "name": "survey_subterranean_num_traps_per_bore", - "label": "How many traps per bore hole?" - }, - { - "type": "number", - "name": "survey_subterranean_max_num_traps_survey", - "label": "Maximum total number of traps for the survey?" - }, - { - "type": "text", - "name": "survey_subterranean_length_traps_situ", - "label": "How long will be traps be left in situ (days or weeks)?" - }, - { - "type": "text", - "name": "survey_subterranean_trap_dimensions", - "label": "Dimensions of trap" - }, - { - "type": "text", - "name": "survey_subterranean_trap_design", - "label": "Trap construction materials and design" - }, - { - "type": "text", - "name": "survey_subterranean_trap_other_details", - "label": "Other details" - } - ], - "other": [ - { - "type": "text_area", - "name": "survey_subterranean_other_capture_methodology", - "label": "Provide details of your fauna capture methodology if it doesn\u2019t fit within previous questions for trap or net." - } - ], - "plankton_net": [ - { - "type": "number", - "name": "survey_subterranean_num_net_sites", - "label": "What is the number of net sites?" - }, - { - "type": "number", - "name": "survey_subterranean_num_net_bores", - "label": "What is the number of bores?" - }, - { - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "survey_subterranean_net_bores_existing", - "label": "Are the bores existing? (yes/no)?" - }, - { - "type": "number", - "name": "survey_subterranean_num_nets_per_bore", - "label": "How many net hauls per bore hole?" - }, - { - "type": "number", - "name": "survey_subterranean_max_num_nets_survey", - "label": "Maximum total number of net hauls for the survey?" - }, - { - "type": "text", - "name": "survey_subterranean_net_dimensions", - "label": "Dimensions of net" - }, - { - "type": "text", - "name": "survey_subterranean_net_design", - "label": "Net construction materials and design" - }, - { - "type": "text", - "name": "survey_subterranean_net_other_details", - "label": "Other details" - } - ] - }, - "options": [ - { - "value": "litter_trap", - "label": "Trap (litter)" - }, - { - "value": "plankton_net", - "label": "Net (plankton)" - } - ], - "type": "radiobuttons", - "name": "survey_subterranean_capture_method", - "label": "Capture Method" - }, - { - "type": "label", - "name": "survey_subterranean_fate", - "label": "What will be the fate(s) of the fauna captured?" - }, - { - "conditions": { - "on": [ - { - "options": [ - { - "value": "immediately", - "label": "Immediately after species idenfication" - }, - { - "value": "after_morphometrics", - "label": "After morphometrics and physical condition taken" - }, - { - "value": "after_samples", - "label": "After samples taken" - }, - { - "value": "after_marking", - "label": "After marking" - }, - { - "value": "after_temp_holding", - "label": "After temporary holding (< 24 hours)" - } - ], - "type": "select", - "name": "survey_subterranean_release_schedule", - "label": "Release Schedule" - }, - { - "type": "label", - "name": "survey_subterranean_pre_release_occurences", - "label": "Which of the following will occur before release?" - }, - { - "conditions": { - "on": [ - { - "type": "label", - "name": "survey_subterranean_mophometrics_recorded", - "label": "What morphometrics and condition details will be recorded?" - }, - { - "type": "checkbox", - "name": "survey_subterranean_mophometric_length", - "label": "Length" - }, - { - "type": "checkbox", - "name": "survey_subterranean_mophometric_sex", - "label": "Sex" - }, - { - "type": "checkbox", - "name": "survey_subterranean_mophometric_age", - "label": "Age" - }, - { - "type": "checkbox", - "name": "survey_subterranean_mophometric_body_condition", - "label": "Body condition" - }, - { - "type": "checkbox", - "name": "survey_subterranean_mophometric_reproductive_condition", - "label": "Reproductive condition" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_subterranean_mophometric_other_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_subterranean_mophometric_other", - "label": "Other" - }, - { - "type": "text_area", - "name": "survey_subterranean_mophometric_other_details", - "label": "Provide any other details relating to measurements and condition" - } - ] - }, - "type": "checkbox", - "name": "survey_subterranean_mophometrics", - "label": "Mophometrics and physical condition analysis" - }, - { - "conditions": { - "on": [ - { - "type": "label", - "name": "survey_subterranean_samples", - "label": "What samples will be taken?" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_subterranean_tissue_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_subterranean_tissue", - "label": "Tissue" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_subterranean_scale_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_subterranean_scale", - "label": "Scale" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_subterranean_hair_feather_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_subterranean_hair_feather", - "label": "Hair / feather" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_subterranean_blood_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_subterranean_blood", - "label": "Blood" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_subterranean_swabs_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_subterranean_swabs", - "label": "Swabs" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_subterranean_samples_other_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_subterranean_samples_other", - "label": "Other" - } - ] - }, - "type": "checkbox", - "name": "survey_subterranean_sampling", - "label": "Sampling" - }, - { - "conditions": { - "on": [ - { - "conditions": { - "permanent": [ - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_subterranean_tags_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_subterranean_tags", - "label": "Tags" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_subterranean_microchips_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_subterranean_microchips", - "label": "Microchips / implants" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_subterranean_bands_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_subterranean_bands", - "label": "Bands" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_subterranean_ear_punching_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_subterranean_ear_punching", - "label": "Ear punching" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_subterranean_marking_other_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_subterranean_marking_other", - "label": "Other" - } - ] - }, - "options": [ - { - "value": "temporary", - "label": "Temporary" - }, - { - "value": "permanent", - "label": "Permanent" - } - ], - "type": "select", - "name": "survey_subterranean_marking", - "label": "What marking will be done and why?" - } - ] - }, - "type": "checkbox", - "name": "survey_subterranean_marking", - "label": "Marking" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_subterranean_why_temporarily_held", - "label": "Why will/may the fauna be temporarily held?" - }, - { - "type": "text_area", - "name": "survey_subterranean_how_temporarily_held", - "label": "How will the fauna be held?" - }, - { - "type": "text_area", - "name": "survey_subterranean_where_temporarily_held", - "label": "Where will the fauna be held?" - }, - { - "type": "text_area", - "name": "survey_subterranean_transported_details", - "label": "If fauna will be transported, provide details?" - }, - { - "conditions": { - "other": [ - { - "type": "text_area", - "name": "survey_subterranean_fauna_release_other_details", - "label": "Please provide details" - } - ] - }, - "options": [ - { - "value": "at_capture_site", - "label": "At capture site" - }, - { - "value": "near_capture_site", - "label": "Near capture site into suitable habitat" - }, - { - "value": "other", - "label": "Other" - } - ], - "type": "select", - "name": "survey_subterranean_where_fauna_released", - "label": "Where will the fauna be released?" - } - ] - }, - "type": "checkbox", - "name": "survey_subterranean_temporary_holding", - "label": "Temporary Holding" - } - ] - }, - "type": "checkbox", - "name": "survey_subterranean_release", - "label": "Release" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_subterranean_why_fauna_retained", - "label": "Why does the fauna need to be retained?" - }, - { - "type": "text_area", - "name": "survey_subterranean_what_fauna_retained", - "label": "What fauna could be retained?" - }, - { - "type": "number", - "name": "survey_subterranean_num_fauna_retained", - "label": "If fauna is to be retained, how many animals?" - }, - { - "conditions": { - "yes": [ - { - "type": "text_area", - "name": "survey_subterranean_euthanise_method", - "label": "Method" - } - ] - }, - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "survey_subterranean_fauna_euthanised", - "label": "Will fauna be euthanised?" - }, - { - "type": "text", - "name": "survey_subterranean_where_specimen_stored", - "label": "Where will the specimen(s) be held/lodged/stored?" - }, - { - "type": "text_area", - "name": "survey_subterranean_mesuem_storage_details", - "label": "If specimen is to be deposited at the WA Museum, will the Museum be contacted prior to the fauna being retained or did the Museum request the specimen?" - } - ] - }, - "type": "checkbox", - "name": "survey_subterranean_retain", - "label": "Retain" - }, - { - "type": "text_area", - "name": "survey_subterranean_prevent_vertebre_by_catch", - "label": "Describe measures that will be used to prevent/minimise vertebrate by-catch" - }, - { - "type": "text_area", - "name": "survey_subterranean_hygiene_disease_considerations", - "label": "Provide details of field hygiene and wildlife disease considerations." - }, - { - "type": "text_area", - "name": "survey_subterranean_fauna_capture_other_details", - "label": "Provide other details relating to fauna capture." - } - ] - }, - "type": "checkbox", - "name": "survey_subterranean", - "label": "Subterranean" - }, - { - "conditions": { - "on": [ - { - "conditions": { - "capture": [ - { - "conditions": { - "net": [ - { - "type": "number", - "name": "survey_aquatic_num_net_sites", - "label": "What is the number of sites where nets will be used?" - }, - { - "type": "number", - "name": "survey_aquatic_num_net_days", - "label": "How many days/nights will nets be used?" - }, - { - "type": "number", - "name": "survey_aquatic_num_net_sessions", - "label": "How many sessions will nets be used?" - }, - { - "type": "number", - "name": "survey_aquatic_num_nets_per_session", - "label": "Total number of nets per session?" - }, - { - "type": "number", - "name": "survey_aquatic_max_num_nets_per_session_per_site", - "label": "Maximum total number of nets per site per session?" - }, - { - "type": "text_area", - "name": "survey_aquatic_different_num_nets_per_session_or_site_explanation", - "label": "If the number of nets differs between sessions or sites then explain" - }, - { - "type": "label", - "name": "survey_aquatic_nets", - "label": "Nets" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_aquatic_dip_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_aquatic_dip_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_aquatic_num_dips", - "label": "Number of nets" - }, - { - "type": "text", - "name": "survey_aquatic_dip_placement", - "label": "Net Placement" - }, - { - "type": "text", - "name": "survey_aquatic_dip_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_aquatic_dip_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_aquatic_dip", - "label": "Dip" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_aquatic_sweep_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_aquatic_sweep_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_aquatic_num_sweeps", - "label": "Number of nets" - }, - { - "type": "text", - "name": "survey_aquatic_sweep_placement", - "label": "Net Placement" - }, - { - "type": "text", - "name": "survey_aquatic_sweep_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_aquatic_sweep_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_aquatic_sweep", - "label": "Sweep" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_aquatic_gill_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_aquatic_gill_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_aquatic_num_gills", - "label": "Number of nets" - }, - { - "type": "text", - "name": "survey_aquatic_gill_placement", - "label": "Net Placement" - }, - { - "type": "text", - "name": "survey_aquatic_gill_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_aquatic_gill_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_aquatic_gill", - "label": "Gill" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_aquatic_seine_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_aquatic_seine_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_aquatic_num_seines", - "label": "Number of nets" - }, - { - "type": "text", - "name": "survey_aquatic_seine_placement", - "label": "Net Placement" - }, - { - "type": "text", - "name": "survey_aquatic_seine_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_aquatic_seine_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_aquatic_seine", - "label": "Seine" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_aquatic_cast_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_aquatic_cast_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_aquatic_num_casts", - "label": "Number of nets" - }, - { - "type": "text", - "name": "survey_aquatic_cast_placement", - "label": "Net Placement" - }, - { - "type": "text", - "name": "survey_aquatic_cast_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_aquatic_cast_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_aquatic_cast", - "label": "Cast" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_aquatic_plankton_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_aquatic_plankton_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_aquatic_num_planktons", - "label": "Number of nets" - }, - { - "type": "text", - "name": "survey_aquatic_plankton_placement", - "label": "Net Placement" - }, - { - "type": "text", - "name": "survey_aquatic_plankton_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_aquatic_plankton_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_aquatic_plankton", - "label": "Plankton" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_aquatic_net_type_other", - "label": "Enter details" - }, - { - "type": "text", - "name": "survey_aquatic_net_other_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_aquatic_net_other_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_aquatic_net_other_num_nets", - "label": "Number of nets" - }, - { - "type": "text", - "name": "survey_aquatic_net_other_placement", - "label": "Net Placement" - }, - { - "type": "text", - "name": "survey_aquatic_net_other_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_aquatic_net_other_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_aquatic_net_other", - "label": "Other" - } - ], - "other": [ - { - "type": "text_area", - "name": "survey_aquatic_other_capture_methodology", - "label": "Provide details of your fauna capture methodology if it doesn\u2019t fit within previous questions for trap, net or hand capture techniques." - } - ], - "trap": [ - { - "type": "number", - "name": "survey_aquatic_num_trap_sites", - "label": "What is the number of trap sites?" - }, - { - "type": "number", - "name": "survey_aquatic_num_traps_open_days", - "label": "How many days/nights will traps be open?" - }, - { - "type": "number", - "name": "survey_aquatic_num_trap_sessions", - "label": "How many trapping sessions?" - }, - { - "type": "number", - "name": "survey_aquatic_num_traps_per_session", - "label": "Total number of traps per session?" - }, - { - "type": "number", - "name": "survey_aquatic_max_num_traps_per_session_per_site", - "label": "Maximum total number of traps per site per session?" - }, - { - "type": "text_area", - "name": "survey_aquatic_different_num_traps_per_session_or_site_explanation", - "label": "If the number of traps differs between sessions or sites, enter the highest number in the questions above, and explain differences below." - }, - { - "type": "label", - "name": "survey_aquatic_traps", - "label": "Traps" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_aquatic_cage_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_aquatic_cage_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_aquatic_num_cages", - "label": "Number of traps" - }, - { - "type": "text", - "name": "survey_aquatic_cage_placement", - "label": "Cage Placement" - }, - { - "type": "text", - "name": "survey_aquatic_cage_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_aquatic_cage_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_aquatic_cage", - "label": "Cage" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_aquatic_box_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_aquatic_box_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_aquatic_num_boxs", - "label": "Number of traps" - }, - { - "type": "text", - "name": "survey_aquatic_box_placement", - "label": "Box Placement" - }, - { - "type": "text", - "name": "survey_aquatic_box_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_aquatic_box_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_aquatic_box", - "label": "Box" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_aquatic_trap_type_other", - "label": "Enter details" - }, - { - "type": "text", - "name": "survey_aquatic_trap_other_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_aquatic_trap_other_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_aquatic_trap_other_num_traps", - "label": "Number of traps" - }, - { - "type": "text", - "name": "survey_aquatic_trap_other_placement", - "label": "Trap Placement" - }, - { - "type": "text", - "name": "survey_aquatic_trap_other_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_aquatic_trap_other_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_aquatic_trap_other", - "label": "Other" - } - ], - "hand": [ - { - "type": "label", - "name": "survey_aquatic_hand_capture_techniques", - "label": "What hand capture techniques will you be using?" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_aquatic_foraging_details", - "label": "Please Provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_aquatic_foraging", - "label": "Foraging" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_aquatic_excavation_details", - "label": "Please Provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_aquatic_excavation", - "label": "Excavation" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_aquatic_excavation_details", - "label": "Please Provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_aquatic_other_hand_capture_techniques", - "label": "Other" - } - ] - }, - "options": [ - { - "value": "trap", - "label": "Trap" - }, - { - "value": "net", - "label": "Net" - }, - { - "value": "hand", - "label": "Hand" - }, - { - "value": "other", - "label": "Other" - } - ], - "type": "radiobuttons", - "name": "survey_aquatic_capture_method", - "label": "Capture Method" - }, - { - "type": "label", - "name": "survey_aquatic_fate", - "label": "What will be the fate(s) of the fauna captured?" - }, - { - "conditions": { - "on": [ - { - "options": [ - { - "value": "immediately", - "label": "Immediately after species idenfication" - }, - { - "value": "after_morphometrics", - "label": "After morphometrics and physical condition taken" - }, - { - "value": "after_samples", - "label": "After samples taken" - }, - { - "value": "after_marking", - "label": "After marking" - }, - { - "value": "after_temp_holding", - "label": "After temporary holding (< 24 hours)" - } - ], - "type": "select", - "name": "survey_aquatic_release_schedule", - "label": "Release Schedule" - }, - { - "type": "label", - "name": "survey_aquatic_pre_release_occurences", - "label": "Which of the following will occur before release?" - }, - { - "conditions": { - "on": [ - { - "type": "label", - "name": "survey_aquatic_mophometrics_recorded", - "label": "What morphometrics and condition details will be recorded?" - }, - { - "type": "checkbox", - "name": "survey_aquatic_mophometric_length", - "label": "Length" - }, - { - "type": "checkbox", - "name": "survey_aquatic_mophometric_sex", - "label": "Sex" - }, - { - "type": "checkbox", - "name": "survey_aquatic_mophometric_age", - "label": "Age" - }, - { - "type": "checkbox", - "name": "survey_aquatic_mophometric_body_condition", - "label": "Body condition" - }, - { - "type": "checkbox", - "name": "survey_aquatic_mophometric_reproductive_condition", - "label": "Reproductive condition" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_aquatic_mophometric_other_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_aquatic_mophometric_other", - "label": "Other" - }, - { - "type": "text_area", - "name": "survey_aquatic_mophometric_other_details", - "label": "Provide any other details relating to measurements and condition" - } - ] - }, - "type": "checkbox", - "name": "survey_aquatic_mophometrics", - "label": "Mophometrics and physical condition analysis" - }, - { - "conditions": { - "on": [ - { - "type": "label", - "name": "survey_aquatic_samples", - "label": "What samples will be taken?" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_aquatic_tissue_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_aquatic_tissue", - "label": "Tissue" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_aquatic_scale_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_aquatic_scale", - "label": "Scale" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_aquatic_hair_feather_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_aquatic_hair_feather", - "label": "Hair / feather" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_aquatic_blood_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_aquatic_blood", - "label": "Blood" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_aquatic_swabs_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_aquatic_swabs", - "label": "Swabs" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_aquatic_samples_other_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_aquatic_samples_other", - "label": "Other" - } - ] - }, - "type": "checkbox", - "name": "survey_aquatic_sampling", - "label": "Sampling" - }, - { - "conditions": { - "on": [ - { - "conditions": { - "permanent": [ - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_aquatic_tags_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_aquatic_tags", - "label": "Tags" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_aquatic_microchips_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_aquatic_microchips", - "label": "Microchips / implants" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_aquatic_bands_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_aquatic_bands", - "label": "Bands" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_aquatic_ear_punching_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_aquatic_ear_punching", - "label": "Ear punching" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_aquatic_marking_other_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_aquatic_marking_other", - "label": "Other" - } - ] - }, - "options": [ - { - "value": "temporary", - "label": "Temporary" - }, - { - "value": "permanent", - "label": "Permanent" - } - ], - "type": "select", - "name": "survey_aquatic_marking", - "label": "What marking will be done and why?" - } - ] - }, - "type": "checkbox", - "name": "survey_aquatic_marking", - "label": "Marking" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_aquatic_why_temporarily_held", - "label": "Why will/may the fauna be temporarily held?" - }, - { - "type": "text_area", - "name": "survey_aquatic_how_temporarily_held", - "label": "How will the fauna be held?" - }, - { - "type": "text_area", - "name": "survey_aquatic_where_temporarily_held", - "label": "Where will the fauna be held?" - }, - { - "type": "text_area", - "name": "survey_aquatic_transported_details", - "label": "If fauna will be transported, provide details?" - }, - { - "conditions": { - "other": [ - { - "type": "text_area", - "name": "survey_aquatic_fauna_release_other_details", - "label": "Please provide details" - } - ] - }, - "options": [ - { - "value": "at_capture_site", - "label": "At capture site" - }, - { - "value": "near_capture_site", - "label": "Near capture site into suitable habitat" - }, - { - "value": "other", - "label": "Other" - } - ], - "type": "select", - "name": "survey_aquatic_where_fauna_released", - "label": "Where will the fauna be released?" - } - ] - }, - "type": "checkbox", - "name": "survey_aquatic_temporary_holding", - "label": "Temporary Holding" - } - ] - }, - "type": "checkbox", - "name": "survey_aquatic_release", - "label": "Release" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_aquatic_why_fauna_retained", - "label": "Why does the fauna need to be retained?" - }, - { - "type": "text_area", - "name": "survey_aquatic_what_fauna_retained", - "label": "What fauna could be retained?" - }, - { - "type": "number", - "name": "survey_aquatic_num_fauna_retained", - "label": "If fauna is to be retained, how many animals?" - }, - { - "conditions": { - "yes": [ - { - "type": "text_area", - "name": "survey_aquatic_euthanise_method", - "label": "Method" - } - ] - }, - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "survey_aquatic_fauna_euthanised", - "label": "Will fauna be euthanised?" - }, - { - "type": "text", - "name": "survey_aquatic_where_specimen_stored", - "label": "Where will the specimen(s) be held/lodged/stored?" - }, - { - "type": "text_area", - "name": "survey_aquatic_mesuem_storage_details", - "label": "If specimen is to be deposited at the WA Museum, will the Museum be contacted prior to the fauna being retained or did the Museum request the specimen?" - } - ] - }, - "type": "checkbox", - "name": "survey_aquatic_retain", - "label": "Retain" - }, - { - "type": "text_area", - "name": "survey_aquatic_unforseen_injury_dealings", - "label": "Describe how unforeseen injuries or other related issues will be dealt with." - }, - { - "type": "text_area", - "name": "survey_aquatic_hygiene_disease_considerations", - "label": "Provide details of field hygiene and wildlife disease considerations." - }, - { - "type": "text_area", - "name": "survey_aquatic_fauna_capture_other_details", - "label": "Provide other details relating to fauna capture." - } - ], - "other": [ - { - "type": "label", - "name": "survey_aquatic_non_capture_method", - "label": "Please select any non-capture survey method you will be using" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_aquatic_secondary_signs_details", - "label": "Please provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_aquatic_secondary_signs", - "label": "Secondary signs / evidence" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_aquatic_habitat_assessment_details", - "label": "Please provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_aquatic_habitat_assessment", - "label": "Habitat Assessment" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_aquatic_non_capture_other_details", - "label": "Please provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_aquatic_non_capture_other", - "label": "Other" - } - ], - "remote_sensing": [ - { - "type": "label", - "name": "survey_aquatic_remote_sensing_apparatus", - "label": "What remote sensing apparatus will you be using?" - }, - { - "conditions": { - "on": [ - { - "conditions": { - "yes": [ - { - "type": "text", - "name": "survey_aquatic_what_bait", - "label": "What bait will be used?" - }, - { - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "survey_aquatic_bait_consumable", - "label": "Will the bait be consumable?" - }, - { - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "survey_aquatic_bait_replenished", - "label": "Will the bait be replenished?" - } - ] - }, - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "survey_aquatic_camera_baited", - "label": "Will cameras be baited with an attractant/lure?" - }, - { - "children": [ - { - "type": "text", - "name": "survey_aquatic_camera_make", - "label": "Make" - }, - { - "type": "number", - "name": "survey_aquatic_num_cameras", - "label": "Number of devices" - }, - { - "type": "text_area", - "name": "survey_aquatic_camera_placement", - "label": "Camera Placement" - }, - { - "type": "text", - "name": "survey_aquatic_camera_situ", - "label": "How long in situ" - }, - { - "type": "text", - "name": "survey_aquatic_camera_other_details", - "label": "Other details" - } - ], - "isRepeatable": true, - "type": "group", - "name": "survey_aquatic_camera_information", - "label": "Camera Information" - } - ] - }, - "type": "checkbox", - "name": "survey_aquatic_camera", - "label": "Camera" - }, - { - "conditions": { - "on": [ - { - "children": [ - { - "type": "text", - "name": "survey_aquatic_acr_make", - "label": "Make" - }, - { - "type": "number", - "name": "survey_aquatic_num_acrs", - "label": "Number of devices" - }, - { - "type": "text", - "name": "survey_aquatic_acr_placement", - "label": "Acoustic recorder Placement" - }, - { - "type": "text", - "name": "survey_aquatic_acr_situ", - "label": "How long in situ" - }, - { - "type": "text", - "name": "survey_aquatic_acr_other_details", - "label": "Other details" - } - ], - "isRepeatable": true, - "type": "group", - "name": "survey_aquatic_acoustic_call_recorder_information", - "label": "Acoustic recorder Information" - } - ] - }, - "type": "checkbox", - "name": "survey_aquatic_acoustic_recorder", - "label": "Acoustic recorder" - }, - { - "type": "text_area", - "name": "survey_aquatic_remote_sensing_other_details", - "label": "Provide any other details relating to remote sensing." - } - ] - }, - "options": [ - { - "value": "capture", - "label": "Capture" - }, - { - "value": "remote_sensing", - "label": "Remote Sensing" - }, - { - "value": "other", - "label": "Other non-capture" - } - ], - "type": "radiobuttons", - "name": "survey_aquatic_survey_method", - "label": "What survey method will you be using?" - } - ] - }, - "type": "checkbox", - "name": "survey_aquatic", - "label": "Aquatic (non-marine)" - }, - { - "conditions": { - "on": [ - { - "conditions": { - "capture": [ - { - "conditions": { - "net": [ - { - "type": "number", - "name": "survey_marine_num_net_sites", - "label": "What is the number of sites where nets will be used?" - }, - { - "type": "number", - "name": "survey_marine_num_net_days", - "label": "How many days/nights will nets be used?" - }, - { - "type": "number", - "name": "survey_marine_num_net_sessions", - "label": "How many sessions will nets be used?" - }, - { - "type": "number", - "name": "survey_marine_num_nets_per_session", - "label": "Total number of nets per session?" - }, - { - "type": "number", - "name": "survey_marine_max_num_nets_per_session_per_site", - "label": "Maximum total number of nets per site per session?" - }, - { - "type": "text_area", - "name": "survey_marine_different_num_nets_per_session_or_site_explanation", - "label": "If the number of nets differs between sessions or sites then explain" - }, - { - "type": "label", - "name": "survey_marine_nets", - "label": "Nets" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_marine_dip_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_marine_dip_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_marine_num_dips", - "label": "Number of nets" - }, - { - "type": "text", - "name": "survey_marine_dip_placement", - "label": "Net Placement" - }, - { - "type": "text", - "name": "survey_marine_dip_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_marine_dip_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_marine_dip", - "label": "Dip" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_marine_sweep_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_marine_sweep_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_marine_num_sweeps", - "label": "Number of nets" - }, - { - "type": "text", - "name": "survey_marine_sweep_placement", - "label": "Net Placement" - }, - { - "type": "text", - "name": "survey_marine_sweep_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_marine_sweep_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_marine_sweep", - "label": "Sweep" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_marine_gill_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_marine_gill_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_marine_num_gills", - "label": "Number of nets" - }, - { - "type": "text", - "name": "survey_marine_gill_placement", - "label": "Net Placement" - }, - { - "type": "text", - "name": "survey_marine_gill_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_marine_gill_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_marine_gill", - "label": "Gill" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_marine_seine_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_marine_seine_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_marine_num_seines", - "label": "Number of nets" - }, - { - "type": "text", - "name": "survey_marine_seine_placement", - "label": "Net Placement" - }, - { - "type": "text", - "name": "survey_marine_seine_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_marine_seine_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_marine_seine", - "label": "Seine" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_marine_cast_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_marine_cast_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_marine_num_casts", - "label": "Number of nets" - }, - { - "type": "text", - "name": "survey_marine_cast_placement", - "label": "Net Placement" - }, - { - "type": "text", - "name": "survey_marine_cast_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_marine_cast_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_marine_cast", - "label": "Cast" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_marine_plankton_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_marine_plankton_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_marine_num_planktons", - "label": "Number of nets" - }, - { - "type": "text", - "name": "survey_marine_plankton_placement", - "label": "Net Placement" - }, - { - "type": "text", - "name": "survey_marine_plankton_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_marine_plankton_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_marine_plankton", - "label": "Plankton" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_marine_net_type_other", - "label": "Enter details" - }, - { - "type": "text", - "name": "survey_marine_net_other_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_marine_net_other_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_marine_net_other_num_nets", - "label": "Number of nets" - }, - { - "type": "text", - "name": "survey_marine_net_other_placement", - "label": "Net Placement" - }, - { - "type": "text", - "name": "survey_marine_net_other_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_marine_net_other_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_marine_net_other", - "label": "Other" - } - ], - "other": [ - { - "type": "text_area", - "name": "survey_marine_other_capture_methodology", - "label": "Provide details of your fauna capture methodology if it doesn\u2019t fit within previous questions for trap, net or hand capture techniques." - } - ], - "trap": [ - { - "type": "number", - "name": "survey_marine_num_trap_sites", - "label": "What is the number of trap sites?" - }, - { - "type": "number", - "name": "survey_marine_num_traps_open_days", - "label": "How many days/nights will traps be open?" - }, - { - "type": "number", - "name": "survey_marine_num_trap_sessions", - "label": "How many trapping sessions?" - }, - { - "type": "number", - "name": "survey_marine_num_traps_per_session", - "label": "Total number of traps per session?" - }, - { - "type": "number", - "name": "survey_marine_max_num_traps_per_session_per_site", - "label": "Maximum total number of traps per site per session?" - }, - { - "type": "text_area", - "name": "survey_marine_different_num_traps_per_session_or_site_explanation", - "label": "If the number of traps differs between sessions or sites, enter the highest number in the questions above, and explain differences below." - }, - { - "type": "label", - "name": "survey_marine_traps", - "label": "Traps" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_marine_cage_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_marine_cage_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_marine_num_cages", - "label": "Number of traps" - }, - { - "type": "text", - "name": "survey_marine_cage_placement", - "label": "Cage Placement" - }, - { - "type": "text", - "name": "survey_marine_cage_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_marine_cage_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_marine_cage", - "label": "Cage" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_marine_box_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_marine_box_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_marine_num_boxs", - "label": "Number of traps" - }, - { - "type": "text", - "name": "survey_marine_box_placement", - "label": "Box Placement" - }, - { - "type": "text", - "name": "survey_marine_box_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_marine_box_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_marine_box", - "label": "Box" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_marine_trap_type_other", - "label": "Enter details" - }, - { - "type": "text", - "name": "survey_marine_trap_other_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_marine_trap_other_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_marine_trap_other_num_traps", - "label": "Number of traps" - }, - { - "type": "text", - "name": "survey_marine_trap_other_placement", - "label": "Trap Placement" - }, - { - "type": "text", - "name": "survey_marine_trap_other_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_marine_trap_other_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_marine_trap_other", - "label": "Other" - } - ], - "hand": [ - { - "type": "label", - "name": "survey_marine_hand_capture_techniques", - "label": "What hand capture techniques will you be using?" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_marine_foraging_details", - "label": "Please Provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_marine_foraging", - "label": "Foraging" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_marine_excavation_details", - "label": "Please Provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_marine_excavation", - "label": "Excavation" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_marine_excavation_details", - "label": "Please Provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_marine_other_hand_capture_techniques", - "label": "Other" - } - ] - }, - "options": [ - { - "value": "trap", - "label": "Trap" - }, - { - "value": "net", - "label": "Net" - }, - { - "value": "hand", - "label": "Hand" - }, - { - "value": "other", - "label": "Other" - } - ], - "type": "radiobuttons", - "name": "survey_marine_capture_method", - "label": "Capture Method" - }, - { - "type": "label", - "name": "survey_marine_fate", - "label": "What will be the fate(s) of the fauna captured?" - }, - { - "conditions": { - "on": [ - { - "options": [ - { - "value": "immediately", - "label": "Immediately after species idenfication" - }, - { - "value": "after_morphometrics", - "label": "After morphometrics and physical condition taken" - }, - { - "value": "after_samples", - "label": "After samples taken" - }, - { - "value": "after_marking", - "label": "After marking" - }, - { - "value": "after_temp_holding", - "label": "After temporary holding (< 24 hours)" - } - ], - "type": "select", - "name": "survey_marine_release_schedule", - "label": "Release Schedule" - }, - { - "type": "label", - "name": "survey_marine_pre_release_occurences", - "label": "Which of the following will occur before release?" - }, - { - "conditions": { - "on": [ - { - "type": "label", - "name": "survey_marine_mophometrics_recorded", - "label": "What morphometrics and condition details will be recorded?" - }, - { - "type": "checkbox", - "name": "survey_marine_mophometric_length", - "label": "Length" - }, - { - "type": "checkbox", - "name": "survey_marine_mophometric_sex", - "label": "Sex" - }, - { - "type": "checkbox", - "name": "survey_marine_mophometric_age", - "label": "Age" - }, - { - "type": "checkbox", - "name": "survey_marine_mophometric_body_condition", - "label": "Body condition" - }, - { - "type": "checkbox", - "name": "survey_marine_mophometric_reproductive_condition", - "label": "Reproductive condition" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_marine_mophometric_other_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_marine_mophometric_other", - "label": "Other" - }, - { - "type": "text_area", - "name": "survey_marine_mophometric_other_details", - "label": "Provide any other details relating to measurements and condition" - } - ] - }, - "type": "checkbox", - "name": "survey_marine_mophometrics", - "label": "Mophometrics and physical condition analysis" - }, - { - "conditions": { - "on": [ - { - "type": "label", - "name": "survey_marine_samples", - "label": "What samples will be taken?" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_marine_tissue_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_marine_tissue", - "label": "Tissue" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_marine_scale_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_marine_scale", - "label": "Scale" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_marine_hair_feather_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_marine_hair_feather", - "label": "Hair / feather" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_marine_blood_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_marine_blood", - "label": "Blood" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_marine_swabs_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_marine_swabs", - "label": "Swabs" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_marine_samples_other_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_marine_samples_other", - "label": "Other" - } - ] - }, - "type": "checkbox", - "name": "survey_marine_sampling", - "label": "Sampling" - }, - { - "conditions": { - "on": [ - { - "conditions": { - "permanent": [ - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_marine_tags_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_marine_tags", - "label": "Tags" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_marine_microchips_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_marine_microchips", - "label": "Microchips / implants" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_marine_bands_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_marine_bands", - "label": "Bands" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_marine_ear_punching_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_marine_ear_punching", - "label": "Ear punching" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_marine_marking_other_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_marine_marking_other", - "label": "Other" - } - ] - }, - "options": [ - { - "value": "temporary", - "label": "Temporary" - }, - { - "value": "permanent", - "label": "Permanent" - } - ], - "type": "select", - "name": "survey_marine_marking", - "label": "What marking will be done and why?" - } - ] - }, - "type": "checkbox", - "name": "survey_marine_marking", - "label": "Marking" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_marine_why_temporarily_held", - "label": "Why will/may the fauna be temporarily held?" - }, - { - "type": "text_area", - "name": "survey_marine_how_temporarily_held", - "label": "How will the fauna be held?" - }, - { - "type": "text_area", - "name": "survey_marine_where_temporarily_held", - "label": "Where will the fauna be held?" - }, - { - "type": "text_area", - "name": "survey_marine_transported_details", - "label": "If fauna will be transported, provide details?" - }, - { - "conditions": { - "other": [ - { - "type": "text_area", - "name": "survey_marine_fauna_release_other_details", - "label": "Please provide details" - } - ] - }, - "options": [ - { - "value": "at_capture_site", - "label": "At capture site" - }, - { - "value": "near_capture_site", - "label": "Near capture site into suitable habitat" - }, - { - "value": "other", - "label": "Other" - } - ], - "type": "select", - "name": "survey_marine_where_fauna_released", - "label": "Where will the fauna be released?" - } - ] - }, - "type": "checkbox", - "name": "survey_marine_temporary_holding", - "label": "Temporary Holding" - } - ] - }, - "type": "checkbox", - "name": "survey_marine_release", - "label": "Release" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_marine_why_fauna_retained", - "label": "Why does the fauna need to be retained?" - }, - { - "type": "text_area", - "name": "survey_marine_what_fauna_retained", - "label": "What fauna could be retained?" - }, - { - "type": "number", - "name": "survey_marine_num_fauna_retained", - "label": "If fauna is to be retained, how many animals?" - }, - { - "conditions": { - "yes": [ - { - "type": "text_area", - "name": "survey_marine_euthanise_method", - "label": "Method" - } - ] - }, - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "survey_marine_fauna_euthanised", - "label": "Will fauna be euthanised?" - }, - { - "type": "text", - "name": "survey_marine_where_specimen_stored", - "label": "Where will the specimen(s) be held/lodged/stored?" - }, - { - "type": "text_area", - "name": "survey_marine_mesuem_storage_details", - "label": "If specimen is to be deposited at the WA Museum, will the Museum be contacted prior to the fauna being retained or did the Museum request the specimen?" - } - ] - }, - "type": "checkbox", - "name": "survey_marine_retain", - "label": "Retain" - }, - { - "type": "text_area", - "name": "survey_marine_unforseen_injury_dealings", - "label": "Describe how unforeseen injuries or other related issues will be dealt with." - }, - { - "type": "text_area", - "name": "survey_marine_hygiene_disease_considerations", - "label": "Provide details of field hygiene and wildlife disease considerations." - }, - { - "type": "text_area", - "name": "survey_marine_fauna_capture_other_details", - "label": "Provide other details relating to fauna capture." - } - ], - "other": [ - { - "type": "label", - "name": "survey_marine_non_capture_method", - "label": "Please select any non-capture survey method you will be using" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_marine_secondary_signs_details", - "label": "Please provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_marine_secondary_signs", - "label": "Secondary signs / evidence" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_marine_habitat_assessment_details", - "label": "Please provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_marine_habitat_assessment", - "label": "Habitat Assessment" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_marine_non_capture_other_details", - "label": "Please provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_marine_non_capture_other", - "label": "Other" - } - ], - "remote_sensing": [ - { - "type": "label", - "name": "survey_marine_remote_sensing_apparatus", - "label": "What remote sensing apparatus will you be using?" - }, - { - "conditions": { - "on": [ - { - "conditions": { - "yes": [ - { - "type": "text", - "name": "survey_marine_what_bait", - "label": "What bait will be used?" - }, - { - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "survey_marine_bait_consumable", - "label": "Will the bait be consumable?" - }, - { - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "survey_marine_bait_replenished", - "label": "Will the bait be replenished?" - } - ] - }, - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "survey_marine_camera_baited", - "label": "Will cameras be baited with an attractant/lure?" - }, - { - "children": [ - { - "type": "text", - "name": "survey_marine_camera_make", - "label": "Make" - }, - { - "type": "number", - "name": "survey_marine_num_cameras", - "label": "Number of devices" - }, - { - "type": "text_area", - "name": "survey_marine_camera_placement", - "label": "Camera Placement" - }, - { - "type": "text", - "name": "survey_marine_camera_situ", - "label": "How long in situ" - }, - { - "type": "text", - "name": "survey_marine_camera_other_details", - "label": "Other details" - } - ], - "isRepeatable": true, - "type": "group", - "name": "survey_marine_camera_information", - "label": "Camera Information" - } - ] - }, - "type": "checkbox", - "name": "survey_marine_camera", - "label": "Camera" - }, - { - "conditions": { - "on": [ - { - "children": [ - { - "type": "text", - "name": "survey_marine_acr_make", - "label": "Make" - }, - { - "type": "number", - "name": "survey_marine_num_acrs", - "label": "Number of devices" - }, - { - "type": "text", - "name": "survey_marine_acr_placement", - "label": "Acoustic recorder Placement" - }, - { - "type": "text", - "name": "survey_marine_acr_situ", - "label": "How long in situ" - }, - { - "type": "text", - "name": "survey_marine_acr_other_details", - "label": "Other details" - } - ], - "isRepeatable": true, - "type": "group", - "name": "survey_marine_acoustic_call_recorder_information", - "label": "Acoustic recorder Information" - } - ] - }, - "type": "checkbox", - "name": "survey_marine_acoustic_recorder", - "label": "Acoustic recorder" - }, - { - "conditions": { - "on": [ - { - "children": [ - { - "type": "text", - "name": "survey_marine_aerial_make", - "label": "Make" - }, - { - "type": "number", - "name": "survey_marine_num_aerials", - "label": "Number of devices" - }, - { - "type": "text", - "name": "survey_marine_aerial_placement", - "label": "Aerial Placement" - }, - { - "type": "text", - "name": "survey_marine_aerial_situ", - "label": "How long in situ" - }, - { - "type": "text", - "name": "survey_marine_aerial_other_details", - "label": "Other details" - } - ], - "type": "group", - "name": "survey_marine_aerial_information", - "label": "Aerial Information" - } - ] - }, - "type": "checkbox", - "name": "survey_marine_aerial", - "label": "Aerial" - }, - { - "type": "text_area", - "name": "survey_marine_remote_sensing_other_details", - "label": "Provide any other details relating to remote sensing." - } - ] - }, - "options": [ - { - "value": "capture", - "label": "Capture" - }, - { - "value": "remote_sensing", - "label": "Remote Sensing" - }, - { - "value": "other", - "label": "Other non-capture" - } - ], - "type": "radiobuttons", - "name": "survey_marine_survey_method", - "label": "What survey method will you be using?" - } - ] - }, - "type": "checkbox", - "name": "survey_marine", - "label": "Marine" - }, - { - "conditions": { - "on": [ - { - "children": [ - { - "type": "text", - "name": "survey_tft_group_name", - "label": "Group name" - }, - { - "speciesType": "fauna", - "type": "species", - "name": "survey_tft_scientific_name", - "label": "Scientific or common name" - }, - { - "type": "text", - "name": "survey_tft_quantity", - "label": "Quantity" - }, - { - "type": "text", - "name": "survey_tft_fate", - "label": "Fate" - } - ], - "isRepeatable": true, - "type": "group", - "name": "survey_targeted_fauna", - "label": "Targeted Fauna Type" - }, - { - "conditions": { - "capture": [ - { - "conditions": { - "net": [ - { - "type": "number", - "name": "survey_targeted_num_net_sites", - "label": "What is the number of sites where nets will be used?" - }, - { - "type": "number", - "name": "survey_targeted_num_net_days", - "label": "How many days/nights will nets be used?" - }, - { - "type": "number", - "name": "survey_targeted_num_net_sessions", - "label": "How many sessions will nets be used?" - }, - { - "type": "number", - "name": "survey_targeted_num_nets_per_session", - "label": "Total number of nets per session?" - }, - { - "type": "number", - "name": "survey_targeted_max_num_nets_per_session_per_site", - "label": "Maximum total number of nets per site per session?" - }, - { - "type": "text_area", - "name": "survey_targeted_different_num_nets_per_session_or_site_explanation", - "label": "If the number of nets differs between sessions or sites then explain" - }, - { - "type": "label", - "name": "survey_targeted_nets", - "label": "Nets" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_targeted_sweep_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_targeted_sweep_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_targeted_num_sweeps", - "label": "Number of nets" - }, - { - "type": "text", - "name": "survey_targeted_sweep_placement", - "label": "Net Placement" - }, - { - "type": "text", - "name": "survey_targeted_sweep_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_targeted_sweep_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted_sweep", - "label": "Sweep" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_targeted_mist_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_targeted_mist_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_targeted_num_mists", - "label": "Number of nets" - }, - { - "type": "text", - "name": "survey_targeted_mist_placement", - "label": "Net Placement" - }, - { - "type": "text", - "name": "survey_targeted_mist_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_targeted_mist_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted_mist", - "label": "Mist" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_targeted_harp_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_targeted_harp_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_targeted_num_harps", - "label": "Number of nets" - }, - { - "type": "text", - "name": "survey_targeted_harp_placement", - "label": "Net Placement" - }, - { - "type": "text", - "name": "survey_targeted_harp_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_targeted_harp_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted_harp", - "label": "Harp" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_targeted_net_type_other", - "label": "Enter details" - }, - { - "type": "text", - "name": "survey_targeted_net_other_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_targeted_net_other_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_targeted_net_other_num_nets", - "label": "Number of nets" - }, - { - "type": "text", - "name": "survey_targeted_net_other_placement", - "label": "Net Placement" - }, - { - "type": "text", - "name": "survey_targeted_net_other_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_targeted_net_other_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted_net_other", - "label": "Other" - } - ], - "other": [ - { - "type": "text_area", - "name": "survey_targeted_other_capture_methodology", - "label": "Provide details of your fauna capture methodology if it doesn\u2019t fit within previous questions for trap, net or hand capture techniques." - } - ], - "trap": [ - { - "type": "number", - "name": "survey_targeted_num_trap_sites", - "label": "What is the number of trap sites?" - }, - { - "type": "number", - "name": "survey_targeted_num_traps_open_days", - "label": "How many days/nights will traps be open?" - }, - { - "type": "number", - "name": "survey_targeted_num_trap_sessions", - "label": "How many trapping sessions?" - }, - { - "type": "number", - "name": "survey_targeted_num_traps_per_session", - "label": "Total number of traps per session?" - }, - { - "type": "number", - "name": "survey_targeted_max_num_traps_per_session_per_site", - "label": "Maximum total number of traps per site per session?" - }, - { - "type": "text_area", - "name": "survey_targeted_different_num_traps_per_session_or_site_explanation", - "label": "If the number of traps differs between sessions or sites, enter the highest number in the questions above, and explain differences below." - }, - { - "type": "label", - "name": "survey_targeted_traps", - "label": "Traps" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_targeted_cage_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_targeted_cage_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_targeted_num_cages", - "label": "Number of traps" - }, - { - "type": "text", - "name": "survey_targeted_cage_placement", - "label": "Cage Placement" - }, - { - "type": "text", - "name": "survey_targeted_cage_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_targeted_cage_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted_cage", - "label": "Cage" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_targeted_box_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_targeted_box_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_targeted_num_boxs", - "label": "Number of traps" - }, - { - "type": "text", - "name": "survey_targeted_box_placement", - "label": "Box Placement" - }, - { - "type": "text", - "name": "survey_targeted_box_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_targeted_box_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted_box", - "label": "Box" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_targeted_dry_pit_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_targeted_dry_pit_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_targeted_num_dry_pits", - "label": "Number of traps" - }, - { - "type": "text", - "name": "survey_targeted_dry_pit_placement", - "label": "Dry Pit Placement" - }, - { - "type": "text", - "name": "survey_targeted_dry_pit_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_targeted_dry_pit_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted_dry_pit", - "label": "Dry Pit" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_targeted_funnel_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_targeted_funnel_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_targeted_num_funnels", - "label": "Number of traps" - }, - { - "type": "text", - "name": "survey_targeted_funnel_placement", - "label": "Funnel Placement" - }, - { - "type": "text", - "name": "survey_targeted_funnel_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_targeted_funnel_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted_funnel", - "label": "Funnel" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_targeted_trap_type_other", - "label": "Enter details" - }, - { - "type": "text", - "name": "survey_targeted_trap_other_make", - "label": "Make" - }, - { - "type": "text", - "name": "survey_targeted_trap_other_size", - "label": "Size" - }, - { - "type": "number", - "name": "survey_targeted_trap_other_num_traps", - "label": "Number of traps" - }, - { - "type": "text", - "name": "survey_targeted_trap_other_placement", - "label": "Trap Placement" - }, - { - "type": "text", - "name": "survey_targeted_trap_other_setting_times", - "label": "Setting times" - }, - { - "type": "text", - "name": "survey_targeted_trap_other_other_details", - "label": "Other details" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted_trap_other", - "label": "Other" - } - ], - "hand": [ - { - "type": "label", - "name": "survey_targeted_hand_capture_techniques", - "label": "What hand capture techniques will you be using?" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_targeted_hook_and_bag_details", - "label": "Please Provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted_hook_and_bag", - "label": "Hook and Bag" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_targeted_Noose_details", - "label": "Please Provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted_noose", - "label": "Noose" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_targeted_foraging_details", - "label": "Please Provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted_foraging", - "label": "Foraging" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_targeted_raking_details", - "label": "Please Provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted_raking", - "label": "Raking" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_targeted_sieving_details", - "label": "Please Provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted_sieving", - "label": "Sieving" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_targeted_excavation_details", - "label": "Please Provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted_excavation", - "label": "Excavation" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_targeted_excavation_details", - "label": "Please Provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted_other_hand_capture_techniques", - "label": "Other" - } - ] - }, - "options": [ - { - "value": "trap", - "label": "Trap" - }, - { - "value": "net", - "label": "Net" - }, - { - "value": "hand", - "label": "Hand" - }, - { - "value": "other", - "label": "Other" - } - ], - "type": "radiobuttons", - "name": "survey_targeted_capture_method", - "label": "Capture Method" - }, - { - "type": "label", - "name": "survey_targeted_fate", - "label": "What will be the fate(s) of the fauna captured?" - }, - { - "conditions": { - "on": [ - { - "options": [ - { - "value": "immediately", - "label": "Immediately after species idenfication" - }, - { - "value": "after_morphometrics", - "label": "After morphometrics and physical condition taken" - }, - { - "value": "after_samples", - "label": "After samples taken" - }, - { - "value": "after_marking", - "label": "After marking" - }, - { - "value": "after_temp_holding", - "label": "After temporary holding (< 24 hours)" - } - ], - "type": "select", - "name": "survey_targeted_release_schedule", - "label": "Release Schedule" - }, - { - "type": "label", - "name": "survey_targeted_pre_release_occurences", - "label": "Which of the following will occur before release?" - }, - { - "conditions": { - "on": [ - { - "type": "label", - "name": "survey_targeted_mophometrics_recorded", - "label": "What morphometrics and condition details will be recorded?" - }, - { - "type": "checkbox", - "name": "survey_targeted_mophometric_length", - "label": "Length" - }, - { - "type": "checkbox", - "name": "survey_targeted_mophometric_sex", - "label": "Sex" - }, - { - "type": "checkbox", - "name": "survey_targeted_mophometric_age", - "label": "Age" - }, - { - "type": "checkbox", - "name": "survey_targeted_mophometric_body_condition", - "label": "Body condition" - }, - { - "type": "checkbox", - "name": "survey_targeted_mophometric_reproductive_condition", - "label": "Reproductive condition" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_targeted_mophometric_other_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted_mophometric_other", - "label": "Other" - }, - { - "type": "text_area", - "name": "survey_targeted_mophometric_other_details", - "label": "Provide any other details relating to measurements and condition" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted_mophometrics", - "label": "Mophometrics and physical condition analysis" - }, - { - "conditions": { - "on": [ - { - "type": "label", - "name": "survey_targeted_samples", - "label": "What samples will be taken?" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_targeted_tissue_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted_tissue", - "label": "Tissue" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_targeted_scale_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted_scale", - "label": "Scale" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_targeted_hair_feather_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted_hair_feather", - "label": "Hair / feather" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_targeted_blood_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted_blood", - "label": "Blood" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_targeted_swabs_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted_swabs", - "label": "Swabs" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_targeted_samples_other_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted_samples_other", - "label": "Other" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted_sampling", - "label": "Sampling" - }, - { - "conditions": { - "on": [ - { - "conditions": { - "permanent": [ - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_targeted_tags_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted_tags", - "label": "Tags" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_targeted_microchips_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted_microchips", - "label": "Microchips / implants" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_targeted_bands_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted_bands", - "label": "Bands" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_targeted_ear_punching_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted_ear_punching", - "label": "Ear punching" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_targeted_marking_other_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted_marking_other", - "label": "Other" - } - ] - }, - "options": [ - { - "value": "temporary", - "label": "Temporary" - }, - { - "value": "permanent", - "label": "Permanent" - } - ], - "type": "select", - "name": "survey_targeted_marking", - "label": "What marking will be done and why?" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted_marking", - "label": "Marking" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_targeted_why_temporarily_held", - "label": "Why will/may the fauna be temporarily held?" - }, - { - "type": "text_area", - "name": "survey_targeted_how_temporarily_held", - "label": "How will the fauna be held?" - }, - { - "type": "text_area", - "name": "survey_targeted_where_temporarily_held", - "label": "Where will the fauna be held?" - }, - { - "type": "text_area", - "name": "survey_targeted_transported_details", - "label": "If fauna will be transported, provide details?" - }, - { - "conditions": { - "other": [ - { - "type": "text_area", - "name": "survey_targeted_fauna_release_other_details", - "label": "Please provide details" - } - ] - }, - "options": [ - { - "value": "at_capture_site", - "label": "At capture site" - }, - { - "value": "near_capture_site", - "label": "Near capture site into suitable habitat" - }, - { - "value": "other", - "label": "Other" - } - ], - "type": "select", - "name": "survey_targeted_where_fauna_released", - "label": "Where will the fauna be released?" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted_temporary_holding", - "label": "Temporary Holding" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted_release", - "label": "Release" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_targeted_why_fauna_retained", - "label": "Why does the fauna need to be retained?" - }, - { - "type": "text_area", - "name": "survey_targeted_what_fauna_retained", - "label": "What fauna could be retained?" - }, - { - "type": "number", - "name": "survey_targeted_num_fauna_retained", - "label": "If fauna is to be retained, how many animals?" - }, - { - "conditions": { - "yes": [ - { - "type": "text_area", - "name": "survey_targeted_euthanise_method", - "label": "Method" - } - ] - }, - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "survey_targeted_fauna_euthanised", - "label": "Will fauna be euthanised?" - }, - { - "type": "text", - "name": "survey_targeted_where_specimen_stored", - "label": "Where will the specimen(s) be held/lodged/stored?" - }, - { - "type": "text_area", - "name": "survey_targeted_mesuem_storage_details", - "label": "If specimen is to be deposited at the WA Museum, will the Museum be contacted prior to the fauna being retained or did the Museum request the specimen?" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted_retain", - "label": "Retain" - }, - { - "type": "text_area", - "name": "survey_targeted_prevent_vertebre_by_catch", - "label": "Describe measures that will be used to prevent/minimise vertebrate by-catch" - }, - { - "type": "text_area", - "name": "survey_targeted_hygiene_disease_considerations", - "label": "Provide details of field hygiene and wildlife disease considerations." - }, - { - "type": "text_area", - "name": "survey_targeted_fauna_capture_other_details", - "label": "Provide other details relating to fauna capture." - } - ], - "other": [ - { - "type": "label", - "name": "survey_targeted_non_capture_method", - "label": "Please select any non-capture survey method you will be using" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_targeted_aural_survey_details", - "label": "Please provide Details" - }, - { - "conditions": { - "yes": [ - { - "type": "text_area", - "name": "survey_targeted_call_playback_details", - "label": "Please provide Details" - } - ] - }, - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "survey_targeted_call_playback", - "label": "Will call play-back be used?" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted_aural_survey", - "label": "Aural survey" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_targeted_bird_census_details", - "label": "Please provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted_bird_census", - "label": "Bird Census" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_targeted_spotlighting_details", - "label": "Please provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted_spotlighting", - "label": "Spotlighting / head torching" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_targeted_hair_tubes_details", - "label": "Please provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted_hair_tubes", - "label": "Hair tubes / sticky wicket" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_targeted_secondary_signs_details", - "label": "Please provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted_secondary_signs", - "label": "Secondary signs / evidence" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_targeted_habitat_assessment_details", - "label": "Please provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted_habitat_assessment", - "label": "Habitat Assessment" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "survey_targeted_non_capture_other_details", - "label": "Please provide Details" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted_non_capture_other", - "label": "Other" - } - ], - "remote_sensing": [ - { - "type": "label", - "name": "survey_targeted_remote_sensing_apparatus", - "label": "What remote sensing apparatus will you be using?" - }, - { - "conditions": { - "on": [ - { - "conditions": { - "yes": [ - { - "type": "text", - "name": "survey_targeted_what_bait", - "label": "What bait will be used?" - }, - { - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "survey_targeted_bait_consumable", - "label": "Will the bait be consumable?" - }, - { - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "survey_targeted_bait_replenished", - "label": "Will the bait be replenished?" - } - ] - }, - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "survey_targeted_camera_baited", - "label": "Will cameras be baited with an attractant/lure?" - }, - { - "children": [ - { - "type": "text", - "name": "survey_targeted_camera_make", - "label": "Make" - }, - { - "type": "number", - "name": "survey_targeted_num_cameras", - "label": "Number of devices" - }, - { - "type": "text_area", - "name": "survey_targeted_camera_placement", - "label": "Camera Placement" - }, - { - "type": "text", - "name": "survey_targeted_camera_situ", - "label": "How long in situ" - }, - { - "type": "text", - "name": "survey_targeted_camera_other_details", - "label": "Other details" - } - ], - "isRepeatable": true, - "type": "group", - "name": "survey_targeted_camera_information", - "label": "Camera Information" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted_camera", - "label": "Camera" - }, - { - "conditions": { - "on": [ - { - "children": [ - { - "type": "text", - "name": "survey_targeted_ubd_make", - "label": "Make" - }, - { - "type": "number", - "name": "survey_targeted_num_ubds", - "label": "Number of devices" - }, - { - "type": "text", - "name": "survey_targeted_ubd_placement", - "label": "Ultrasonic bat detector Placement" - }, - { - "type": "text", - "name": "survey_targeted_ubd_situ", - "label": "How long in situ" - }, - { - "type": "text", - "name": "survey_targeted_ubd_other_details", - "label": "Other details" - } - ], - "isRepeatable": true, - "type": "group", - "name": "survey_targeted_ultrasonic_bat_detector_information", - "label": "Ultrasonic Bat Detector Information" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted_ultrasonic_bat_detector", - "label": "Ultrasonic bat detector" - }, - { - "conditions": { - "on": [ - { - "children": [ - { - "type": "text", - "name": "survey_targeted_acr_make", - "label": "Make" - }, - { - "type": "number", - "name": "survey_targeted_num_acrs", - "label": "Number of devices" - }, - { - "type": "text", - "name": "survey_targeted_acr_placement", - "label": "Acoustic call recorder Placement" - }, - { - "type": "text", - "name": "survey_targeted_acr_situ", - "label": "How long in situ" - }, - { - "type": "text", - "name": "survey_targeted_acr_other_details", - "label": "Other details" - } - ], - "isRepeatable": true, - "type": "group", - "name": "survey_targeted_acoustic_call_recorder_information", - "label": "Acoustic call recorder Information" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted_acoustic_call_recorder", - "label": "Acoustic call recorder" - }, - { - "conditions": { - "on": [ - { - "children": [ - { - "type": "text", - "name": "survey_targeted_aerial_make", - "label": "Make" - }, - { - "type": "number", - "name": "survey_targeted_num_aerials", - "label": "Number of devices" - }, - { - "type": "text", - "name": "survey_targeted_aerial_placement", - "label": "Aerial Placement" - }, - { - "type": "text", - "name": "survey_targeted_aerial_situ", - "label": "How long in situ" - }, - { - "type": "text", - "name": "survey_targeted_aerial_other_details", - "label": "Other details" - } - ], - "type": "group", - "name": "survey_targeted_aerial_information", - "label": "Aerial Information" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted_aerial", - "label": "Aerial" - }, - { - "type": "text_area", - "name": "survey_targeted_remote_sensing_other_details", - "label": "Provide any other details relating to remote sensing." - } - ] - }, - "options": [ - { - "value": "capture", - "label": "Capture" - }, - { - "value": "remote_sensing", - "label": "Remote Sensing" - }, - { - "value": "other", - "label": "Other non-capture" - } - ], - "type": "radiobuttons", - "name": "survey_targeted_survey_method", - "label": "What survey method will you be using?" - } - ] - }, - "type": "checkbox", - "name": "survey_targeted", - "label": "Targeted" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "survey_other_survey_type_details", - "label": "Provide details" - } - ] - }, - "type": "checkbox", - "name": "survey_other_survey_type", - "label": "Other" - } - ] - } - ], - "research": [ - { - "type": "label", - "name": "research_note_1", - "label": "Note: \u2018Research\u2019 as a licence project type should only be select if the proposed activity does not fit within the methodology for research or survey." - }, - { - "type": "label", - "name": "research_note_2", - "label": "Monitoring should be selected if your study includes capture-mark-recapture or fauna tracking. Usually with field sessions at regular or irregular intervals, and total project duration greater than 12 months." - }, - { - "type": "label", - "name": "research_note_2", - "label": "Survey should be selected if your study includes capture and release, for one or a few field sessions, and total project duration up to but not greater than 12 months." - }, - { - "conditions": { - "field_and_laboratory": [ - { - "type": "text_area", - "name": "research_lab_details", - "label": "Provide details of laboratory/facility" - }, - { - "type": "text_area", - "name": "research_animal_husbandry", - "label": "Provide specific details of animal husbandry" - }, - { - "type": "text_area", - "name": "research_fauna_activities", - "label": "Provide specific details of fauna related activities that are proposed to occur within the laboratory/facility" - }, - { - "type": "text_area", - "name": "research_fauna_hold_length", - "label": "How long will the fauna be held?" - }, - { - "conditions": { - "research_release_wild": [ - { - "type": "label", - "name": "research_fauna_release_details", - "label": "Provide details for the following" - }, - { - "type": "text_area", - "name": "research_fauna_release_risk_assessment", - "label": "Risk assessment (release of fauna back to the wild after being held and studied in a laboratory/facility poses a risk of disease/parasite introduction to the wild fauna)" - }, - { - "type": "text_area", - "name": "research_fauna_release_quarantine", - "label": "Quarantine and health check requirements prior to release" - }, - { - "type": "text_area", - "name": "research_fauna_release_site", - "label": "Proposed release site" - }, - { - "type": "text_area", - "name": "research_fauna_release_site_transportation", - "label": "Transportation to release site" - }, - { - "type": "text_area", - "name": "research_fauna_post_release_monitoring", - "label": "Post release monitoring" - } - ], - "research_euthanase": [ - { - "type": "label", - "name": "research_fauna_euthanasia_details", - "label": "Method of euthanasia" - }, - { - "conditions": { - "yes": [ - { - "type": "text_area", - "name": "research_fauna_stored", - "label": "Where will the specimen(s) be held/lodged/stored?" - } - ], - "no": [ - { - "type": "text_area", - "name": "research_fauna_disposal", - "label": "Provide details of disposal" - } - ] - }, - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "research_fauna_retained_specimen", - "label": "Will the fauna be retained as a specimen?" - } - ] - }, - "options": [ - { - "value": "research_transfer_alive", - "label": "Transfer alive to another project" - }, - { - "value": "research_release_wild", - "label": "Release to the wild" - }, - { - "value": "research_euthanase", - "label": "Euthanase" - } - ], - "type": "radiobuttons", - "name": "research_fauna_final_fate", - "label": "What is the final fate of fauna that has been in the laboratory/specialised facility?" - }, - { - "type": "text_area", - "name": "research_lab_other_details", - "label": "Provide any other details relating to the Laboratory/specialised facility component" - } - ] - }, - "options": [ - { - "value": "field_component_only", - "label": "Field component only" - }, - { - "value": "field_and_laboratory", - "label": "Field and laboratory/specialised facility components" - } - ], - "type": "radiobuttons", - "name": "research_type", - "label": "Which of the following describes your research?" - }, - { - "type": "number", - "name": "research_num_research_locations", - "label": "At how many locations will your research occur?" - }, - { - "name": "research_details", - "isRepeatable": true, - "help_text": "If multiple research locations; provide details separately for each location and add an additional location after activity questions.", - "label": "Monitoring Details", - "type": "group", - "children": [ - { - "type": "text_area", - "name": "research_address", - "label": "Location / Address" - }, - { - "type": "text", - "name": "research_coordinates", - "label": "Coordinate / GPS" - }, - { - "children": [ - { - "type": "date", - "name": "research_field_session_start_date", - "label": "Start Date" - }, - { - "type": "date", - "name": "research_field_session_end_date", - "label": "End Date" - } - ], - "isRepeatable": true, - "type": "group", - "name": "research_field_session", - "label": "Field session" - }, - { - "type": "text", - "name": "research_field_dates_unknown", - "label": "If field dates are unknown, use anticipated field dates in the start and end date above and explain below." - }, - { - "conditions": { - "on": [ - { - "children": [ - { - "type": "text", - "name": "research_tft_group_name", - "label": "Group name" - }, - { - "speciesType": "fauna", - "type": "species", - "name": "research_tft_scientific_name", - "label": "Scientific or common name" - } - ], - "isRepeatable": true, - "type": "group", - "name": "research_targeted_fauna", - "label": "Targeted Fauna Type" - } - ] - }, - "type": "checkbox", - "name": "research_targeting_species_or_fauna", - "label": "Is the research targeting species or fauna group?" - }, - { - "conditions": { - "yes": [ - { - "children": [ - { - "type": "text", - "name": "research_threatened_group_name", - "label": "Group name" - }, - { - "speciesType": "fauna", - "type": "species", - "name": "research_threatened_scientific_name", - "label": "Scientific or common name" - } - ], - "isRepeatable": true, - "type": "group", - "name": "research_threatened_fauna", - "label": "Threatened Fauna" - } - ] - }, - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - }, - { - "value": "unknown", - "label": "Unknown" - } - ], - "type": "radiobuttons", - "name": "research_threatened_priority_fauna", - "label": "Will your activity possibly interact with any threatened or priority fauna (including non-target species)?" - }, - { - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "research_standard_operating_procedures", - "label": "Will your activities be in accordance with Parks and Wildlife standard operating procedures?" - }, - { - "conditions": { - "yes": [ - { - "type": "text", - "name": "research_sops_details", - "label": "Provide details" - }, - { - "type": "file", - "name": "research_sops_documents", - "label": "Attach a copy of the relevent document(s)" - } - ] - }, - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "research_sops", - "label": "Will your activities be in accordance with any other SOPs, protocols, guidelines or manuals?" - }, - { - "type": "label", - "name": "research_field_component", - "label": "Field component" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "research_non_capture_details", - "label": "Provide specific details of non-capture methodology" - } - ] - }, - "type": "checkbox", - "name": "research_non_capture", - "label": "Non-capture" - }, - { - "conditions": { - "on": [ - { - "type": "text", - "name": "research_capture_details", - "label": "Provide specific details of capture methodology" - } - ] - }, - "type": "checkbox", - "name": "research_capture", - "label": "Capture" - }, - { - "type": "label", - "name": "research_fate", - "label": "What will be the fate(s) of the fauna captured?" - }, - { - "conditions": { - "on": [ - { - "options": [ - { - "value": "immediately", - "label": "Immediately after species idenfication" - }, - { - "value": "after_transmitter_attachment", - "label": "After attachment of transmitter" - }, - { - "value": "after_morphometrics", - "label": "After morphometrics and physical condition taken" - }, - { - "value": "after_samples", - "label": "After samples taken" - }, - { - "value": "after_marking", - "label": "After marking" - }, - { - "value": "after_temp_holding", - "label": "After temporary holding (< 24 hours)" - } - ], - "type": "select", - "name": "research_release_schedule", - "label": "Release Schedule" - }, - { - "type": "label", - "name": "research_pre_release_occurences", - "label": "Which of the following will occur before release?" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "research_prerelease_transmitter_type", - "label": "Transmitter type, make and model, and construction material" - }, - { - "type": "text_area", - "name": "research_prerelease_method_attachment", - "label": "Method of attachment to animal" - }, - { - "type": "text", - "name": "research_prerelease_transmitter_max_weight", - "label": "Maximum weight of transmitter and attachment materials" - }, - { - "type": "text", - "name": "research_prerelease_mim_body_weight", - "label": "Minimum body weight of animal to which transmitter will be attached" - }, - { - "type": "text", - "name": "research_prerelease_transmitter_attachment_length", - "label": "How long will the transmitter remain attached to the animal?" - }, - { - "conditions": { - "yes": [ - { - "type": "declaration", - "name": "research_prerelease_acknowledge", - "label": "I acknowledge that every attempt will be made to recapture the animal to remove the transmitter, and will notify Wildlife Licensing if this cannot be done." - } - ], - "no": [ - { - "type": "text_area", - "name": "research_prerelease_detach_details", - "label": "Provide details of how the transmitter will detach from the animal" - } - ] - }, - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "research_prerelease_recapture_remove", - "label": "Does the animal need to be recaptured to remove the transmitter?" - } - ] - }, - "type": "checkbox", - "name": "research_release_transmitter", - "label": "Attachment of transmitter" - }, - { - "conditions": { - "on": [ - { - "type": "label", - "name": "research_mophometrics_recorded", - "label": "What morphometrics and condition details will be recorded?" - }, - { - "type": "checkbox", - "name": "research_mophometric_length", - "label": "Length" - }, - { - "type": "checkbox", - "name": "research_mophometric_sex", - "label": "Sex" - }, - { - "type": "checkbox", - "name": "research_mophometric_age", - "label": "Age" - }, - { - "type": "checkbox", - "name": "research_mophometric_body_condition", - "label": "Body condition" - }, - { - "type": "checkbox", - "name": "research_mophometric_reproductive_condition", - "label": "Reproductive condition" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "research_mophometric_other_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "research_mophometric_other", - "label": "Other" - }, - { - "type": "text_area", - "name": "research_mophometric_other_details", - "label": "Provide any other details relating to measurements and condition" - } - ] - }, - "type": "checkbox", - "name": "research_mophometrics", - "label": "Mophometrics and physical condition analysis" - }, - { - "conditions": { - "on": [ - { - "type": "label", - "name": "research_samples", - "label": "What samples will be taken?" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "research_tissue_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "research_tissue", - "label": "Tissue" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "research_scale_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "research_scale", - "label": "Scale" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "research_hair_feather_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "research_hair_feather", - "label": "Hair / feather" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "research_blood_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "research_blood", - "label": "Blood" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "research_swabs_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "research_swabs", - "label": "Swabs" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "research_samples_other_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "research_samples_other", - "label": "Other" - } - ] - }, - "type": "checkbox", - "name": "research_sampling", - "label": "Sampling" - }, - { - "conditions": { - "on": [ - { - "conditions": { - "permanent": [ - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "research_tags_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "research_tags", - "label": "Tags" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "research_microchips_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "research_microchips", - "label": "Microchips / implants" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "research_bands_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "research_bands", - "label": "Bands" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "research_ear_punching_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "research_ear_punching", - "label": "Ear punching" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "research_marking_other_details", - "label": "Please provide details" - } - ] - }, - "type": "checkbox", - "name": "research_marking_other", - "label": "Other" - } - ] - }, - "options": [ - { - "value": "temporary", - "label": "Temporary" - }, - { - "value": "permanent", - "label": "Permanent" - } - ], - "type": "select", - "name": "research_marking", - "label": "What marking will be done and why?" - } - ] - }, - "type": "checkbox", - "name": "research_marking", - "label": "Marking" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "research_why_temporarily_held", - "label": "Why will/may the fauna be temporarily held?" - }, - { - "type": "text_area", - "name": "research_how_temporarily_held", - "label": "How will the fauna be held?" - }, - { - "type": "text_area", - "name": "research_where_temporarily_held", - "label": "Where will the fauna be held?" - }, - { - "type": "text_area", - "name": "research_transported_details", - "label": "If fauna will be transported, provide details?" - }, - { - "conditions": { - "other": [ - { - "type": "text_area", - "name": "research_fauna_release_other_details", - "label": "Please provide details" - }, - { - "conditions": { - "yes": [ - { - "type": "text_area", - "name": "research_transportation_details", - "label": "Provide details of transportation" - } - ], - "no": [ - { - "type": "text_area", - "name": "research_euthanasia_details", - "label": "Provide details on euthanasia" - } - ] - }, - "options": [ - { - "value": "yes", - "label": "Yes" - }, - { - "value": "no", - "label": "No" - } - ], - "type": "radiobuttons", - "name": "research_retained_alived", - "label": "Will fauna will be retained alive for study in laboratory/specialised facility?" - }, - { - "type": "text", - "name": "research_where_specimen_stored", - "label": "Where will the specimen(s) be held/lodged/stored?" - }, - { - "type": "text_area", - "name": "research_unforseen_injury_dealings", - "label": "Describe how unforeseen injuries or other related issues will be dealt with." - }, - { - "type": "text_area", - "name": "research_hygiene_disease_considerations", - "label": "Provide details of field hygiene and wildlife disease considerations." - }, - { - "type": "text_area", - "name": "research_fauna_capture_other_details", - "label": "Provide other details relating to fauna capture." - } - ] - }, - "options": [ - { - "value": "at_capture_site", - "label": "At capture site" - }, - { - "value": "near_capture_site", - "label": "Near capture site into suitable habitat" - }, - { - "value": "other", - "label": "Other" - } - ], - "type": "select", - "name": "research_where_fauna_released", - "label": "Where will the fauna be released?" - } - ] - }, - "type": "checkbox", - "name": "research_temporary_holding", - "label": "Temporary Holding" - } - ] - }, - "type": "checkbox", - "name": "research_release", - "label": "Release" - }, - { - "conditions": { - "on": [ - { - "type": "text_area", - "name": "research_species_retained", - "label": "Provide details on what species and how many individuals (per species) are to be retained" - } - ] - }, - "type": "checkbox", - "name": "research_retain", - "label": "Retain" - } - ] - } - ] - }, - "options": [ - { - "value": "survey", - "label": "Survey" - }, - { - "value": "monitoring", - "label": "Monitoring" - }, - { - "value": "research", - "label": "Research" - } - ], - "defaultBlank": true - } - ], - "type": "section", - "name": "project_description", - "label": "Project Description" - } -] diff --git a/commercialoperator/frontend/commercialoperator/src/assets/logo.png b/commercialoperator/frontend/commercialoperator/src/assets/logo.png deleted file mode 100755 index f3d2503fc2..0000000000 Binary files a/commercialoperator/frontend/commercialoperator/src/assets/logo.png and /dev/null differ diff --git a/commercialoperator/frontend/commercialoperator/src/components/Hello.vue b/commercialoperator/frontend/commercialoperator/src/components/Hello.vue deleted file mode 100755 index 2d8053956d..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/Hello.vue +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/add_comm_log.vue b/commercialoperator/frontend/commercialoperator/src/components/common/add_comm_log.vue deleted file mode 100755 index c82a70411f..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/add_comm_log.vue +++ /dev/null @@ -1,294 +0,0 @@ - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/add_contact.vue b/commercialoperator/frontend/commercialoperator/src/components/common/add_contact.vue deleted file mode 100755 index 545de64c37..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/add_contact.vue +++ /dev/null @@ -1,210 +0,0 @@ - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/approvals_dashboard.vue b/commercialoperator/frontend/commercialoperator/src/components/common/approvals_dashboard.vue deleted file mode 100755 index 4d7998dce4..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/approvals_dashboard.vue +++ /dev/null @@ -1,805 +0,0 @@ - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/blank_template.vue b/commercialoperator/frontend/commercialoperator/src/components/common/blank_template.vue deleted file mode 100755 index 0190575b7c..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/blank_template.vue +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/comms_logs.vue b/commercialoperator/frontend/commercialoperator/src/components/common/comms_logs.vue deleted file mode 100755 index 89441bd457..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/comms_logs.vue +++ /dev/null @@ -1,457 +0,0 @@ - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/compliances_dashboard.vue b/commercialoperator/frontend/commercialoperator/src/components/common/compliances_dashboard.vue deleted file mode 100755 index cec14ab5f3..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/compliances_dashboard.vue +++ /dev/null @@ -1,381 +0,0 @@ - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/edit_vehicle.vue b/commercialoperator/frontend/commercialoperator/src/components/common/edit_vehicle.vue deleted file mode 100644 index e753915c9d..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/edit_vehicle.vue +++ /dev/null @@ -1,361 +0,0 @@ - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/edit_vessel.vue b/commercialoperator/frontend/commercialoperator/src/components/common/edit_vessel.vue deleted file mode 100644 index eb8e2990ef..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/edit_vessel.vue +++ /dev/null @@ -1,323 +0,0 @@ - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/event/activities.vue b/commercialoperator/frontend/commercialoperator/src/components/common/event/activities.vue deleted file mode 100755 index 8fed9c237a..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/event/activities.vue +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/event/applicant.vue b/commercialoperator/frontend/commercialoperator/src/components/common/event/applicant.vue deleted file mode 100755 index fd8a38f114..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/event/applicant.vue +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/event/confirmation.vue b/commercialoperator/frontend/commercialoperator/src/components/common/event/confirmation.vue deleted file mode 100755 index 1336563be8..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/event/confirmation.vue +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/event/event_management.vue b/commercialoperator/frontend/commercialoperator/src/components/common/event/event_management.vue deleted file mode 100755 index cdcb6f6062..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/event/event_management.vue +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/event/online_training.vue b/commercialoperator/frontend/commercialoperator/src/components/common/event/online_training.vue deleted file mode 100755 index b0194bab84..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/event/online_training.vue +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/event/other_details.vue b/commercialoperator/frontend/commercialoperator/src/components/common/event/other_details.vue deleted file mode 100755 index c44dfd57f0..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/event/other_details.vue +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/event/payment.vue b/commercialoperator/frontend/commercialoperator/src/components/common/event/payment.vue deleted file mode 100755 index cc716bb82f..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/event/payment.vue +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/event/vehicles_vessels.vue b/commercialoperator/frontend/commercialoperator/src/components/common/event/vehicles_vessels.vue deleted file mode 100755 index 3b480f956f..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/event/vehicles_vessels.vue +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/filming/access.vue b/commercialoperator/frontend/commercialoperator/src/components/common/filming/access.vue deleted file mode 100755 index c4e71918d8..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/filming/access.vue +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/filming/activity.vue b/commercialoperator/frontend/commercialoperator/src/components/common/filming/activity.vue deleted file mode 100755 index 25cc9cc40a..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/filming/activity.vue +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/filming/applicant.vue b/commercialoperator/frontend/commercialoperator/src/components/common/filming/applicant.vue deleted file mode 100755 index fd8a38f114..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/filming/applicant.vue +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/filming/confirmation.vue b/commercialoperator/frontend/commercialoperator/src/components/common/filming/confirmation.vue deleted file mode 100755 index 1336563be8..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/filming/confirmation.vue +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/filming/equipment.vue b/commercialoperator/frontend/commercialoperator/src/components/common/filming/equipment.vue deleted file mode 100755 index 13da819f69..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/filming/equipment.vue +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/filming/online_training.vue b/commercialoperator/frontend/commercialoperator/src/components/common/filming/online_training.vue deleted file mode 100755 index b0194bab84..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/filming/online_training.vue +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/filming/other_details.vue b/commercialoperator/frontend/commercialoperator/src/components/common/filming/other_details.vue deleted file mode 100755 index c44dfd57f0..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/filming/other_details.vue +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/filming/payment.vue b/commercialoperator/frontend/commercialoperator/src/components/common/filming/payment.vue deleted file mode 100755 index cc716bb82f..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/filming/payment.vue +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/more_referrals.vue b/commercialoperator/frontend/commercialoperator/src/components/common/more_referrals.vue deleted file mode 100755 index 931cbdc52a..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/more_referrals.vue +++ /dev/null @@ -1,285 +0,0 @@ - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/payments_dashboard.vue b/commercialoperator/frontend/commercialoperator/src/components/common/payments_dashboard.vue deleted file mode 100755 index 8cc54741f4..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/payments_dashboard.vue +++ /dev/null @@ -1,540 +0,0 @@ - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/proposals_dashboard.vue b/commercialoperator/frontend/commercialoperator/src/components/common/proposals_dashboard.vue deleted file mode 100755 index 2a45af06ca..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/proposals_dashboard.vue +++ /dev/null @@ -1,648 +0,0 @@ - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/qaofficer_dashboard.vue b/commercialoperator/frontend/commercialoperator/src/components/common/qaofficer_dashboard.vue deleted file mode 100755 index 69abcfd822..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/qaofficer_dashboard.vue +++ /dev/null @@ -1,487 +0,0 @@ - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/referrals_dashboard.vue b/commercialoperator/frontend/commercialoperator/src/components/common/referrals_dashboard.vue deleted file mode 100755 index 9fce4cd9d9..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/referrals_dashboard.vue +++ /dev/null @@ -1,375 +0,0 @@ - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/tclass/accreditation_type.vue b/commercialoperator/frontend/commercialoperator/src/components/common/tclass/accreditation_type.vue deleted file mode 100644 index c4b27ce38b..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/tclass/accreditation_type.vue +++ /dev/null @@ -1,133 +0,0 @@ - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/tclass/activities_land.vue b/commercialoperator/frontend/commercialoperator/src/components/common/tclass/activities_land.vue deleted file mode 100755 index fee530f947..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/tclass/activities_land.vue +++ /dev/null @@ -1,887 +0,0 @@ - - - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/tclass/activities_land_orig.vue b/commercialoperator/frontend/commercialoperator/src/components/common/tclass/activities_land_orig.vue deleted file mode 100755 index ca55d70bb4..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/tclass/activities_land_orig.vue +++ /dev/null @@ -1,1134 +0,0 @@ - - - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/tclass/activities_marine.vue b/commercialoperator/frontend/commercialoperator/src/components/common/tclass/activities_marine.vue deleted file mode 100755 index 1259c995b7..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/tclass/activities_marine.vue +++ /dev/null @@ -1,625 +0,0 @@ - - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/tclass/activities_marine_orig.vue b/commercialoperator/frontend/commercialoperator/src/components/common/tclass/activities_marine_orig.vue deleted file mode 100755 index 7565efb6b9..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/tclass/activities_marine_orig.vue +++ /dev/null @@ -1,505 +0,0 @@ - - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/tclass/applicant.vue b/commercialoperator/frontend/commercialoperator/src/components/common/tclass/applicant.vue deleted file mode 100755 index a8a383d800..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/tclass/applicant.vue +++ /dev/null @@ -1,285 +0,0 @@ - - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/tclass/assessment.vue b/commercialoperator/frontend/commercialoperator/src/components/common/tclass/assessment.vue deleted file mode 100644 index c77e17a89e..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/tclass/assessment.vue +++ /dev/null @@ -1,143 +0,0 @@ - - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/tclass/confirmation.vue b/commercialoperator/frontend/commercialoperator/src/components/common/tclass/confirmation.vue deleted file mode 100755 index fbfd9d47ee..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/tclass/confirmation.vue +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/tclass/edit_marine_park_activities.vue b/commercialoperator/frontend/commercialoperator/src/components/common/tclass/edit_marine_park_activities.vue deleted file mode 100644 index 60ae700b25..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/tclass/edit_marine_park_activities.vue +++ /dev/null @@ -1,172 +0,0 @@ - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/tclass/edit_park_activities.vue b/commercialoperator/frontend/commercialoperator/src/components/common/tclass/edit_park_activities.vue deleted file mode 100644 index 4527ca975c..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/tclass/edit_park_activities.vue +++ /dev/null @@ -1,213 +0,0 @@ - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/tclass/edit_trail_activities.vue b/commercialoperator/frontend/commercialoperator/src/components/common/tclass/edit_trail_activities.vue deleted file mode 100644 index 2049d306fa..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/tclass/edit_trail_activities.vue +++ /dev/null @@ -1,211 +0,0 @@ - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/tclass/online_training.vue b/commercialoperator/frontend/commercialoperator/src/components/common/tclass/online_training.vue deleted file mode 100755 index 56d9b1f35b..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/tclass/online_training.vue +++ /dev/null @@ -1,229 +0,0 @@ - - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/tclass/order_table.vue b/commercialoperator/frontend/commercialoperator/src/components/common/tclass/order_table.vue deleted file mode 100644 index 38cdf892d1..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/tclass/order_table.vue +++ /dev/null @@ -1,362 +0,0 @@ - - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/tclass/other_details.vue b/commercialoperator/frontend/commercialoperator/src/components/common/tclass/other_details.vue deleted file mode 100644 index 7798f01684..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/tclass/other_details.vue +++ /dev/null @@ -1,679 +0,0 @@ - - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/tclass/payment_order.vue b/commercialoperator/frontend/commercialoperator/src/components/common/tclass/payment_order.vue deleted file mode 100755 index e83213deb5..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/tclass/payment_order.vue +++ /dev/null @@ -1,304 +0,0 @@ - - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/tclass/required_docs.vue b/commercialoperator/frontend/commercialoperator/src/components/common/tclass/required_docs.vue deleted file mode 100644 index 0f75912b45..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/tclass/required_docs.vue +++ /dev/null @@ -1,276 +0,0 @@ - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/vehicle_table.vue b/commercialoperator/frontend/commercialoperator/src/components/common/vehicle_table.vue deleted file mode 100644 index a8dca8c596..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/vehicle_table.vue +++ /dev/null @@ -1,325 +0,0 @@ - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/common/vessel_table.vue b/commercialoperator/frontend/commercialoperator/src/components/common/vessel_table.vue deleted file mode 100644 index dd5aee84a3..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/common/vessel_table.vue +++ /dev/null @@ -1,242 +0,0 @@ - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/external/api.js b/commercialoperator/frontend/commercialoperator/src/components/external/api.js deleted file mode 100755 index e777851f60..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/external/api.js +++ /dev/null @@ -1,8 +0,0 @@ -module.exports = { - proposals: '/api/proposal.json', - profile: '/api/profile', - countries: 'https://restcountries.eu/rest/v1/?fullText=true', - organisations: '/api/organisations.json', - organisation_contacts: '/api/organisation_contacts.json', - my_organisations: '/api/my_organisations', -} diff --git a/commercialoperator/frontend/commercialoperator/src/components/external/approvals/approval.vue b/commercialoperator/frontend/commercialoperator/src/components/external/approvals/approval.vue deleted file mode 100755 index 67bc6922eb..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/external/approvals/approval.vue +++ /dev/null @@ -1,279 +0,0 @@ - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/external/compliances/access.vue b/commercialoperator/frontend/commercialoperator/src/components/external/compliances/access.vue deleted file mode 100755 index a72f0877d4..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/external/compliances/access.vue +++ /dev/null @@ -1,418 +0,0 @@ - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/external/compliances/submit.vue b/commercialoperator/frontend/commercialoperator/src/components/external/compliances/submit.vue deleted file mode 100755 index 932c10d0b2..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/external/compliances/submit.vue +++ /dev/null @@ -1,80 +0,0 @@ - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/external/dashboard.vue b/commercialoperator/frontend/commercialoperator/src/components/external/dashboard.vue deleted file mode 100755 index 8bd7c99ead..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/external/dashboard.vue +++ /dev/null @@ -1,58 +0,0 @@ - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/external/organisations/manage.vue b/commercialoperator/frontend/commercialoperator/src/components/external/organisations/manage.vue deleted file mode 100755 index 8193b5cf2a..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/external/organisations/manage.vue +++ /dev/null @@ -1,1053 +0,0 @@ - - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/external/proposal.vue b/commercialoperator/frontend/commercialoperator/src/components/external/proposal.vue deleted file mode 100755 index 12feea624d..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/external/proposal.vue +++ /dev/null @@ -1,583 +0,0 @@ - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/external/proposal_apply.vue b/commercialoperator/frontend/commercialoperator/src/components/external/proposal_apply.vue deleted file mode 100644 index 6d4329204b..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/external/proposal_apply.vue +++ /dev/null @@ -1,639 +0,0 @@ - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/external/proposal_submit.vue b/commercialoperator/frontend/commercialoperator/src/components/external/proposal_submit.vue deleted file mode 100755 index ab9dd84352..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/external/proposal_submit.vue +++ /dev/null @@ -1,80 +0,0 @@ - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/external/routes/index.js b/commercialoperator/frontend/commercialoperator/src/components/external/routes/index.js deleted file mode 100755 index 0e0b93b7d6..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/external/routes/index.js +++ /dev/null @@ -1,88 +0,0 @@ -import ExternalDashboard from '../dashboard.vue' -import Proposal from '../proposal.vue' -//import CommercialOperatorLicence from '../commercial_operator_licence.vue' -import ProposalApply from '../proposal_apply.vue' -import ProposalSubmit from '../proposal_submit.vue' -import Organisation from '../organisations/manage.vue' -import Compliance from '../compliances/access.vue' -import ComplianceSubmit from '../compliances/submit.vue' -import Approval from '../approvals/approval.vue' -import PaymentOrder from '@/components/common/tclass/payment_order.vue' -import PaymentDash from '@/components/common/payments_dashboard.vue' -export default -{ - path: '/external', - component: - { - render(c) - { - return c('router-view') - } - }, - children: [ - { - path: '/', - component: ExternalDashboard, - name: 'external-proposals-dash' - }, - { - path: 'organisations/manage/:org_id', - component: Organisation - }, - { - path: 'compliance/:compliance_id', - component: Compliance - }, - { - path: 'compliance/submit', - component: ComplianceSubmit, - name:"submit_compliance" - }, - { - path: 'approval/:approval_id', - component: Approval, - }, - { - path: 'payment', - component: PaymentDash, - props: { level: 'external' } - }, - { - path: 'payment_order', - component: PaymentOrder, - name:"payment_order" - }, - { - path: 'proposal', - component: - { - render(c) - { - return c('router-view') - } - }, - children: [ - { - path: '/', - component: ProposalApply, - name:"apply_proposal" - }, - { - path: 'submit', - component: ProposalSubmit, - name:"submit_proposal" - }, - { - path: ':proposal_id', - component: Proposal, - name:"draft_proposal" - }, - //{ - // path: ':proposal_id', - // component: CommercialOperatorLicence, - // name:"draft_commercial_operator_licence" - //}, - ] - } - ] -} diff --git a/commercialoperator/frontend/commercialoperator/src/components/external/utils.js b/commercialoperator/frontend/commercialoperator/src/components/external/utils.js deleted file mode 100755 index 070670aa79..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/external/utils.js +++ /dev/null @@ -1,58 +0,0 @@ -import Vue from 'vue' -import api from './api' -import {helpers} from '@/utils/hooks' - -export default { - fetchProfile: function (){ - return new Promise ((resolve,reject) => { - Vue.http.get(api.profile).then((response) => { - resolve(response.body); - }, - (error) => { - reject(error); - }); - }); - - }, - fetchProposal: function(id){ - return new Promise ((resolve,reject) => { - Vue.http.get(helpers.add_endpoint_json(api.proposals,id)).then((response) => { - resolve(response.body); - }, - (error) => { - reject(error); - }); - }); - }, - fetchCountries: function (){ - return new Promise ((resolve,reject) => { - Vue.http.get(api.countries).then((response) => { - resolve(response.body); - }, - (error) => { - reject(error); - }); - }); - - }, - fetchOrganisationPermissions: function(id){ - return new Promise ((resolve,reject) => { - Vue.http.get(helpers.add_endpoint_json(api.my_organisations,id)).then((response) => { - resolve(response.body); - }, - (error) => { - reject(error); - }); - }); - }, - fetchOrganisation: function(id){ - return new Promise ((resolve,reject) => { - Vue.http.get(helpers.add_endpoint_json(api.organisations,id)).then((response) => { - resolve(response.body); - }, - (error) => { - reject(error); - }); - }); - }, -} diff --git a/commercialoperator/frontend/commercialoperator/src/components/form.vue b/commercialoperator/frontend/commercialoperator/src/components/form.vue deleted file mode 100755 index 98e5e69d06..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/form.vue +++ /dev/null @@ -1,133 +0,0 @@ - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/form_event.vue b/commercialoperator/frontend/commercialoperator/src/components/form_event.vue deleted file mode 100755 index 07dd7ac672..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/form_event.vue +++ /dev/null @@ -1,171 +0,0 @@ - - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/form_filming.vue b/commercialoperator/frontend/commercialoperator/src/components/form_filming.vue deleted file mode 100755 index 45b71505a4..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/form_filming.vue +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/form_tclass.vue b/commercialoperator/frontend/commercialoperator/src/components/form_tclass.vue deleted file mode 100755 index 76e8b908c5..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/form_tclass.vue +++ /dev/null @@ -1,279 +0,0 @@ - - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/forms/Form.vue b/commercialoperator/frontend/commercialoperator/src/components/forms/Form.vue deleted file mode 100755 index 9f229d126c..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/forms/Form.vue +++ /dev/null @@ -1,52 +0,0 @@ - diff --git a/commercialoperator/frontend/commercialoperator/src/components/forms/checkbox.vue b/commercialoperator/frontend/commercialoperator/src/components/forms/checkbox.vue deleted file mode 100755 index 020c490c65..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/forms/checkbox.vue +++ /dev/null @@ -1,65 +0,0 @@ - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/forms/comment.vue b/commercialoperator/frontend/commercialoperator/src/components/forms/comment.vue deleted file mode 100755 index 0c4851af09..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/forms/comment.vue +++ /dev/null @@ -1,26 +0,0 @@ - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/forms/comment_icon_checkbox_radio.vue b/commercialoperator/frontend/commercialoperator/src/components/forms/comment_icon_checkbox_radio.vue deleted file mode 100755 index c50a853c62..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/forms/comment_icon_checkbox_radio.vue +++ /dev/null @@ -1,30 +0,0 @@ - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/forms/conditions.vue b/commercialoperator/frontend/commercialoperator/src/components/forms/conditions.vue deleted file mode 100755 index eec31495fc..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/forms/conditions.vue +++ /dev/null @@ -1,37 +0,0 @@ - diff --git a/commercialoperator/frontend/commercialoperator/src/components/forms/date-field.vue b/commercialoperator/frontend/commercialoperator/src/components/forms/date-field.vue deleted file mode 100755 index d64a8217b7..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/forms/date-field.vue +++ /dev/null @@ -1,79 +0,0 @@ - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/forms/declarations.vue b/commercialoperator/frontend/commercialoperator/src/components/forms/declarations.vue deleted file mode 100755 index 3f36ea1492..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/forms/declarations.vue +++ /dev/null @@ -1,40 +0,0 @@ - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/forms/file.vue b/commercialoperator/frontend/commercialoperator/src/components/forms/file.vue deleted file mode 100755 index 3e126c5e8d..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/forms/file.vue +++ /dev/null @@ -1,279 +0,0 @@ - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/forms/filefield.vue b/commercialoperator/frontend/commercialoperator/src/components/forms/filefield.vue deleted file mode 100644 index 2b495e7e76..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/forms/filefield.vue +++ /dev/null @@ -1,279 +0,0 @@ - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/forms/filefield2.vue b/commercialoperator/frontend/commercialoperator/src/components/forms/filefield2.vue deleted file mode 100755 index 2b00febe6d..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/forms/filefield2.vue +++ /dev/null @@ -1,263 +0,0 @@ - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/forms/group.vue b/commercialoperator/frontend/commercialoperator/src/components/forms/group.vue deleted file mode 100755 index e669e9fe0b..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/forms/group.vue +++ /dev/null @@ -1,62 +0,0 @@ - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/forms/help_text.vue b/commercialoperator/frontend/commercialoperator/src/components/forms/help_text.vue deleted file mode 100755 index 2aa48c545d..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/forms/help_text.vue +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/forms/help_text_display.vue b/commercialoperator/frontend/commercialoperator/src/components/forms/help_text_display.vue deleted file mode 100755 index 68a095dcee..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/forms/help_text_display.vue +++ /dev/null @@ -1,23 +0,0 @@ - - - - - diff --git a/commercialoperator/frontend/commercialoperator/src/components/forms/help_text_url.vue b/commercialoperator/frontend/commercialoperator/src/components/forms/help_text_url.vue deleted file mode 100755 index 4eb697b24f..0000000000 --- a/commercialoperator/frontend/commercialoperator/src/components/forms/help_text_url.vue +++ /dev/null @@ -1,25 +0,0 @@ - - - - - diff --git a/disturbance/frontend/disturbance/src/components/forms/label.vue b/disturbance/frontend/disturbance/src/components/forms/label.vue deleted file mode 100755 index 561da5cb18..0000000000 --- a/disturbance/frontend/disturbance/src/components/forms/label.vue +++ /dev/null @@ -1,14 +0,0 @@ - - - - - diff --git a/disturbance/frontend/disturbance/src/components/forms/radio.vue b/disturbance/frontend/disturbance/src/components/forms/radio.vue deleted file mode 100755 index de096992e5..0000000000 --- a/disturbance/frontend/disturbance/src/components/forms/radio.vue +++ /dev/null @@ -1,57 +0,0 @@ - - - - - diff --git a/disturbance/frontend/disturbance/src/components/forms/readonly_file.vue b/disturbance/frontend/disturbance/src/components/forms/readonly_file.vue deleted file mode 100755 index 92703620cb..0000000000 --- a/disturbance/frontend/disturbance/src/components/forms/readonly_file.vue +++ /dev/null @@ -1,15 +0,0 @@ - - - - - diff --git a/disturbance/frontend/disturbance/src/components/forms/readonly_text.vue b/disturbance/frontend/disturbance/src/components/forms/readonly_text.vue deleted file mode 100755 index 2227bcf57d..0000000000 --- a/disturbance/frontend/disturbance/src/components/forms/readonly_text.vue +++ /dev/null @@ -1,21 +0,0 @@ - - - - - diff --git a/disturbance/frontend/disturbance/src/components/forms/section.vue b/disturbance/frontend/disturbance/src/components/forms/section.vue deleted file mode 100755 index a050b0a66a..0000000000 --- a/disturbance/frontend/disturbance/src/components/forms/section.vue +++ /dev/null @@ -1,54 +0,0 @@ - - - - - diff --git a/disturbance/frontend/disturbance/src/components/forms/select-conditions.vue b/disturbance/frontend/disturbance/src/components/forms/select-conditions.vue deleted file mode 100755 index e68231f915..0000000000 --- a/disturbance/frontend/disturbance/src/components/forms/select-conditions.vue +++ /dev/null @@ -1,39 +0,0 @@ - diff --git a/disturbance/frontend/disturbance/src/components/forms/select.vue b/disturbance/frontend/disturbance/src/components/forms/select.vue deleted file mode 100755 index cce6b2aa05..0000000000 --- a/disturbance/frontend/disturbance/src/components/forms/select.vue +++ /dev/null @@ -1,175 +0,0 @@ - - - - - diff --git a/disturbance/frontend/disturbance/src/components/forms/text-area.vue b/disturbance/frontend/disturbance/src/components/forms/text-area.vue deleted file mode 100755 index 26304a6c6c..0000000000 --- a/disturbance/frontend/disturbance/src/components/forms/text-area.vue +++ /dev/null @@ -1,58 +0,0 @@ - - - - - diff --git a/disturbance/frontend/disturbance/src/components/forms/text.vue b/disturbance/frontend/disturbance/src/components/forms/text.vue deleted file mode 100755 index 023b215d47..0000000000 --- a/disturbance/frontend/disturbance/src/components/forms/text.vue +++ /dev/null @@ -1,58 +0,0 @@ - - - - - diff --git a/disturbance/frontend/disturbance/src/components/forms/text_info.vue b/disturbance/frontend/disturbance/src/components/forms/text_info.vue deleted file mode 100755 index b4934d83ef..0000000000 --- a/disturbance/frontend/disturbance/src/components/forms/text_info.vue +++ /dev/null @@ -1,15 +0,0 @@ - - - - - diff --git a/disturbance/frontend/disturbance/src/components/internal/api.js b/disturbance/frontend/disturbance/src/components/internal/api.js deleted file mode 100755 index 4ac897badf..0000000000 --- a/disturbance/frontend/disturbance/src/components/internal/api.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - organisations: '/api/organisations.json', - countries: 'https://restcountries.eu/rest/v1/?fullText=true', -} diff --git a/disturbance/frontend/disturbance/src/components/internal/approvals/approval.vue b/disturbance/frontend/disturbance/src/components/internal/approvals/approval.vue deleted file mode 100755 index 3afe7643a5..0000000000 --- a/disturbance/frontend/disturbance/src/components/internal/approvals/approval.vue +++ /dev/null @@ -1,287 +0,0 @@ - - - diff --git a/disturbance/frontend/disturbance/src/components/internal/approvals/approval_cancellation.vue b/disturbance/frontend/disturbance/src/components/internal/approvals/approval_cancellation.vue deleted file mode 100755 index ecb1845bee..0000000000 --- a/disturbance/frontend/disturbance/src/components/internal/approvals/approval_cancellation.vue +++ /dev/null @@ -1,210 +0,0 @@ - - - - - diff --git a/disturbance/frontend/disturbance/src/components/internal/approvals/approval_surrender.vue b/disturbance/frontend/disturbance/src/components/internal/approvals/approval_surrender.vue deleted file mode 100755 index c963fca432..0000000000 --- a/disturbance/frontend/disturbance/src/components/internal/approvals/approval_surrender.vue +++ /dev/null @@ -1,213 +0,0 @@ - - - - - diff --git a/disturbance/frontend/disturbance/src/components/internal/approvals/approval_suspension.vue b/disturbance/frontend/disturbance/src/components/internal/approvals/approval_suspension.vue deleted file mode 100755 index c669d1e3e8..0000000000 --- a/disturbance/frontend/disturbance/src/components/internal/approvals/approval_suspension.vue +++ /dev/null @@ -1,244 +0,0 @@ - - - - - diff --git a/disturbance/frontend/disturbance/src/components/internal/approvals/dashboard.vue b/disturbance/frontend/disturbance/src/components/internal/approvals/dashboard.vue deleted file mode 100755 index dfd4e05b7c..0000000000 --- a/disturbance/frontend/disturbance/src/components/internal/approvals/dashboard.vue +++ /dev/null @@ -1,33 +0,0 @@ - - diff --git a/disturbance/frontend/disturbance/src/components/internal/compliances/access.vue b/disturbance/frontend/disturbance/src/components/internal/compliances/access.vue deleted file mode 100755 index 15bbbc39e7..0000000000 --- a/disturbance/frontend/disturbance/src/components/internal/compliances/access.vue +++ /dev/null @@ -1,274 +0,0 @@ - - - diff --git a/disturbance/frontend/disturbance/src/components/internal/compliances/compliance_amendment_request.vue b/disturbance/frontend/disturbance/src/components/internal/compliances/compliance_amendment_request.vue deleted file mode 100755 index ad384bfc7e..0000000000 --- a/disturbance/frontend/disturbance/src/components/internal/compliances/compliance_amendment_request.vue +++ /dev/null @@ -1,204 +0,0 @@ - - - - - diff --git a/disturbance/frontend/disturbance/src/components/internal/compliances/dashboard.vue b/disturbance/frontend/disturbance/src/components/internal/compliances/dashboard.vue deleted file mode 100755 index 620b87c637..0000000000 --- a/disturbance/frontend/disturbance/src/components/internal/compliances/dashboard.vue +++ /dev/null @@ -1,33 +0,0 @@ - - diff --git a/disturbance/frontend/disturbance/src/components/internal/dashboard.vue b/disturbance/frontend/disturbance/src/components/internal/dashboard.vue deleted file mode 100755 index c3cd043612..0000000000 --- a/disturbance/frontend/disturbance/src/components/internal/dashboard.vue +++ /dev/null @@ -1,40 +0,0 @@ - - diff --git a/disturbance/frontend/disturbance/src/components/internal/organisations/access.vue b/disturbance/frontend/disturbance/src/components/internal/organisations/access.vue deleted file mode 100755 index 560b7774ff..0000000000 --- a/disturbance/frontend/disturbance/src/components/internal/organisations/access.vue +++ /dev/null @@ -1,463 +0,0 @@ - - - diff --git a/disturbance/frontend/disturbance/src/components/internal/organisations/dashboard.vue b/disturbance/frontend/disturbance/src/components/internal/organisations/dashboard.vue deleted file mode 100755 index ad0320af0a..0000000000 --- a/disturbance/frontend/disturbance/src/components/internal/organisations/dashboard.vue +++ /dev/null @@ -1,271 +0,0 @@ - - diff --git a/disturbance/frontend/disturbance/src/components/internal/organisations/manage.vue b/disturbance/frontend/disturbance/src/components/internal/organisations/manage.vue deleted file mode 100755 index e999501577..0000000000 --- a/disturbance/frontend/disturbance/src/components/internal/organisations/manage.vue +++ /dev/null @@ -1,480 +0,0 @@ - - - - - - diff --git a/disturbance/frontend/disturbance/src/components/internal/proposals/amendment_request.vue b/disturbance/frontend/disturbance/src/components/internal/proposals/amendment_request.vue deleted file mode 100755 index dbe628b09b..0000000000 --- a/disturbance/frontend/disturbance/src/components/internal/proposals/amendment_request.vue +++ /dev/null @@ -1,247 +0,0 @@ - - - - - diff --git a/disturbance/frontend/disturbance/src/components/internal/proposals/proposal.vue b/disturbance/frontend/disturbance/src/components/internal/proposals/proposal.vue deleted file mode 100755 index 81a5a70e3f..0000000000 --- a/disturbance/frontend/disturbance/src/components/internal/proposals/proposal.vue +++ /dev/null @@ -1,1140 +0,0 @@ - - - diff --git a/disturbance/frontend/disturbance/src/components/internal/proposals/proposal_add_requirement.vue b/disturbance/frontend/disturbance/src/components/internal/proposals/proposal_add_requirement.vue deleted file mode 100755 index 8b730a53e4..0000000000 --- a/disturbance/frontend/disturbance/src/components/internal/proposals/proposal_add_requirement.vue +++ /dev/null @@ -1,361 +0,0 @@ - - - - - diff --git a/disturbance/frontend/disturbance/src/components/internal/proposals/proposal_approval.vue b/disturbance/frontend/disturbance/src/components/internal/proposals/proposal_approval.vue deleted file mode 100755 index e44d875bf0..0000000000 --- a/disturbance/frontend/disturbance/src/components/internal/proposals/proposal_approval.vue +++ /dev/null @@ -1,231 +0,0 @@ - - - diff --git a/disturbance/frontend/disturbance/src/components/internal/proposals/proposal_proposed_decline.vue b/disturbance/frontend/disturbance/src/components/internal/proposals/proposal_proposed_decline.vue deleted file mode 100755 index f8a21d9a20..0000000000 --- a/disturbance/frontend/disturbance/src/components/internal/proposals/proposal_proposed_decline.vue +++ /dev/null @@ -1,188 +0,0 @@ - - - - - diff --git a/disturbance/frontend/disturbance/src/components/internal/proposals/proposal_requirements.vue b/disturbance/frontend/disturbance/src/components/internal/proposals/proposal_requirements.vue deleted file mode 100755 index 6e6d236cba..0000000000 --- a/disturbance/frontend/disturbance/src/components/internal/proposals/proposal_requirements.vue +++ /dev/null @@ -1,306 +0,0 @@ - - - diff --git a/disturbance/frontend/disturbance/src/components/internal/proposals/proposed_issuance.vue b/disturbance/frontend/disturbance/src/components/internal/proposals/proposed_issuance.vue deleted file mode 100755 index 4b5caf7704..0000000000 --- a/disturbance/frontend/disturbance/src/components/internal/proposals/proposed_issuance.vue +++ /dev/null @@ -1,369 +0,0 @@ - - - - - diff --git a/disturbance/frontend/disturbance/src/components/internal/referrals/referral.vue b/disturbance/frontend/disturbance/src/components/internal/referrals/referral.vue deleted file mode 100755 index c3e8392d1b..0000000000 --- a/disturbance/frontend/disturbance/src/components/internal/referrals/referral.vue +++ /dev/null @@ -1,746 +0,0 @@ - - - diff --git a/disturbance/frontend/disturbance/src/components/internal/routes/index.js b/disturbance/frontend/disturbance/src/components/internal/routes/index.js deleted file mode 100755 index 9da8adc35d..0000000000 --- a/disturbance/frontend/disturbance/src/components/internal/routes/index.js +++ /dev/null @@ -1,118 +0,0 @@ -import InternalDashboard from '../dashboard.vue' -import Search from '../search.vue' -import OrgAccessTable from '../organisations/dashboard.vue' -import OrgAccess from '../organisations/access.vue' -import Organisation from '../organisations/manage.vue' -import Proposal from '../proposals/proposal.vue' -import Referral from '../referrals/referral.vue' -import ApprovalDash from '../approvals/dashboard.vue' -import ComplianceDash from '../compliances/dashboard.vue' -import Compliance from '../compliances/access.vue' -import Approval from '../approvals/approval.vue' -export default -{ - path: '/internal', - component: - { - render(c) - { - return c('router-view') - } - }, - children: [ - { - path: '/', - component: InternalDashboard - }, - { - path: 'approvals', - component: ApprovalDash, - name:"internal-approvals-dash" - }, - { - path: 'approval/:approval_id', - component: Approval, - - }, - { - path: 'compliances', - component: ComplianceDash, - name:"internal-compliances-dash" - }, - { - path: 'compliance/:compliance_id', - component: Compliance, - - }, - { - path: 'search', - component: Search, - name:"internal-search" - }, - { - path: 'organisations', - component: { - render(c) - { - return c('router-view') - } - }, - children: [ - { - path: 'access', - component: OrgAccessTable, - name:"org-access-dash" - }, - { - path: 'access/:access_id', - component: OrgAccess, - name:"org-access" - }, - { - path: ':org_id', - component: Organisation, - name:"internal-org-detail" - }, - - ] - }, - { - path: 'proposal', - component: { - render(c) - { - return c('router-view') - } - }, - children: [ - { - path: ':proposal_id', - component: { - render(c) - { - return c('router-view') - } - }, - children: [ - { - path: '/', - component: Proposal, - name:"internal-proposal" - }, - { - path: 'referral/:referral_id', - component: Referral, - name:"internal-referral" - }, - ] - }, - - ] - }, - /*{ - path: 'proposal', - component: Proposal, - name:"new_proposal" - }*/ - ] -} diff --git a/disturbance/frontend/disturbance/src/components/internal/search.vue b/disturbance/frontend/disturbance/src/components/internal/search.vue deleted file mode 100755 index a7336b677d..0000000000 --- a/disturbance/frontend/disturbance/src/components/internal/search.vue +++ /dev/null @@ -1,354 +0,0 @@ - - diff --git a/disturbance/frontend/disturbance/src/components/internal/utils.js b/disturbance/frontend/disturbance/src/components/internal/utils.js deleted file mode 100755 index 89580cbd4d..0000000000 --- a/disturbance/frontend/disturbance/src/components/internal/utils.js +++ /dev/null @@ -1,47 +0,0 @@ -import Vue from 'vue' -import api from './api' -import {helpers} from '@/utils/hooks' - -export default { - fetchProposal: function(id){ - return new Promise ((resolve,reject) => { - Vue.http.get(helpers.add_endpoint_json(api.proposals,id)).then((response) => { - resolve(response.body); - }, - (error) => { - reject(error); - }); - }); - }, - fetchOrganisations: function(id){ - return new Promise ((resolve,reject) => { - Vue.http.get(api.organisations).then((response) => { - resolve(response.body); - }, - (error) => { - reject(error); - }); - }); - }, - fetchCountries: function (){ - return new Promise ((resolve,reject) => { - Vue.http.get(api.countries).then((response) => { - resolve(response.body); - }, - (error) => { - reject(error); - }); - }); - - }, - fetchOrganisation: function(id){ - return new Promise ((resolve,reject) => { - Vue.http.get(helpers.add_endpoint_json(api.organisations,id)).then((response) => { - resolve(response.body); - }, - (error) => { - reject(error); - }); - }); - }, -} diff --git a/disturbance/frontend/disturbance/src/components/user/profile.vue b/disturbance/frontend/disturbance/src/components/user/profile.vue deleted file mode 100755 index 8a6910782a..0000000000 --- a/disturbance/frontend/disturbance/src/components/user/profile.vue +++ /dev/null @@ -1,819 +0,0 @@ - - - - - - diff --git a/disturbance/frontend/disturbance/src/components/user/routes.js b/disturbance/frontend/disturbance/src/components/user/routes.js deleted file mode 100755 index 54d2524fbf..0000000000 --- a/disturbance/frontend/disturbance/src/components/user/routes.js +++ /dev/null @@ -1,3 +0,0 @@ -export default = [ - -] diff --git a/disturbance/frontend/disturbance/src/main.js b/disturbance/frontend/disturbance/src/main.js deleted file mode 100755 index dae472ed4d..0000000000 --- a/disturbance/frontend/disturbance/src/main.js +++ /dev/null @@ -1,39 +0,0 @@ -// The Vue build version to load with the `import` command -// (runtime-only or standalone) has been set in webpack.base.conf with an alias. -import Vue from 'vue' -import resource from 'vue-resource' -import App from './App' -import router from './router' -import bs from 'bootstrap' -import helpers from '@/utils/helpers' -import hooks from './packages' -import api_endpoints from './api' -require( '../node_modules/bootstrap/dist/css/bootstrap.css' ); -//require('../node_modules/eonasdan-bootstrap-datetimepicker/build/css/bootstrap-datetimepicker.min.css') -require( '../node_modules/font-awesome/css/font-awesome.min.css' ) - -Vue.config.devtools = true; -Vue.config.productionTip = false -Vue.use( resource ); - -// Add CSRF Token to every request -Vue.http.interceptors.push( function ( request, next ) { - // modify headers - if ( request.url != api_endpoints.countries ) { - request.headers.set( 'X-CSRFToken', helpers.getCookie( 'csrftoken' ) ); - } - - // continue to next interceptor - next(); -} ); - - -/* eslint-disable no-new */ -new Vue( { - el: '#app', - router, - template: '', - components: { - App - } -} ) diff --git a/disturbance/frontend/disturbance/src/packages.js b/disturbance/frontend/disturbance/src/packages.js deleted file mode 100755 index be33147524..0000000000 --- a/disturbance/frontend/disturbance/src/packages.js +++ /dev/null @@ -1,17 +0,0 @@ -import { extendMoment } from 'moment-range'; -import jszip from 'jszip'; - -require( 'datatables.net' )(); -require( 'datatables.net-bs' )(); -require( 'datatables.net-responsive-bs' )(window, $); -require( 'datatables.net-buttons/js/dataTables.buttons.js' )(window, $); -require( 'datatables.net-buttons/js/buttons.html5.js' )(window, $, jszip); - -require("datatables.net-bs/css/dataTables.bootstrap.css"); -require("datatables.net-responsive-bs/css/responsive.bootstrap.css"); - -require("sweetalert2/dist/sweetalert2.css"); - -require('jquery-validation'); - -extendMoment(moment); diff --git a/disturbance/frontend/disturbance/src/router/index.js b/disturbance/frontend/disturbance/src/router/index.js deleted file mode 100755 index 92fe227c15..0000000000 --- a/disturbance/frontend/disturbance/src/router/index.js +++ /dev/null @@ -1,25 +0,0 @@ -import Vue from 'vue' -import Router from 'vue-router' -import Hello from '@/components/Hello' -import Profile from '@/components/user/profile.vue' -import external_routes from '@/components/external/routes' -import internal_routes from '@/components/internal/routes' -Vue.use(Router) - -export default new Router({ - mode: 'history', - routes: [ - { - path: '/firsttime', - name: 'first-time', - component: Profile - }, - { - path: '/account', - name: 'account', - component: Profile - }, - external_routes, - internal_routes - ] -}) diff --git a/disturbance/frontend/disturbance/src/utils/helpers.js b/disturbance/frontend/disturbance/src/utils/helpers.js deleted file mode 100755 index d89065d062..0000000000 --- a/disturbance/frontend/disturbance/src/utils/helpers.js +++ /dev/null @@ -1,121 +0,0 @@ -module.exports = { - apiError: function ( resp ) { - var error_str = ''; - if ( resp.status === 400 ) { - try { - obj = JSON.parse( resp.responseText ); - error_str = obj.non_field_errors[ 0 ].replace( /[\[\]"]/g, '' ); - } - catch ( e ) { - error_str = resp.responseText.replace( /[\[\]"]/g, '' ); - } - } - else if ( resp.status === 404 ) { - error_str = 'The resource you are looking for does not exist.'; - } - else { - error_str = resp.responseText.replace( /[\[\]"]/g, '' ); - } - return error_str; - }, - apiVueResourceError: function(resp){ - var error_str = ''; - var text = null; - if (resp.status === 400) { - if (Array.isArray(resp.body)){ - text = resp.body[0]; - } - else if (typeof resp.body == 'object'){ - text = resp.body; - } - else{ - text = resp.body; - } - - if (typeof text == 'object'){ - if (text.hasOwnProperty('non_field_errors')) { - error_str = text.non_field_errors[0].replace(/[\[\]"]/g, ''); - } - else{ - error_str = text; - } - } - else{ - error_str = text.replace(/[\[\]"]/g,''); - error_str = text.replace(/^['"](.*)['"]$/, '$1'); - } - } - else if ( resp.status === 404) { - error_str = 'The resource you are looking for does not exist.'; - } - return error_str; - }, - - goBack: function ( vm ) { - vm.$router.go( window.history.back() ); - }, - copyObject: function(obj){ - return JSON.parse(JSON.stringify(obj)); - }, - getCookie: function ( name ) { - var value = null; - if ( document.cookie && document.cookie !== '' ) { - var cookies = document.cookie.split( ';' ); - for ( var i = 0; i < cookies.length; i++ ) { - var cookie = cookies[ i ].trim(); - if ( cookie.substring( 0, name.length + 1 ) - .trim() === ( name + '=' ) ) { - value = decodeURIComponent( cookie.substring( name.length + 1 ) ); - break; - } - } - } - return value; - }, - namePopover: function ( $, vmDataTable ) { - vmDataTable.on( 'mouseover', '.name_popover', function ( e ) { - $( this ) - .popover( 'show' ); - $( this ) - .on( 'mouseout', function () { - $( this ) - .popover( 'hide' ); - } ); - } ); - }, - add_endpoint_json: function ( string, addition ) { - var res = string.split( ".json" ) - return res[ 0 ] + '/' + addition + '.json'; - }, - dtPopover: function(value,truncate_length=30,trigger='hover'){ - var ellipsis = '...', - truncated = _.truncate(value, { - length: truncate_length, - omission: ellipsis, - separator: ' ' - }), - result = '' + truncated + '', - popTemplate = _.template('more'); - if (_.endsWith(truncated, ellipsis)) { - result += popTemplate({ - text: value - }); - } - return result; - }, - dtPopoverCellFn: function(cell){ - $(cell).find('[data-toggle="popover"]') - .popover() - .on('click', function (e) { - e.preventDefault(); - return true; - }); - } -}; diff --git a/disturbance/frontend/disturbance/src/utils/hooks.js b/disturbance/frontend/disturbance/src/utils/hooks.js deleted file mode 100755 index 2d5e54b2f0..0000000000 --- a/disturbance/frontend/disturbance/src/utils/hooks.js +++ /dev/null @@ -1,6 +0,0 @@ -import api_endpoints from '@/api.js'; -import helpers from './helpers' -export { - api_endpoints, - helpers, -} diff --git a/disturbance/frontend/disturbance/src/utils/renderer.js b/disturbance/frontend/disturbance/src/utils/renderer.js deleted file mode 100755 index 8f8ce3da38..0000000000 --- a/disturbance/frontend/disturbance/src/utils/renderer.js +++ /dev/null @@ -1,415 +0,0 @@ -import Section from '../components/forms/section.vue' -import Group from '../components/forms/group.vue' -import Radio from '../components/forms/radio.vue' -import Conditions from '../components/forms/conditions.vue' -import SelectConditions from '../components/forms/select-conditions.vue' -import Checkbox from '../components/forms/checkbox.vue' -import Declaration from '../components/forms/declarations.vue' -import File from '../components/forms/file.vue' -import Select from '../components/forms/select.vue' -import DateField from '../components/forms/date-field.vue' -import TextField from '../components/forms/text.vue' -import TextArea from '../components/forms/text-area.vue' -import Label from '../components/forms/label.vue' -import TextInfo from '../components/forms/text_info.vue' -import AssessorText from '../components/forms/readonly_text.vue' -import HelpText from '../components/forms/help_text.vue' -import HelpTextUrl from '../components/forms/help_text_url.vue' -import CommentRadioCheckBox from '../components/forms/comment_icon_checkbox_radio.vue' -import IFrame from '../components/forms/iframe.vue' -import {helpers,api_endpoints} from "@/utils/hooks.js" - -module.exports = { - renderChildren(h,c,data=null,assessorData=null,_readonly) { - var is_readonly = this.status_data.readonly; - var assessorStatus = this.status_data.assessorStatus; - var assessorData = this.status_data.assessorData; - var commentData = this.status_data.commentData; - var assessorInfo = this.status_data.assessorInfo; - var proposalId = this.status_data.proposalId; - var applicationType = this.status_data.applicationType; - var assessorMode = false; - var assessorCanAssess = false; - var assessorLevel = ''; - var readonly = false; - var _elements = []; - if (assessorStatus != null){ - assessorMode = assessorStatus['assessor_mode']; - assessorCanAssess = assessorStatus['has_assessor_mode']; - assessorLevel = assessorStatus['assessor_level']; - } - //var site_url = api_endpoints.site_url; - var site_url = (api_endpoints.site_url.endsWith("/")) ? (api_endpoints.site_url): (api_endpoints.site_url + "/"); - - // Visibility - var visibility = this.getVisibility(h,c,is_readonly,assessorMode,assessorCanAssess) - if (!visibility.visible){ return "" } - var assessor_visibility = assessorLevel == 'assessor' && this.status_data.assessorStatus.has_assessor_mode? true : false; - assessor_visibility = !assessor_visibility; - - // Editablility - readonly = !visibility.editable; - - var val = (data) ? (data[c.name]) ? data[c.name] : null : null; - var comment_val = (commentData) ? (commentData[c.name]) ? commentData[c.name] : null : null; - - if (c && c.help_text && c.help_text.indexOf("site_url:/") >= 0) { - var help_text = c.help_text.replace('site_url:/', site_url); - if (help_text.indexOf("anchor=") >= 0) { - help_text = help_text.replace('anchor=', "#"); - } - } else { - var help_text = c.help_text; - } - - if (c && c.help_text_assessor && c.help_text_assessor.indexOf("site_url:/") >= 0) { - var help_text_assessor = c.help_text_assessor.replace('site_url:/', site_url); - if (help_text_assessor.indexOf("anchor=") >= 0) { - help_text_assessor = help_text_assessor.replace('anchor=', "#"); - } - } else { - var help_text_assessor = c.help_text_assessor; - } - - // repeat for help_text_url - if (c && c.help_text_url && c.help_text_url.indexOf("site_url:/") >= 0) { - var help_text_url = c.help_text_url.replace('site_url:/', site_url); - if (help_text_url.indexOf("anchor=") >= 0) { - help_text_url = help_text_url.replace('anchor=', "#"); - } - } else { - var help_text_url = c.help_text_url; - } - - if (c && c.help_text_assessor_url && c.help_text_assessor_url.indexOf("site_url:/") >= 0) { - var help_text_assessor_url = c.help_text_assessor_url.replace('site_url:/', site_url); - if (help_text_assessor_url.indexOf("anchor=") >= 0) { - help_text_assessor_url = help_text_assessor_url.replace('anchor=', "#"); - } - } else { - var help_text_assessor_url = c.help_text_assessor_url; - } - - - - var id = 'id_' + c.name; - var id1 = id + '_1' - var id2 = id + '_2' - var id3 = id + '_3' - - switch (c.type) { - case 'text': - readonly = (c.readonly) ? (c.readonly): (readonly); - _elements.push( - - ) - break; - case 'text_info': - _elements.push( - - ) - break; - case 'iframe': - _elements.push( -