class OrderViewSet(CoreViewSet): """Order ViewSet""" required_scopes = (Scope.internal_front_end, ) serializer_class = OrderSerializer queryset = Order.objects.select_related( 'company', 'contact', 'primary_market', ) @action(methods=['post'], detail=True, schema=StubSchema()) def complete(self, request, *args, **kwargs): """Complete an order.""" instance = self.get_object() serializer = CompleteOrderSerializer( instance, data={}, context=self.get_serializer_context(), ) serializer.is_valid(raise_exception=True) instance = serializer.complete() return Response( self.get_serializer(instance=instance).data, status=status.HTTP_200_OK, ) @action(methods=['post'], detail=True, schema=StubSchema()) def cancel(self, request, *args, **kwargs): """Cancel an order.""" instance = self.get_object() serializer = CancelOrderSerializer( instance, data=request.data, context=self.get_serializer_context(), ) serializer.is_valid(raise_exception=True) instance = serializer.cancel() return Response( self.get_serializer(instance=instance).data, status=status.HTTP_200_OK, ) def get_serializer_context(self): """Extra context provided to the serializer class.""" return { **super().get_serializer_context(), 'current_user': self.request.user if self.request else None, }
class BaseEntityDocumentModelViewSet(CoreViewSet): """Documents ViewSet.""" lookup_url_kwarg = 'entity_document_pk' def create(self, request, *args, **kwargs): """Create and one-time upload URL generation.""" response = super().create(request, *args, **kwargs) entity_document = self.get_queryset().get(pk=response.data['id']) response.data['signed_upload_url'] = entity_document.document.get_signed_upload_url() return response @action(methods=['post'], detail=True, schema=StubSchema()) def upload_complete_callback(self, request, *args, **kwargs): """File upload done callback.""" entity_document = self.get_object() entity_document.document.schedule_av_scan() return self.retrieve(request) @action(methods=['get'], detail=True, schema=StubSchema()) def download(self, request, *args, **kwargs): """Provides download information.""" entity_document = self.get_object() if not entity_document.document.scanned_on: raise TemporarilyUnavailableException() if not entity_document.document.av_clean: raise PermissionDenied('File did not pass virus scanning.') url = entity_document.document.get_signed_url() response = super().retrieve(request) response.data['document_url'] = url return response def perform_destroy(self, instance): """ Marks document with pending_delete status and schedules Celery task that performs deletion of corresponding s3 file, document and entity_document. Deletion of document will cascade to entity document. """ instance.document.mark_deletion_pending() delete_document.apply_async(args=(instance.document.pk,))
class ArchivableViewSetMixin: """To be used with archivable models.""" archive_validators = [] unarchive_validators = [] @action(methods=['post'], detail=True, schema=StubSchema()) def archive(self, request, pk): """Archive the object.""" obj = self.get_object() context = { 'user': request.user, } archive_serializer = ArchiveSerializer( instance=obj, data=request.data, context=context, validators=self.archive_validators, ) archive_serializer.is_valid(raise_exception=True) archive_serializer.save() obj_serializer = self.get_serializer_class()(obj) return Response(data=obj_serializer.data) @action(methods=['post'], detail=True, schema=StubSchema()) def unarchive(self, request, pk): """Unarchive the object.""" obj = self.get_object() unarchive_serializer = UnarchiveSerializer( instance=obj, data=request.data, validators=self.unarchive_validators, ) unarchive_serializer.is_valid(raise_exception=True) unarchive_serializer.save() obj_serializer = self.get_serializer_class()(obj) return Response(data=obj_serializer.data)
class CompanyViewSet(ArchivableViewSetMixin, CoreViewSet): """Company view set.""" serializer_class = CompanySerializer unarchive_validators = (NotATransferredCompanyValidator(), ) filter_backends = (DjangoFilterBackend, OrderingFilter) filterset_fields = ('global_headquarters_id', 'global_ultimate_duns_number') ordering_fields = ('name', 'created_on') queryset = Company.objects.select_related( 'address_country', 'archived_by', 'business_type', 'employee_range', 'export_experience_category', 'global_headquarters__one_list_account_owner__dit_team__country', 'global_headquarters__one_list_account_owner__dit_team__uk_region', 'global_headquarters__one_list_account_owner__dit_team', 'global_headquarters__one_list_account_owner', 'global_headquarters__one_list_tier', 'global_headquarters', 'headquarter_type', 'one_list_account_owner__dit_team__country', 'one_list_account_owner__dit_team__uk_region', 'one_list_account_owner__dit_team', 'one_list_account_owner', 'one_list_tier', 'registered_address_country', 'transferred_to', 'turnover_range', 'uk_region', ).prefetch_related( Prefetch('contacts', queryset=get_contact_queryset()), Prefetch('investor_investment_projects', queryset=get_slim_investment_project_queryset()), 'export_to_countries', 'future_interest_countries', 'sector__parent__parent', 'sector__parent', 'sector', Prefetch('export_countries', queryset=get_export_country_queryset()), ) @action( methods=['post'], detail=True, permission_classes=[ HasPermissions( f'company.{CompanyPermission.change_company}', f'company.{CompanyPermission.change_regional_account_manager}', ), ], schema=StubSchema(), ) def assign_regional_account_manager(self, request, *args, **kwargs): """ Sets the company to be an international trade adviser-managed One List company, and assigns the requested user as the account manager. This means: - setting the One List tier to 'Tier D - Interaction Trade Adviser Accounts' (using the tier ID, not the name) - setting the requested user as the One List account manager (overwriting the existing value) The operation is not allowed if: - the company is a subsidiary of a One List company - the company is already a One List company on a different tier (i.e. not 'Tier D - Interaction Trade Adviser Accounts') """ instance = self.get_object() serializer = AssignRegionalAccountManagerSerializer(instance=instance, data=request.data) serializer.is_valid(raise_exception=True) serializer.save(request.user) return Response(None, status=status.HTTP_204_NO_CONTENT) @action( methods=['post'], detail=True, permission_classes=[ HasPermissions( f'company.{CompanyPermission.change_company}', f'company.{CompanyPermission.change_regional_account_manager}', ), ], schema=StubSchema(), ) def self_assign_account_manager(self, request, *args, **kwargs): """ Sets the company to be an international trade adviser-managed One List company, and assigns the authenticated user as the account manager. This means: - setting the One List tier to 'Tier D - Interaction Trade Adviser Accounts' (using the tier ID, not the name) - setting the authenticated user as the One List account manager (overwriting the existing value) The operation is not allowed if: - the company is a subsidiary of a One List company - the company is already a One List company on a different tier (i.e. not 'Tier D - Interaction Trade Adviser Accounts') """ instance = self.get_object() serializer = SelfAssignAccountManagerSerializer(instance=instance, data=request.data) serializer.is_valid(raise_exception=True) serializer.save(request.user) return Response(None, status=status.HTTP_204_NO_CONTENT) @action( methods=['post'], detail=True, permission_classes=[ HasPermissions( f'company.{CompanyPermission.change_company}', f'company.{CompanyPermission.change_regional_account_manager}', ), ], schema=StubSchema(), ) def remove_account_manager(self, request, *args, **kwargs): """ Remove the One List account manager and tier from a company if it is an international trade adviser-managed One List company. The operation is not allowed if the company is a One List company that isn't on 'Tier D - Interaction Trade Adviser Accounts'. """ instance = self.get_object() serializer = RemoveAccountManagerSerializer(instance=instance, data=request.data) serializer.is_valid(raise_exception=True) serializer.save(request.user) return Response(None, status=status.HTTP_204_NO_CONTENT) @action( methods=['post'], detail=True, permission_classes=[ HasPermissions( f'company.{CompanyPermission.change_company}', f'company.{CompanyPermission.change_one_list_tier_and_global_account_manager}', ), ], schema=StubSchema(), ) def assign_one_list_tier_and_global_account_manager( self, request, *args, **kwargs): """ Assign One List tier and Global Account Manager. This endpoint enables a user with correct permissions to assign company one list tier and global account manager except when company is on 'Tier D - Interaction Trade Adviser Accounts'. One List tier and Global Account Manager cannot be assigned to a subsidiary. """ instance = self.get_object() serializer = AssignOneListTierAndGlobalAccountManagerSerializer( instance=instance, data=request.data, ) serializer.is_valid(raise_exception=True) serializer.save(request.user) return Response(None, status=status.HTTP_204_NO_CONTENT) @action( methods=['post'], detail=True, permission_classes=[ HasPermissions( f'company.{CompanyPermission.change_company}', f'company.{CompanyPermission.change_one_list_tier_and_global_account_manager}', ), ], schema=StubSchema(), ) def remove_from_one_list(self, request, *args, **kwargs): """ Remove company from One List. The operation is not allowed if the company is on 'Tier D - Interaction Trade Adviser Accounts'. """ instance = self.get_object() serializer = RemoveCompanyFromOneListSerializer(instance=instance, data=request.data) serializer.is_valid(raise_exception=True) serializer.save(request.user) return Response(None, status=status.HTTP_204_NO_CONTENT) @action( methods=['patch'], detail=True, permission_classes=[ HasPermissions( f'company.{CompanyPermission.change_company}', f'company.{CompanyPermission.change_one_list_core_team_member}', ), ], schema=StubSchema(), ) def update_one_list_core_team(self, request, *args, **kwargs): """Updates core team for the company.""" instance = self.get_object() serializer = UpdateOneListCoreTeamMembersSerializer( instance=instance, data=request.data, partial=True, ) serializer.is_valid(raise_exception=True) serializer.save(request.user) return Response(None, status=status.HTTP_204_NO_CONTENT) @action( methods=['patch'], permission_classes=[ HasPermissions( f'company.{CompanyPermission.change_company}', 'company.change_companyexportcountry', ), ], detail=True, ) def update_export_detail(self, request, *args, **kwargs): """ Update export related information for the company. """ instance = self.get_object() serializer = UpdateExportDetailsSerializer( instance=instance, data=request.data, partial=True, ) serializer.is_valid(raise_exception=True) serializer.save(request.user) return Response(None, status=status.HTTP_204_NO_CONTENT)
class CompanyReferralViewSet(CoreViewSet): """Company referral view set.""" serializer_class = CompanyReferralSerializer queryset = CompanyReferral.objects.select_related( 'company', 'contact', 'completed_by__dit_team', 'created_by__dit_team', 'interaction', 'recipient__dit_team', ) def get_queryset(self): """ Get a queryset for list action that is filtered to the authenticated user's sent and received referrals, otherwise return original queryset. """ if self.action == 'list': return super().get_queryset().filter( Q(created_by=self.request.user) | Q(recipient=self.request.user), ) return super().get_queryset() @action( methods=['post'], detail=True, schema=StubSchema(), permission_classes=[ HasPermissions('company_referral.change_companyreferral'), ], ) def complete(self, request, **kwargs): """ View for completing a referral. Completing a referral involves creating an interaction and linking the referral and interaction together. Hence, this view creates an interaction and updates the referral object accordingly. """ referral = self.get_object() context = { **self.get_serializer_context(), # Used by HasAssociatedInvestmentProjectValidator 'check_association_permissions': False, 'referral': referral, 'user': request.user, } data = { **request.data, 'company': { 'id': referral.company.pk, }, } serializer = CompleteCompanyReferralSerializer( data=data, context=context, ) serializer.is_valid(raise_exception=True) serializer.save() return Response(serializer.data, status=status.HTTP_201_CREATED)
class IProjectViewSet(ArchivableViewSetMixin, CoreViewSet): """Unified investment project views. This replaces the previous project, value, team and requirements endpoints. """ permission_classes = ( InvestmentProjectModelPermissions, IsAssociatedToInvestmentProjectPermission, ) serializer_class = IProjectSerializer queryset = InvestmentProject.objects.select_related( 'archived_by', 'average_salary', 'client_relationship_manager__dit_team', 'client_relationship_manager', 'country_lost_to', 'country_investment_originates_from', 'fdi_type', 'intermediate_company', 'investment_type', 'investmentprojectcode', 'investor_company', 'investor_type', 'level_of_involvement', 'project_assurance_adviser__dit_team', 'project_assurance_adviser', 'project_manager__dit_team', 'project_manager', 'referral_source_activity_marketing', 'referral_source_activity_website', 'referral_source_activity', 'referral_source_adviser', 'specific_programme', 'stage', 'uk_company__address_country', 'uk_company', ).prefetch_related( 'actual_uk_regions', 'business_activities', 'client_contacts', 'competitor_countries', 'delivery_partners', 'sector__parent__parent', 'sector__parent', 'sector', 'strategic_drivers', 'uk_region_locations', Prefetch('team_members', queryset=_team_member_queryset), ) filter_backends = ( DjangoFilterBackend, OrderingFilter, IsAssociatedToInvestmentProjectFilter, ) filterset_fields = ('investor_company_id', ) ordering = ('-created_on', ) def get_view_name(self): """Returns the view set name for the DRF UI.""" return 'Investment projects' def get_serializer_context(self): """Extra context provided to the serializer class.""" return { **super().get_serializer_context(), 'current_user': self.request.user if self.request else None, } @action( methods=['post'], detail=True, permission_classes=[ HasPermissions( f'investment.{InvestmentProjectPermission.change_to_any_stage}' ), ], filter_backends=[], schema=StubSchema(), ) def change_stage(self, request, *args, **kwargs): """Change the stage of an investment project""" instance = self.get_object() serializer = IProjectChangeStageSerializer( instance, data=request.data, context=self.get_serializer_context(), ) serializer.is_valid(raise_exception=True) instance = serializer.change_stage(user=self.request.user) return Response( self.get_serializer(instance=instance).data, status=status.HTTP_200_OK, )