diff --git a/accounts/api_urls.py b/accounts/api_urls.py index 40ad6de..8fbbeb3 100644 --- a/accounts/api_urls.py +++ b/accounts/api_urls.py @@ -6,6 +6,7 @@ urlpatterns = [ path("", api_views.AccountsListView.as_view()), path("/", api_views.AccountDetailView.as_view()), + path("/create_mail", api_views.AccountCreateMailView.as_view()), path("comment//", api_views.AccountCommentView.as_view()), path("attachment//", api_views.AccountAttachmentView.as_view()), ] diff --git a/accounts/api_views.py b/accounts/api_views.py index d1c88b1..f166461 100644 --- a/accounts/api_views.py +++ b/accounts/api_views.py @@ -3,8 +3,8 @@ from django.contrib.sites.shortcuts import get_current_site from django.db.models import Q -from accounts.models import Account, Tags -from accounts.tasks import send_email_to_assigned_user +from accounts.models import Account, Tags, Email +from accounts.tasks import send_email_to_assigned_user, send_email from accounts import swagger_params from accounts.serializer import ( AccountSerializer, @@ -38,7 +38,7 @@ from tasks.serializer import TaskSerializer from opportunity.serializer import OpportunitySerializer from invoices.serializer import InvoiceSerailizer -from emails.serializer import EmailSerailizer +from accounts.serializer import EmailSerializer from teams.models import Teams from rest_framework import status @@ -48,6 +48,7 @@ from rest_framework.pagination import LimitOffsetPagination from drf_yasg.utils import swagger_auto_schema import json +from crm import settings class AccountsListView(APIView, LimitOffsetPagination): @@ -62,7 +63,7 @@ def get_context_data(self, **kwargs): if len(self.request.data) == 0 else self.request.data ) - queryset = self.model.objects.filter(company=self.request.company) + queryset = self.model.objects.all() if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: queryset = queryset.filter( Q(created_by=self.request.user) | Q(assigned_to=self.request.user) @@ -125,17 +126,11 @@ def get_context_data(self, **kwargs): } context["users"] = UserSerializer( - User.objects.filter(is_active=True, company=self.request.company).order_by( - "email" - ), + User.objects.filter(is_active=True).order_by("email"), many=True, ).data context["industries"] = INDCHOICES - tag_ids = ( - Account.objects.filter(company=self.request.company) - .values_list("tags", flat=True) - .distinct() - ) + tag_ids = Account.objects.all().values_list("tags", flat=True).distinct() context["tags"] = TagsSerailizer( Tags.objects.filter(id__in=tag_ids), many=True ).data @@ -167,21 +162,20 @@ def post(self, request, *args, **kwargs): ) # Save Account if serializer.is_valid(): - account_object = serializer.save( - created_by=request.user, company=request.company - ) + account_object = serializer.save(created_by=request.user) if params.get("contacts"): contacts = json.loads(params.get("contacts")) for contact in contacts: - obj_contact = Contact.objects.filter( - id=contact, company=request.company - ) + obj_contact = Contact.objects.filter(id=contact) if obj_contact: account_object.contacts.add(contact) else: account_object.delete() data["contacts"] = "Please enter valid contact" - return Response({"error": True, "errors": data}) + return Response( + {"error": True, "errors": data}, + status=status.HTTP_400_BAD_REQUEST, + ) if params.get("tags"): tags = json.loads(params.get("tags")) for tag in tags: @@ -195,26 +189,30 @@ def post(self, request, *args, **kwargs): if params.get("teams"): teams = json.loads(params.get("teams")) for team in teams: - teams_ids = Teams.objects.filter( - id=team, company=request.company - ) + teams_ids = Teams.objects.filter(id=team) if teams_ids: account_object.teams.add(team) else: account_object.delete() data["team"] = "Please enter valid Team" - return Response({"error": True, "errors": data}) + return Response( + {"error": True, "errors": data}, + status=status.HTTP_400_BAD_REQUEST, + ) if params.get("assigned_to"): assinged_to_users_ids = json.loads(params.get("assigned_to")) for user_id in assinged_to_users_ids: - user = User.objects.filter(id=user_id, company=request.company) + user = User.objects.filter(id=user_id) if user: account_object.assigned_to.add(user_id) else: account_object.delete() data["assigned_to"] = "Please enter valid user" - return Response({"error": True, "errors": data}) + return Response( + {"error": True, "errors": data}, + status=status.HTTP_400_BAD_REQUEST, + ) if self.request.FILES.get("account_attachment"): attachment = Attachments() @@ -228,15 +226,17 @@ def post(self, request, *args, **kwargs): account_object.assigned_to.all().values_list("id", flat=True) ) - current_site = get_current_site(request) recipients = assigned_to_list send_email_to_assigned_user.delay( recipients, account_object.id, - domain=current_site.domain, + domain=settings.Domain, protocol=self.request.scheme, ) - return Response({"error": False, "message": "Account Created Successfully"}) + return Response( + {"error": False, "message": "Account Created Successfully"}, + status=status.HTTP_200_OK, + ) return Response( {"error": True, "errors": serializer.errors}, status=status.HTTP_400_BAD_REQUEST, @@ -257,11 +257,6 @@ def put(self, request, pk, format=None): params = request.query_params if len(request.data) == 0 else request.data account_object = self.get_object(pk=pk) data = {} - if account_object.company != request.company: - return Response( - {"error": True, "errors": "User company doesnot match with header...."}, - status=status.HTTP_404_NOT_FOUND, - ) serializer = AccountCreateSerializer( account_object, data=params, request_obj=request, account=True ) @@ -277,7 +272,7 @@ def put(self, request, pk, format=None): "error": True, "errors": "You do not have Permission to perform this action", }, - status=status.HTTP_401_UNAUTHORIZED, + status=status.HTTP_403_FORBIDDEN, ) account_object = serializer.save() previous_assigned_to_users = list( @@ -287,14 +282,15 @@ def put(self, request, pk, format=None): if params.get("contacts"): contacts = json.loads(params.get("contacts")) for contact in contacts: - obj_contact = Contact.objects.filter( - id=contact, company=request.company - ) + obj_contact = Contact.objects.filter(id=contact) if obj_contact: account_object.contacts.add(contact) else: data["contacts"] = "Please enter valid Contact" - return Response({"error": True, "errors": data}) + return Response( + {"error": True, "errors": data}, + status=status.HTTP_400_BAD_REQUEST, + ) account_object.tags.clear() if params.get("tags"): tags = json.loads(params.get("tags")) @@ -311,25 +307,29 @@ def put(self, request, pk, format=None): if params.get("teams"): teams = json.loads(params.get("teams")) for team in teams: - teams_ids = Teams.objects.filter( - id=team, company=request.company - ) + teams_ids = Teams.objects.filter(id=team) if teams_ids: account_object.teams.add(team) else: data["team"] = "Please enter valid Team" - return Response({"error": True, "errors": data}) + return Response( + {"error": True, "errors": data}, + status=status.HTTP_400_BAD_REQUEST, + ) account_object.assigned_to.clear() if params.get("assigned_to"): assinged_to_users_ids = json.loads(params.get("assigned_to")) for user_id in assinged_to_users_ids: - user = User.objects.filter(id=user_id, company=request.company) + user = User.objects.filter(id=user_id) if user: account_object.assigned_to.add(user_id) else: data["assigned_to"] = "Please enter valid User" - return Response({"error": True, "errors": data}) + return Response( + {"error": True, "errors": data}, + status=status.HTTP_400_BAD_REQUEST, + ) if self.request.FILES.get("account_attachment"): attachment = Attachments() @@ -342,12 +342,11 @@ def put(self, request, pk, format=None): assigned_to_list = list( account_object.assigned_to.all().values_list("id", flat=True) ) - current_site = get_current_site(self.request) recipients = list(set(assigned_to_list) - set(previous_assigned_to_users)) send_email_to_assigned_user.delay( recipients, account_object.id, - domain=current_site.domain, + domain=settings.Domain, protocol=self.request.scheme, ) return Response( @@ -359,22 +358,17 @@ def put(self, request, pk, format=None): status=status.HTTP_400_BAD_REQUEST, ) - @swagger_auto_schema( - tags=["Accounts"], manual_parameters=swagger_params.company_params - ) + @swagger_auto_schema(tags=["Accounts"]) def delete(self, request, pk, format=None): self.object = self.get_object(pk) - if self.object.company != request.company: - return Response( - {"error": True, "errors": "User company doesnot match with header...."} - ) if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: if self.request.user != self.object.created_by: return Response( { "error": True, "errors": "You do not have Permission to perform this action", - } + }, + status=status.HTTP_403_FORBIDDEN, ) self.object.delete() return Response( @@ -383,15 +377,10 @@ def delete(self, request, pk, format=None): ) @swagger_auto_schema( - tags=["Accounts"], manual_parameters=swagger_params.account_get_detail_params + tags=["Accounts"], ) def get(self, request, pk, format=None): self.account = self.get_object(pk=pk) - if self.account.company != request.company: - return Response( - {"error": True, "errors": "User company doesnot match with header...."}, - status=status.HTTP_404_NOT_FOUND, - ) context = {} context["account_obj"] = AccountSerializer(self.account).data if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: @@ -403,7 +392,8 @@ def get(self, request, pk, format=None): { "error": True, "errors": "You do not have Permission to perform this action", - } + }, + status=status.HTTP_403_FORBIDDEN, ) comment_permission = ( @@ -417,12 +407,7 @@ def get(self, request, pk, format=None): ) if self.request.user.is_superuser or self.request.user.role == "ADMIN": - users_mention = list( - User.objects.filter( - is_active=True, - company=self.request.company, - ).values("username") - ) + users_mention = list(User.objects.filter(is_active=True).values("username")) elif self.request.user != self.account.created_by: if self.account.created_by: users_mention = [{"username": self.account.created_by.username}] @@ -445,10 +430,7 @@ def get(self, request, pk, format=None): Opportunity.objects.filter(account=self.account), many=True ).data, "users": UserSerializer( - User.objects.filter( - is_active=True, - company=self.request.company, - ).order_by("email"), + User.objects.filter(is_active=True).order_by("email"), many=True, ).data, "cases": CaseSerializer( @@ -468,7 +450,7 @@ def get(self, request, pk, format=None): "invoices": InvoiceSerailizer( self.account.accounts_invoices.all(), many=True ).data, - "emails": EmailSerailizer( + "emails": EmailSerializer( self.account.sent_email.all(), many=True ).data, "users_mention": users_mention, @@ -487,11 +469,6 @@ def post(self, request, pk, **kwargs): ) context = {} self.account_obj = Account.objects.get(pk=pk) - if self.account_obj.company != request.company: - return Response( - {"error": True, "errors": "User company does not match with header...."} - ) - if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: if not ( (self.request.user == self.account_obj.created_by) @@ -502,7 +479,7 @@ def post(self, request, pk, **kwargs): "error": True, "errors": "You do not have Permission to perform this action", }, - status=status.HTTP_401_UNAUTHORIZED, + status=status.HTTP_403_FORBIDDEN, ) comment_serializer = CommentSerializer(data=params) if comment_serializer.is_valid(): @@ -572,12 +549,11 @@ def put(self, request, pk, format=None): { "error": True, "errors": "You don't have permission to edit this Comment", - } + }, + status=status.HTTP_403_FORBIDDEN, ) - @swagger_auto_schema( - tags=["Accounts"], manual_parameters=swagger_params.company_params - ) + @swagger_auto_schema(tags=["Accounts"]) def delete(self, request, pk, format=None): self.object = self.get_object(pk) if ( @@ -595,7 +571,8 @@ def delete(self, request, pk, format=None): { "error": True, "errors": "You don't have permission to perform this action", - } + }, + status=status.HTTP_403_FORBIDDEN, ) @@ -604,9 +581,7 @@ class AccountAttachmentView(APIView): authentication_classes = (JSONWebTokenAuthentication,) permission_classes = (IsAuthenticated,) - @swagger_auto_schema( - tags=["Accounts"], manual_parameters=swagger_params.company_params - ) + @swagger_auto_schema(tags=["Accounts"]) def delete(self, request, pk, format=None): self.object = self.model.objects.get(pk=pk) if ( @@ -624,5 +599,61 @@ def delete(self, request, pk, format=None): { "error": True, "errors": "You don't have permission to delete this Attachment", - } + }, + status=status.HTTP_403_FORBIDDEN, + ) + + +class AccountCreateMailView(APIView): + + authentication_classes = (JSONWebTokenAuthentication,) + permission_classes = (IsAuthenticated,) + model = Account + + @swagger_auto_schema( + tags=["Accounts"], manual_parameters=swagger_params.account_mail_params + ) + def post(self, request, pk, *args, **kwargs): + params = request.query_params if len(request.data) == 0 else request.data + scheduled_later = params.get("scheduled_later") + scheduled_date_time = params.get("scheduled_date_time") + account = Account.objects.filter(id=pk).first() + serializer = EmailSerializer( + data=params, + request_obj=request, # account=account, + ) + + data = {} + if serializer.is_valid(): + email_obj = serializer.save(from_account=account) + if scheduled_later not in ["", None, False, "false"]: + if scheduled_date_time in ["", None]: + return Response( + {"error": True, "errors": serializer.errors}, + status=status.HTTP_400_BAD_REQUEST, + ) + + if params.get("recipients"): + contacts = json.loads(params.get("recipients")) + for contact in contacts: + obj_contact = Contact.objects.filter(id=contact) + if obj_contact: + email_obj.recipients.add(contact) + else: + email_obj.delete() + data["recipients"] = "Please enter valid recipient" + return Response({"error": True, "errors": data}) + if params.get("scheduled_later") != "true": + send_email.delay(email_obj.id) + else: + email_obj.scheduled_later = True + email_obj.scheduled_date_time = scheduled_date_time + return Response( + {"error": False, "message": "Email sent successfully"}, + status=status.HTTP_200_OK, + ) + else: + return Response( + {"error": True, "errors": serializer.errors}, + status=status.HTTP_400_BAD_REQUEST, ) diff --git a/accounts/forms.py b/accounts/forms.py deleted file mode 100644 index 795d090..0000000 --- a/accounts/forms.py +++ /dev/null @@ -1,217 +0,0 @@ -from django import forms -from .models import Account, Email -from common.models import Comment, Attachments, User -from leads.models import Lead -from contacts.models import Contact -from django.db.models import Q -from teams.models import Teams - - -class AccountForm(forms.ModelForm): - teams_queryset = [] - teams = forms.MultipleChoiceField(choices=teams_queryset) - - def __init__(self, *args, **kwargs): - account_view = kwargs.pop("account", False) - request_user = kwargs.pop("request_user", None) - request_obj = kwargs.pop("request_obj", None) - super(AccountForm, self).__init__(*args, **kwargs) - for field in self.fields.values(): - field.widget.attrs = {"class": "form-control"} - self.fields["description"].widget.attrs.update({"rows": "8"}) - self.fields["status"].choices = [ - (each[0], each[1]) for each in Account.ACCOUNT_STATUS_CHOICE - ] - self.fields["status"].required = False - for key, value in self.fields.items(): - if key == "phone": - value.widget.attrs["placeholder"] = "+911234567890" - else: - value.widget.attrs["placeholder"] = value.label - - self.fields["billing_address_line"].widget.attrs.update( - {"placeholder": "Address Line"} - ) - self.fields["billing_street"].widget.attrs.update({"placeholder": "Street"}) - self.fields["billing_city"].widget.attrs.update({"placeholder": "City"}) - self.fields["billing_state"].widget.attrs.update({"placeholder": "State"}) - self.fields["billing_postcode"].widget.attrs.update({"placeholder": "Postcode"}) - self.fields["billing_country"].choices = [("", "--Country--"),] + list( - self.fields["billing_country"].choices - )[1:] - # self.fields["lead"].queryset = Lead.objects.all( - # ).exclude(status='closed') - if request_user.role == "ADMIN": - self.fields["lead"].queryset = ( - Lead.objects.filter(company=request_obj.company) - .exclude(status="closed") - .order_by("title") - ) - self.fields["contacts"].queryset = Contact.objects.filter( - company=request_obj.company - ) - self.fields["teams"].choices = [ - (team.get("id"), team.get("name")) - for team in Teams.objects.filter(company=request_obj.company).values( - "id", "name" - ) - ] - self.fields["teams"].required = False - else: - self.fields["lead"].queryset = ( - Lead.objects.filter( - Q(assigned_to__in=[request_user]) | Q(created_by=request_user) - ) - .filter(company=request_obj.company) - .exclude(status="closed") - .order_by("title") - ) - self.fields["contacts"].queryset = Contact.objects.filter( - Q(assigned_to__in=[request_user]) | Q(created_by=request_user) - ).filter(company=request_obj.company) - self.fields["teams"].required = False - - self.fields["assigned_to"].required = False - if account_view: - self.fields["billing_address_line"].required = True - self.fields["billing_street"].required = True - self.fields["billing_city"].required = True - self.fields["billing_state"].required = True - self.fields["billing_postcode"].required = True - self.fields["billing_country"].required = True - - # lead is not mandatory while editing - if self.instance.id: - self.fields["lead"].required = False - self.fields["lead"].required = False - self.company = request_obj.company - - def clean_name(self): - name = self.cleaned_data.get("name") - if self.instance.id: - if self.instance.name != name: - if not Account.objects.filter( - name__iexact=self.cleaned_data.get("name"), company=self.company - ).exists(): - return self.cleaned_data.get("name") - raise forms.ValidationError("Account already exists with this name") - return self.cleaned_data.get("name") - if not Account.objects.filter( - name__iexact=self.cleaned_data.get("name"), company=self.company - ).exists(): - return self.cleaned_data.get("name") - raise forms.ValidationError("Account already exists with this name") - - class Meta: - model = Account - fields = ( - "name", - "phone", - "email", - "website", - "industry", - "description", - "status", - "assigned_to", - "billing_address_line", - "billing_street", - "billing_city", - "billing_state", - "billing_postcode", - "billing_country", - "lead", - "contacts", - ) - - -class AccountCommentForm(forms.ModelForm): - comment = forms.CharField(max_length=255, required=True) - - class Meta: - model = Comment - fields = ("comment", "account", "commented_by") - - -class AccountAttachmentForm(forms.ModelForm): - attachment = forms.FileField(max_length=1001, required=True) - - class Meta: - model = Attachments - fields = ("attachment", "account") - - -class EmailForm(forms.ModelForm): - recipients = forms.CharField() - # message_subject = forms.CharField(max_length=500) - # message_body = forms.CharField(widget=forms.Textarea) - # timezone = forms.CharField(max_length=200) - # scheduled_date_time = forms.DateTimeField() - # scheduled_later = forms.CharField(max_length=20) - - def __init__(self, *args, **kwargs): - self.account_obj = kwargs.pop("account", False) - super(EmailForm, self).__init__(*args, **kwargs) - # self.fields['message_subject'].widget.attrs['class'] = 'form-control' - # self.fields['message_subject'].widget.attrs['required'] = True - # self.fields['message_subject'].widget.attrs['placeholder'] = 'Email Subject' - - # self.fields['recipient'].required = False - self.fields["from_email"].required = True - self.fields["message_subject"].required = True - self.fields["message_body"].required = True - - self.fields["scheduled_date_time"].required = False - self.fields["scheduled_later"].required = False - self.fields["recipients"].required = True - self.fields["recipients"].query = self.account_obj.contacts.all() - # self.fields['recipients'].choices = list((contact.get('id'), contact.get('email')) - # for contact in self.account_obj.contacts.values('id', 'email')) - - class Meta: - model = Email - fields = [ - "recipients", - "message_subject", - "from_email", - "message_body", - "timezone", - "scheduled_date_time", - "scheduled_later", - ] - - # def clean_recipients(self): - # recipients = self.cleaned_data.get('recipients') - # recipients = recipients.split(',') - # if len(recipients) == 0: - # raise forms.ValidationError('This field is required.') - # contacts = list(self.account_obj.contacts.values_list('id', flat=True)) - # for recipient in recipients: - # if int(recipient) not in contacts: - # raise forms.ValidationError('{} is not a valid choice.'.format(recipient)) - # return recipients - - def clean_scheduled_date_time(self): - scheduled_date_time = self.cleaned_data.get("scheduled_date_time") - if self.data.get("scheduled_later") not in ["", None, False, "false"]: - if scheduled_date_time in ["", None]: - raise forms.ValidationError("This Field is required.") - - if self.data.get("scheduled_later") == "true": - if scheduled_date_time in ["", None]: - raise forms.ValidationError("This Field is required.") - - return scheduled_date_time - - def clean_message_body(self): - message_body = self.cleaned_data.get("message_body") - count = 0 - for i in message_body: - if i == "{": - count += 1 - elif i == "}": - count -= 1 - if count < 0: - raise forms.ValidationError("Brackets do not match, Enter valid tags.") - if count != 0: - raise forms.ValidationError("Brackets do not match, Enter valid tags.") - return message_body diff --git a/accounts/migrations/0012_remove_account_company.py b/accounts/migrations/0012_remove_account_company.py new file mode 100644 index 0000000..94dc247 --- /dev/null +++ b/accounts/migrations/0012_remove_account_company.py @@ -0,0 +1,17 @@ +# Generated by Django 3.1.7 on 2021-03-23 14:25 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("accounts", "0011_account_company"), + ] + + operations = [ + migrations.RemoveField( + model_name="account", + name="company", + ), + ] diff --git a/accounts/models.py b/accounts/models.py index 2550056..ba06ba1 100644 --- a/accounts/models.py +++ b/accounts/models.py @@ -3,7 +3,7 @@ from django.utils.translation import pgettext_lazy from django.utils.translation import ugettext_lazy as _ -from common.models import User, Company +from common.models import User from common.utils import INDCHOICES, COUNTRIES from phonenumber_field.modelfields import PhoneNumberField from django.utils.text import slugify @@ -70,10 +70,6 @@ class Account(models.Model): assigned_to = models.ManyToManyField(User, related_name="account_assigned_users") teams = models.ManyToManyField(Teams, related_name="account_teams") - company = models.ForeignKey( - Company, on_delete=models.SET_NULL, null=True, blank=True - ) - def __str__(self): return self.name diff --git a/accounts/serializer.py b/accounts/serializer.py index d85c1d2..483bee4 100644 --- a/accounts/serializer.py +++ b/accounts/serializer.py @@ -1,6 +1,6 @@ from rest_framework import serializers from accounts.models import Account, Email, Tags -from common.serializer import UserSerializer, CompanySerializer, AttachmentsSerializer +from common.serializer import UserSerializer, AttachmentsSerializer from leads.serializer import LeadSerializer from teams.serializer import TeamsSerializer from contacts.serializer import ContactSerializer @@ -15,7 +15,6 @@ class Meta: class AccountSerializer(serializers.ModelSerializer): created_by = UserSerializer() lead = LeadSerializer() - company = CompanySerializer() tags = TagsSerailizer(read_only=True, many=True) assigned_to = UserSerializer(read_only=True, many=True) contacts = ContactSerializer(read_only=True, many=True) @@ -50,26 +49,44 @@ class Meta: "contacts", "assigned_to", "teams", - "company", ) class EmailSerializer(serializers.ModelSerializer): + def __init__(self, *args, **kwargs): + request_obj = kwargs.pop("request_obj", None) + super(EmailSerializer, self).__init__(*args, **kwargs) + class Meta: model = Email fields = ( - "from_account" - "recipients" - "message_subject" - "message_body" - "timezone" - "scheduled_date_time" - "scheduled_later" - "created_on" - "from_email" - "rendered_message_body" + "message_subject", + "message_body", + "timezone", + "scheduled_date_time", + "scheduled_later", + "created_on", + "from_email", + "rendered_message_body", ) + def validate_message_body(self, message_body): + count = 0 + for i in message_body: + if i == "{": + count += 1 + elif i == "}": + count -= 1 + if count < 0: + raise serializers.ValidationError( + "Brackets do not match, Enter valid tags." + ) + if count != 0: + raise serializers.ValidationError( + "Brackets do not match, Enter valid tags." + ) + return message_body + class EmailLogSerializer(serializers.ModelSerializer): email = EmailSerializer() @@ -96,20 +113,17 @@ def __init__(self, *args, **kwargs): if self.instance: self.fields["lead"].required = False self.fields["lead"].required = False - self.company = request_obj.company def validate_name(self, name): if self.instance: if self.instance.name != name: - if not Account.objects.filter( - name__iexact=name, company=self.company - ).exists(): + if not Account.objects.filter(name__iexact=name).exists(): return name raise serializers.ValidationError( "Account already exists with this name" ) return name - if not Account.objects.filter(name__iexact=name, company=self.company).exists(): + if not Account.objects.filter(name__iexact=name).exists(): return name raise serializers.ValidationError("Account already exists with this name") diff --git a/accounts/swagger_params.py b/accounts/swagger_params.py index 77f7f1d..32b8dbb 100644 --- a/accounts/swagger_params.py +++ b/accounts/swagger_params.py @@ -1,23 +1,12 @@ from drf_yasg import openapi -company_params_in_header = openapi.Parameter( - "company", openapi.IN_HEADER, required=True, type=openapi.TYPE_STRING -) - - account_get_params = [ - company_params_in_header, openapi.Parameter("name", openapi.IN_QUERY, type=openapi.TYPE_STRING), openapi.Parameter("city", openapi.IN_QUERY, type=openapi.TYPE_STRING), openapi.Parameter("tags", openapi.IN_QUERY, type=openapi.TYPE_STRING), ] -account_get_detail_params = [ - company_params_in_header, -] - account_post_params = [ - company_params_in_header, openapi.Parameter( "name", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING ), @@ -67,12 +56,7 @@ openapi.Parameter("lead", openapi.IN_QUERY, type=openapi.TYPE_STRING), ] -company_params = [ - company_params_in_header, -] - account_detail_get_params = [ - company_params_in_header, openapi.Parameter( "account_attachment", openapi.IN_QUERY, @@ -82,12 +66,10 @@ ] account_comment_edit_params = [ - company_params_in_header, openapi.Parameter("comment", openapi.IN_QUERY, type=openapi.TYPE_STRING), ] account_detail_get_params = [ - company_params_in_header, openapi.Parameter( "account_attachment", openapi.IN_QUERY, @@ -97,6 +79,20 @@ ] account_comment_edit_params = [ - company_params_in_header, openapi.Parameter("comment", openapi.IN_QUERY, type=openapi.TYPE_STRING), ] + +account_mail_params = [ + openapi.Parameter("from_email", openapi.IN_QUERY, type=openapi.TYPE_STRING), + openapi.Parameter("recipients", openapi.IN_QUERY, type=openapi.TYPE_STRING), + openapi.Parameter("message_subject", openapi.IN_QUERY, type=openapi.TYPE_STRING), + openapi.Parameter("scheduled_later", openapi.IN_QUERY, type=openapi.TYPE_BOOLEAN), + openapi.Parameter("timezone", openapi.IN_QUERY, type=openapi.TYPE_STRING), + openapi.Parameter( + "scheduled_date_time", + openapi.IN_QUERY, + type=openapi.FORMAT_DATETIME, + example="2021-01-01 00:00", + ), + openapi.Parameter("message_body", openapi.IN_QUERY, type=openapi.TYPE_STRING), +] diff --git a/accounts/tasks.py b/accounts/tasks.py index bf6377c..aebcd75 100644 --- a/accounts/tasks.py +++ b/accounts/tasks.py @@ -11,7 +11,6 @@ from accounts.models import Account, Email, EmailLog from common.models import User from common.utils import convert_to_custom_timezone -from marketing.models import BlockedDomain, BlockedEmail app = Celery("redis://") @@ -19,8 +18,6 @@ @app.task def send_email(email_obj_id): email_obj = Email.objects.filter(id=email_obj_id).first() - blocked_domains = BlockedDomain.objects.values_list("domain", flat=True) - blocked_emails = BlockedEmail.objects.values_list("email", flat=True) if email_obj: from_email = email_obj.from_email contacts = email_obj.recipients.all() @@ -28,39 +25,36 @@ def send_email(email_obj_id): if not EmailLog.objects.filter( email=email_obj, contact=contact_obj, is_sent=True ).exists(): - if (contact_obj.email not in blocked_emails) and ( - contact_obj.email.split("@")[-1] not in blocked_domains - ): - html = email_obj.message_body - context_data = { - "email": contact_obj.email if contact_obj.email else "", - "name": contact_obj.first_name - if contact_obj.first_name - else "" + " " + contact_obj.last_name - if contact_obj.last_name - else "", - } - try: - html_content = Template(html).render(Context(context_data)) - subject = email_obj.message_subject - msg = EmailMessage( - subject, - html_content, - from_email=from_email, - to=[ - contact_obj.email, - ], + html = email_obj.message_body + context_data = { + "email": contact_obj.email if contact_obj.email else "", + "name": contact_obj.first_name + if contact_obj.first_name + else "" + " " + contact_obj.last_name + if contact_obj.last_name + else "", + } + try: + html_content = Template(html).render(Context(context_data)) + subject = email_obj.message_subject + msg = EmailMessage( + subject, + html_content, + from_email=from_email, + to=[ + contact_obj.email, + ], + ) + msg.content_subtype = "html" + res = msg.send() + if res: + email_obj.rendered_message_body = html_content + email_obj.save() + EmailLog.objects.create( + email=email_obj, contact=contact_obj, is_sent=True ) - msg.content_subtype = "html" - res = msg.send() - if res: - email_obj.rendered_message_body = html_content - email_obj.save() - EmailLog.objects.create( - email=email_obj, contact=contact_obj, is_sent=True - ) - except Exception as e: - print(e) + except Exception as e: + print(e) @app.task @@ -71,35 +65,24 @@ def send_email_to_assigned_user( account = Account.objects.filter(id=from_email).first() created_by = account.created_by - blocked_domains = BlockedDomain.objects.values_list("domain", flat=True) - blocked_emails = BlockedEmail.objects.values_list("email", flat=True) - for user in recipients: recipients_list = [] user = User.objects.filter(id=user, is_active=True).first() if user: - if (user.email not in blocked_emails) and ( - user.email.split("@")[-1] not in blocked_domains - ): - recipients_list.append(user.email) - context = {} - context["url"] = ( - protocol - + "://" - + domain - + reverse("accounts:view_account", args=(account.id,)) - ) - context["user"] = user - context["account"] = account - context["created_by"] = created_by - subject = "Assigned a account for you." - html_content = render_to_string( - "assigned_to/account_assigned.html", context=context - ) + recipients_list.append(user.email) + context = {} + context["url"] = protocol + "://" + domain + context["user"] = user + context["account"] = account + context["created_by"] = created_by + subject = "Assigned a account for you." + html_content = render_to_string( + "assigned_to/account_assigned.html", context=context + ) - msg = EmailMessage(subject, html_content, to=recipients_list) - msg.content_subtype = "html" - msg.send() + msg = EmailMessage(subject, html_content, to=recipients_list) + msg.content_subtype = "html" + msg.send() @app.task diff --git a/accounts/templates/accounts.html b/accounts/templates/accounts.html deleted file mode 100644 index 6634745..0000000 --- a/accounts/templates/accounts.html +++ /dev/null @@ -1,1011 +0,0 @@ -{% extends 'sales/base.html' %} -{% load static %} -{% load paginate %} -{% load thumbnail %} -{% block extralinks %} - - -{% endblock %} -{% block content %} - -
- - -
-
-
-
-
-
-
Filters
-
-
-
- - -
-
-
-
- - -
-
- -
-
- - -
-
-
-
- - Clear -
-
-
-
-
-
-
-
-
- - -
-
-
-
- -
-
-
-
-
- Open Accounts - {% if show_pageitems %} - {% show_pageitems %}{% else %}{{open_accounts|length}}{% endif %} - - - -
-
- - - {% if open_accounts|length > 0 %} - - - - - - - - - - - {% endif %} - - - {% if per_page %} - {% paginate per_page open_accounts %} - {% else%} - {% paginate 10 open_accounts %} - {% endif %} - {% for each_account in open_accounts %} - - - - - - - - - - - - {% endfor %} - -
IDNameCreated ByCityStateCreated OnTagsActions
{{ forloop.counter }}{% if each_account.name %}{{ each_account.name }}{% endif %} - - {% if each_account.created_by %} - {% if each_account.created_by.profile_pic %} - {% thumbnail each_account.created_by.profile_pic "40x40" crop="center" as im %} - - {% endthumbnail %} - {% else %} - Micro profile pic - {% endif %} - {% else %} - None - {% endif %} - {% if each_account.billing_city %}{{ each_account.billing_city }} {% else %} Not specified - {% endif %}{% if each_account.billing_state %}{{ each_account.billing_state }} {% else %} Not - specified {% endif %}{{ each_account.created_on_arrow }} - {% with tags=each_account.tags.all %} - {% if tags %} - {% for tag in tags %} - {{ tag.name }} - {% endfor %} - {% else %} - No Tags - {% endif %} - {% endwith %} - - {% if each_account.contacts.all %} - - {% endif %} - - - -
-
- {% ifequal open_accounts|length 0 %} -
No Acccount Records Found
- {% endifequal %} -
- {% show_pages %} -
-
-
-
-
-
-
-
- Closed Accounts - {% if show_pageitems %} - {% show_pageitems %}{% else %}{{close_accounts|length}}{% endif %} - - - -
-
- - - {% if close_accounts|length > 0 %} - - - - - - - - - - - {% endif %} - - - {% if per_page %} - {% paginate per_page close_accounts %} - {% else%} - {% paginate 10 close_accounts %} - {% endif %} - {% for each_account in close_accounts %} - - - - - - - - - - - {% endfor %} - -
IDNameCreated ByCityStateCreated OnTagsActions
{{ forloop.counter }}{% if each_account.name %}{{ each_account.name }}{% endif %} - - {% if each_account.created_by %} - {% if each_account.created_by.profile_pic %} - {% thumbnail each_account.created_by.profile_pic "40x40" crop="center" as im %} - - {% endthumbnail %} - {% else %} - Micro profile pic - {% endif %} - {% else %} - None - {% endif %} - {% if each_account.billing_city %}{{ each_account.billing_city }} {% else %} Not specified - {% endif %}{% if each_account.billing_state %}{{ each_account.billing_state }} {% else %} Not - specified {% endif %}{{ each_account.created_on_arrow }} - {% with tags=each_account.tags.all %} - {% if tags %} - {% for tag in tags %} - {{ tag.name }} - {% endfor %} - {% else %} - No Tags - {% endif %} - {% endwith %} - - - - -
-
- {% ifequal close_accounts|length 0 %} -
No Closed Acccount Records Found
- {% endifequal %} -
- {% show_pages %} -
-
-
-
-
-
-
-
-
-
- - - -
- - - -{% for account_record in open_accounts %} - - - -{% endfor %} - - - -{% for account_record in close_accounts %} - - - -{% endfor %} - - - -{% endblock %} -{% block js_block %} - - -{% endblock js_block %} \ No newline at end of file diff --git a/accounts/templates/create_account.html b/accounts/templates/create_account.html deleted file mode 100644 index 77dda80..0000000 --- a/accounts/templates/create_account.html +++ /dev/null @@ -1,539 +0,0 @@ -{% extends 'sales/base.html' %} -{% load static %} -{% block breadcrumb %} -{% block extralinks %} - -{% endblock %} - -{% endblock %} -{% block content %} -{% if contact_count or edit_view%} -
-
-
-
-
-
- {% if account_obj %}EDIT{% else %}CREATE{% endif %} ACCOUNT -
-
-
-
-
- - {{ account_form.name }} - {{ account_form.name.errors }} -
-
-
-
- - {{ account_form.website }} - {{ account_form.website.errors }} -
-
-
-
- - {{ account_form.phone }} - {{ account_form.phone.errors }} -
-
-
-
- - {{ account_form.email }} - {{ account_form.email.errors }} -
-
-
-
- - - {{ account_form.lead }} - {{ account_form.lead.errors }} -
-
-
-
-
-
- - {{ account_form.billing_address_line }} - {{ account_form.billing_address_line.errors }} -
-
-
-
- - {{ account_form.billing_street }} - {{ account_form.billing_street.errors }} -
-
-
-
- - {{ account_form.billing_postcode }} - {{ account_form.billing_postcode.errors }} -
-
-
-
- - {{ account_form.billing_city }} - {{ account_form.billing_city.errors }} -
-
-
-
- - {{ account_form.billing_state }} - {{ account_form.billing_state.errors }} -
-
-
-
- - {{ account_form.billing_country }} - {{ account_form.billing_country.errors }} -
-
-
-
- - {{ account_form.contacts }} - {{ account_form.contacts.errors }} -
-
-
-
-
-
Copy Address
-
-
-
- {% if request.user.is_superuser or request.user.role == 'ADMIN' %} -
-
- - - {{ account_form.teams.errors }} -
-
- -
-
- - -
-
- - {% endif %} -
-
- - - - {{ account_form.assigned_to.errors }} - - -
-
-
-
- - {{ account_form.status }} - {{ account_form.status.errors }} -
-
-
-
- -
-
-
-
-
-
- - - {% if account_obj.account_attachment.count %} - {% for attachment in account_obj.account_attachment.all %} -
- {{ attachment.file_name }} - {% if not attachment.created_by.role == 'ADMIN' or attachment.created_by.role == request.user.role %} - X - {% endif %} -
- {% endfor %} - {% endif %} - -
-
-
-
-
- - Cancel -
-
-
-
-
-
- -
- -
-{% else %} -
-

Create a contact to create an account

-
-{% endif %} -{% endblock %} -{% block js_block %} - - -{% endblock js_block %} \ No newline at end of file diff --git a/accounts/templates/create_mail_accounts.html b/accounts/templates/create_mail_accounts.html deleted file mode 100644 index 022c82e..0000000 --- a/accounts/templates/create_mail_accounts.html +++ /dev/null @@ -1,289 +0,0 @@ -{% extends 'sales/base.html' %} -{% load static %} -{% load paginate %} -{% block extralinks %} -{% load thumbnail %} - -{% endblock %} - -{% block breadcrumb %} - -{% endblock breadcrumb %} - -{% block content %} - -
- -
-
-
-
-
-
-
-
- Send Mail -
- -
-
-
- - - - -
- -
-
-
- - -
- -
-
-
-
-
- - -
-
- - -
-
-
-
- -
-
- - -
- -
-
Personalization tags
-

The following tags can be used on both Plain text or HTML. Add these tags to - customize the email template, these tags will be replaced with the associated contact details - while the mails are sent.

-
    -
  • - Name: - {% templatetag openvariable %} name {% templatetag closevariable %} -
  • -
  • - Email: - {% templatetag openvariable %} email {% templatetag closevariable %} -
  • - -
-
-
- - Cancel -
-
- -
-
-
-
- -
-
-
-{% endblock %} -{% block js_block %} - - -{% endblock js_block %} \ No newline at end of file diff --git a/accounts/templates/error_template.html b/accounts/templates/error_template.html deleted file mode 100644 index 72690fa..0000000 --- a/accounts/templates/error_template.html +++ /dev/null @@ -1,17 +0,0 @@ -{% extends 'base.html' %} -{% load static %} -{% load paginate %} -{% block content %} - -
- - -
-

create a contacts and leads to continue creating an account

-
- - - -
- -{% endblock %} diff --git a/accounts/templates/view_account.html b/accounts/templates/view_account.html deleted file mode 100644 index d4a03af..0000000 --- a/accounts/templates/view_account.html +++ /dev/null @@ -1,915 +0,0 @@ -{% extends 'sales/base.html' %} -{% load static %} -{% load thumbnail %} -{% block breadcrumb %} - -{% block extralinks %} - - -{% endblock extralinks %} - - - -{% endblock breadcrumb %} -{% block content %} - -
-
-
-
-
-
-
- Overview - - - -
-
-
-
- {% if account_record.name %} -
-
- - -
-
- {% endif %} - {% if account_record.phone %} -
-
- - -
-
- {% endif %} - {% if account_record.status %} -
-
- - -
-
- {% endif %} -
-
- {% if account_record.email %} -
-
- - -
-
- {% endif %} - {% if account_record.website %} -
-
- - -
-
- {% endif %} - {% if account_record.contacts.all %} -
-
- - {% for contact in account_record.contacts.all %} - - {% endfor %} -
-
- {% endif %} - {% if account_record.lead %} -
-
- - -
-
- {% endif %} -
-
- {% if account_record.billing_address_line or account_record.billing_street or account_record.billing_city or account_record.billing_state or account_record.billing_postcode or account_record.billing_country %} -
-
- - -
-
- {% endif %} -
- {% if account_record.assigned_to.all %} -
- -
- {% for user in account_record.assigned_to.all %} -
- {{user}} -
- {% endfor %} -
-
- {% endif %} -
- {% if account_record.description %} -
-
- - -
-
- {% endif %} - {% if account_record.tags.all %} -
-
- - -
-
- {% endif %} -
-
-
- Created by {{ account_record.created_by }} created on - {{ account_record.created_on_arrow }} -
-
-
- -
-
-
Attachments
-
-
-
-
-
- -
- -
-
-
- -
-
- -
-
    - {% for attachment in attachments %} -
  • - {% if request.user.is_superuser or request.user.role == 'ADMIN' or request.user == attachment.created_by %} -
    -
    - -
    -
    - {% endif %} -
    - {% if attachment.attachment %} - {% if 'image' in attachment.file_type %} - {% thumbnail attachment.attachment "80x80" crop="center" as im %} - - {% endthumbnail %} - {% endif %} - {% endif %} -
      {{attachment.file_name}} Download
    -
    -
    -
    Uploaded by :{{ attachment.created_by }}
    -
    {{ attachment.created_on_arrow }}
    -
    -
  • - {% endfor %} -
-
-
-
- - -
-
-
Comments
-
-
-
-
-
- -
- -
-
-
- -
-
- -
-
    - {% for comment in comments %} -
  • - {% if request.user.is_superuser or request.user.role == 'ADMIN' or request.user == comment.commented_by %} -
    - - -
    - {% endif %} -
    -
    {{ comment.comment }}
    -
    -
    -
    {{ comment.commented_by }}
    -
    {{ comment.commented_on_arrow }}
    -
    -
  • - {% endfor %} -
-
-
- -
- - -
-
-
-
-
-
-
-
-
-
-
- Contacts - - {% if contacts|length > 0 %} - - - {% endif %} -
-
- - {% if contacts|length > 0 %} - - - - - - - - - - {% endif %} - - {% for contact in contacts %} - - - - - - - - {% endfor %} - -
S.NoContact NamePhoneEmailActions
{{ forloop.counter }}{{ contact.first_name }} {{ contact.last_name }}{{ contact.phone }}{{ contact.email }} - View - Edit - Remove -
-
- {% ifequal contacts|length 0 %} -
No Contact Records Found
- {% endifequal %} -
-
-
-
-
-
-
-
-
-
-
-
- Opportunities - -
-
- - {% if opportunity_list|length > 0 %} - - - - - - - - - - {% endif %} - - {% for opportunity in opportunity_list %} - - - - - - - - {% endfor %} - -
S.NoNameStageProbabilityActions
{{ forloop.counter }}{{opportunity.name}}{{opportunity.stage}}{{opportunity.probability}} {% if opportunity.probability %} % - {% endif %} - View - Edit - Remove -
-
- {% ifequal opportunity_list|length 0 %} -
No Opportunity Records Found
- {% endifequal %} -
-
-
-
-
-
-
-
-
-
-
-
- Cases - -
-
- - {% if cases|length > 0 %} - - - - - - - - - - {% endif %} - - {% for case in cases %} - - - - - - - - {% endfor %} - -
S.NoNameStatusPriorityActions
{{ forloop.counter }}{{ case.name }}{{ case.status }}{{ case.priority }} - View - Edit - Remove -
-
- {% ifequal cases|length 0 %} -
No Case Records Found
- {% endifequal %} -
-
-
-
-
-
-
-
-
-
-
-
- Tasks - -
-
- - {% if tasks|length > 0 %} - - - - - - - - - - {% endif %} - - {% for task in tasks %} - - - - - - - - {% endfor %} - -
S.NoTitleStatusPriorityActions
{{ forloop.counter }}{{task.title}}{{task.status}}{{task.priority}} {% if task.probability %} % {% endif %} - View - Edit - Remove -
-
- {% ifequal tasks|length 0 %} -
No tasks Records Found
- {% endifequal %} -
-
-
-
-
-
-
-
-
-
-
-
- Invoices - -
-
- - {% if invoices|length > 0 %} - - - - - - - - - - {% endif %} - - {% for invoice in invoices %} - - - - - - - - {% endfor %} - -
S.NoTitleEmailStatusActions
{{ forloop.counter }}{{invoice.invoice_title}}{{invoice.email}}{{invoice.status}} {% if task.probability %} % {% endif %} - View - Edit - Remove -
-
- {% ifequal invoices|length 0 %} -
No invoices Records Found
- {% endifequal %} -
-
-
-
-
-
- -
-
-
-
-
-
- Sent Mails - -
-
- - {% if emails|length > 0 %} - - - - - - - - - - - {% endif %} - - {% for email in emails %} - - - - - - - - - {% endfor %} - -
S.NoFrom mailContactSubjectCreated On View
{{ forloop.counter }}{{email.from_email}}{{email.recipients.count}}{{email.message_subject}}{{email.created_on}} - View -
-
- {% ifequal emails|length 0 %} -
No Emails Records Found
- {% endifequal %} -
-
-
-
-
-
- -
-
- -
- Processing File... -
-
-
-
- - - - - -{% endblock content %} -{% block js_block %} - - - - - -{% endblock js_block %} \ No newline at end of file diff --git a/accounts/tests.py b/accounts/tests.py deleted file mode 100644 index 49da5ad..0000000 --- a/accounts/tests.py +++ /dev/null @@ -1,1058 +0,0 @@ -from django.core.files.uploadedfile import SimpleUploadedFile -from django.test import TestCase -from django.urls import reverse -from django.utils import timezone - -from accounts.models import Account, Tags, Email -from cases.models import Case -from common.models import Address, Attachments, Comment, User, Company -from contacts.models import Contact -from leads.models import Lead -from teams.models import Teams - - -class AccountCreateTest(object): - def setUp(self): - self.company, _ = Company.objects.get_or_create( - name="test company", address="IN", sub_domain="test", country="IN" - ) - self.user = User.objects.create( - first_name="johnAccount", - username="johnDoeAccount", - email="johnAccount@example.com", - role="ADMIN", - company=self.company, - ) - self.user.set_password("password") - self.user.save() - - self.user1 = User.objects.create( - first_name="jane", - username="janeAccount", - email="janeAccount@example.com", - role="USER", - has_sales_access=True, - company=self.company, - ) - self.user1.set_password("password") - self.user1.save() - - self.account = Account.objects.create( - name="john doe", - email="johndoe@example.com", - phone="123456789", - billing_address_line="", - billing_street="street name", - billing_city="city name", - billing_state="state", - billing_postcode="1234", - billing_country="US", - website="www.example.como", - created_by=self.user, - status="open", - industry="SOFTWARE", - description="Testing", - ) - self.case = Case.objects.create( - name="Jane doe", - case_type="Problem", - status="New", - account=self.account, - priority="Low", - description="case description", - created_by=self.user, - closed_on="2016-05-04", - ) - self.comment = Comment.objects.create( - comment="test comment", case=self.case, commented_by=self.user - ) - self.attachment = Attachments.objects.create( - attachment="image.png", - case=self.case, - created_by=self.user, - account=self.account, - ) - self.client.login(email="johnAccount@example.com", password="password") - self.lead = Lead.objects.create( - title="LeadCreation", - first_name="john lead", - last_name="doe", - email="johnLead@example.com", - address_line="", - street="street name", - city="city name", - state="state", - postcode="5079", - country="IN", - website="www.example.com", - status="assigned", - source="Call", - opportunity_amount="700", - description="lead description", - created_by=self.user, - ) - self.lead.assigned_to.add(self.user) - self.address = Address.objects.create( - street="street number", - city="city", - state="state", - postcode=12346, - country="IN", - ) - - self.contact = Contact.objects.create( - first_name="contact", - email="contact@example.com", - phone="12345", - address=self.address, - description="contact", - created_by=self.user, - ) - - self.contact_user1 = Contact.objects.create( - first_name="contact", - email="contactUser1@example.com", - address=self.address, - description="contact", - created_by=self.user1, - ) - - -class AccountsCreateTestCase(AccountCreateTest, TestCase): - def test_account_create_url(self): - response = self.client.get( - "/accounts/create/", - { - "name": "account", - "email": "johndoe@example.com", - "phone": "1234567891", - "billing_address_line": "address line", - "billing_street": "billing street", - "billing_city": "billing city", - "billing_state": "state", - "billing_postcode": "1234", - "billing_country": "IN", - "website": "www.example.com", - "industry": "SOFTWARE", - "description": "Testing", - }, - ) - self.assertEqual(response.status_code, 200) - - def test_account_create_html(self): - response = self.client.get( - "/accounts/create/", - { - "name": "account", - "email": "accountEmail@example.com", - "phone": "", - "billing_address_line": "", - "billing_street": "", - "billing_city": "city", - "billing_state": "state", - "billing_postcode": "1234", - "billing_country": "IN", - "website": "www.example.com", - "industry": "SOFTWARE", - "description": "Testing Done", - }, - ) - self.assertTemplateUsed(response, "create_account.html") - - -class AccountsListTestCase(AccountCreateTest, TestCase): - def test_accounts_list(self): - self.accounts = Account.objects.all() - response = self.client.get(reverse("accounts:list")) - self.assertEqual(response.status_code, 200) - self.assertTemplateUsed(response, "accounts.html") - - def test_accounts_list_queryset(self): - self.account = Account.objects.all() - data = { - "name": "name", - "city": "city", - "billing_address_line": "billing_address_line", - "billing_street": "billing_street", - "billing_city": "billing_city", - "billing_state": "billing_state", - "billing_postcode": "billing_postcode", - "billing_country": "billing_country", - } - response = self.client.post(reverse("accounts:list"), data) - self.assertEqual(response.status_code, 200) - self.assertTemplateUsed(response, "accounts.html") - - -class AccountsCountTestCase(AccountCreateTest, TestCase): - def test_accounts_list_count(self): - count = Account.objects.all().count() - self.assertEqual(count, 1) - - -class AccountsViewTestCase(AccountCreateTest, TestCase): - def test_accounts_view(self): - self.accounts = Account.objects.all() - response = self.client.get("/accounts/" + str(self.account.id) + "/view/") - self.assertEqual(response.status_code, 200) - self.assertTemplateUsed(response, "view_account.html") - - -class AccountsRemoveTestCase(AccountCreateTest, TestCase): - def test_accounts_remove(self): - response = self.client.get("/accounts/" + str(self.account.id) + "/delete/") - self.assertEqual(response["location"], "/accounts/") - - # def test_accounts_remove_status(self): - # Account.objects.filter(id=self.account.id).delete() - # response = self.client.get('/accounts/list/') - # self.assertEqual(response.status_code, 200) - - -class AccountsUpdateUrlTestCase(AccountCreateTest, TestCase): - def test_accounts_update(self): - response = self.client.get( - "/accounts/" + str(self.account.id) + "/edit/", - { - "name": "janedoe", - "email": "janeDoe@example.com", - "phone": "1234567891", - "billing_address_line": "", - "billing_street": "street", - "billing_city": "city", - "billing_state": "state", - "billing_postcode": "1234", - "billing_country": "IN", - "website": "www.example.com", - "industry": "SOFTWARE", - "description": "Test description", - }, - ) - self.assertEqual(response.status_code, 200) - self.assertTemplateUsed(response, "create_account.html") - - def test_accounts_update_post(self): - response = self.client.post( - "/accounts/" + str(self.account.id) + "/edit/", - { - "name": "janeDoe", - "email": "janeDoe@example.com", - "phone": "1234567891", - "billing_address_line": "", - "billing_street": "Stree", - "billing_city": "city", - "billing_state": "state", - "billing_postcode": "1234", - "billing_country": "IN", - "website": "www.example.com", - "industry": "SOFTWARE", - "description": "Testing Description", - }, - ) - self.assertEqual(response.status_code, 200) - self.assertTemplateUsed(response, "create_account.html") - - def test_accounts_update_status(self): - response = self.client.get("/accounts/" + str(self.account.id) + "/edit/") - self.assertEqual(response.status_code, 200) - - def test_accounts_update_html(self): - response = self.client.get("/accounts/" + str(self.account.id) + "/edit/") - self.assertTemplateUsed(response, "create_account.html") - - -class AccountCreateEmptyFormTestCase(AccountCreateTest, TestCase): - def test_account_creation_invalid_data(self): - data = { - "name": "", - "email": "", - "phone": "", - "website": "", - "industry": "", - "description": "", - "billing_address_line": "", - "billing_street": "", - "billing_city": "city", - "billing_state": "state", - "billing_postcode": "1234567897", - "billing_country": "IN", - } - response = self.client.post("/accounts/create/", data) - self.assertEqual(response.status_code, 200) - - -class AccountModelTest(AccountCreateTest, TestCase): - def test_string_representation(self): - account = Account( - name="Account name", - ) - self.assertEqual(str(account), account.name) - - def setUp(self): - self.company, _ = Company.objects.get_or_create( - name="test company", address="IN", sub_domain="test", country="IN" - ) - self.user = User.objects.create( - username="username", - email="email@email.com", - company=self.company, - ) - - -class CommentTestCase(AccountCreateTest, TestCase): - def test_comment_add(self): - response = self.client.post( - "/accounts/comment/add/", {"accountid": self.account.id} - ) - self.assertEqual(response.status_code, 200) - - def test_comment_create(self): - response = self.client.post( - "/accounts/comment/add/", - {"accountid": self.account.id, "comment": self.comment.id}, - ) - self.assertEqual(response.status_code, 200) - - def test_comment_creation(self): - self.client.login(email="mp@micropyramid.com", password="mp") - response = self.client.post( - "/accounts/comment/add/", - {"accountid": self.account.id, "comment": "comment"}, - ) - self.assertEqual(response.status_code, 200) - - def test_comment_edit(self): - self.client.login(email="mp@micropyramid.com", password="mp") - response = self.client.post( - "/accounts/comment/edit/", - {"commentid": self.comment.id, "comment": "comment"}, - ) - self.assertEqual(response.status_code, 200) - - def test_comment_update(self): - response = self.client.post( - "/accounts/comment/edit/", - {"commentid": self.comment.id, "comment": "comment"}, - ) - self.assertEqual(response.status_code, 200) - - # def test_comment_valid(self): - # url = "/accounts/comment/add/" - # data = {"comment": "hai", "commented_by": self.user, - # "account": self.account} - # response = self.client.post(url, data) - # print(url,response) - # self.assertEqual(response.status_code, 200) - - def test_comment_delete(self): - response = self.client.post( - "/accounts/comment/remove/", {"comment_id": self.comment.id} - ) - self.assertEqual(response.status_code, 200) - - def test_comment_deletion(self): - self.client.login(email="mp@micropyramid.com", password="mp") - response = self.client.post( - "/accounts/comment/remove/", {"comment_id": self.comment.id} - ) - self.assertEqual(response.status_code, 200) - - -class AttachmentTestCase(AccountCreateTest, TestCase): - def test_attachment_add(self): - self.client.login(email="janeAccount@example.com", password="password") - response = self.client.post( - "/accounts/attachment/add/", {"accountid": self.account.id} - ) - self.assertEqual(response.status_code, 200) - - def test_attachment_valid(self): - upload_file = open("static/images/user.png", "rb") - response = self.client.post( - "/accounts/attachment/add/", - { - "accountid": self.account.id, - "attachment": SimpleUploadedFile(upload_file.name, upload_file.read()), - }, - ) - self.assertEqual(response.status_code, 200) - - def test_attachment_delete(self): - response = self.client.post( - "/accounts/attachment/remove/", {"attachment_id": self.attachment.id} - ) - self.assertEqual(response.status_code, 200) - - def test_attachment_deletion(self): - self.client.login(email="janeAccount@example.com", password="password") - response = self.client.post( - "/accounts/attachment/remove/", {"attachment_id": self.attachment.id} - ) - self.assertEqual(response.status_code, 200) - - -class TagCreateTest(object): - def setUp(self): - self.tag = Tags.objects.create(name="tag", slug="tag1") - - -class TagModelTest(TagCreateTest, TestCase): - def test_string_representation(self): - tag = Tags(name="tag", slug="tag1") - self.assertEqual(str(self.tag.name), tag.name) - - -class TestCreateLeadPostView(AccountCreateTest, TestCase): - def test_create_lead_post_status(self): - upload_file = open("static/images/user.png", "rb") - response = self.client.post( - reverse("accounts:new_account"), - { - "name": "janeLead", - "email": "janeLead@example.com", - "phone": "+911234567891", - "billing_address_line": "address line", - "billing_street": "street name", - "billing_city": "city name", - "billing_state": "usa", - "billing_postcode": "1234", - "billing_country": "IN", - "website": "www.example.com", - "created_by": self.user, - "status": "open", - "industry": "SOFTWARE", - "description": "Test description", - "lead": str(self.lead.id), - "contacts": str(self.contact.id), - "tags": "tag1", - "account_attachment": SimpleUploadedFile( - upload_file.name, upload_file.read() - ), - }, - HTTP_X_REQUESTED_WITH="XMLHttpRequest", - ) - self.assertEqual(response.status_code, 200) - - def test_update_lead_post_status(self): - upload_file = open("static/images/user.png", "rb") - response = self.client.post( - reverse("accounts:edit_account", kwargs={"pk": self.account.id}), - { - "name": "janedoeLead", - "email": "janelead@example.com", - "phone": "91123456789", - "billing_address_line": "", - "billing_street": "stree", - "billing_city": "city", - "billing_state": "state name", - "billing_postcode": "123456", - "billing_country": "IN", - "website": "www.example.com", - "created_by": self.user, - "status": "open", - "industry": "SOFTWARE", - "description": "Testing Description", - "lead": str(self.lead.id), - "contacts": str(self.contact.id), - "tags": "tag1", - "account_attachment": SimpleUploadedFile( - upload_file.name, upload_file.read() - ), - }, - ) - self.assertEqual(response.status_code, 200) - - -class test_account_forms(AccountCreateTest, TestCase): - def test_account_form(self): - self.client.login(email="janeAccount@example.com", password="password") - response = self.client.get(reverse("accounts:new_account")) - self.assertEqual(200, response.status_code) - - response = self.client.get( - reverse("accounts:create_mail") + "?account_id={}".format(self.account.id) - ) - self.assertEqual(200, response.status_code) - - data = { - "account_id": self.account.id, - "message_body": "message body {{email}}", - "message_subject": "message subject", - "recipients": [self.contact.id, self.contact_user1.id], - "scheduled_date_time": timezone.now(), - } - - response = self.client.post(reverse("accounts:create_mail"), data) - self.assertEqual(200, response.status_code) - - data = { - "account_id": self.account.id, - "message_body": "message body {{email}", - "message_subject": "message subject", - "recipients": [self.contact.id, self.contact_user1.id], - "scheduled_date_time": "", - "scheduled_later": "true", - } - - response = self.client.post(reverse("accounts:create_mail"), data) - self.assertEqual(200, response.status_code) - - data = { - "account_id": self.account.id, - "message_body": "message body {{email}}}", - "message_subject": "message subject", - "recipients": [self.contact.id, self.contact_user1.id], - "scheduled_date_time": timezone.now().strftime("%Y-%m-%d %H:%M"), - } - - response = self.client.post(reverse("accounts:create_mail"), data) - self.assertEqual(200, response.status_code) - - data = { - "account_id": self.account.id, - "message_body": "message body {{email}}", - "message_subject": "message subject", - "recipients": [self.contact.id, self.contact_user1.id], - "scheduled_date_time": timezone.now().strftime("%Y-%m-%d %H:%M"), - "scheduled_later": "true", - } - response = self.client.post(reverse("accounts:create_mail"), data) - self.assertEqual(200, response.status_code) - - data = { - "account_id": self.account.id, - "message_body": "message body {{email}}", - "message_subject": "message subject", - "recipients": [self.contact.id, self.contact_user1.id], - "from_email": "jane@doe.com", - "timezone": "UTC", - } - response = self.client.post(reverse("accounts:create_mail"), data) - self.assertEqual(200, response.status_code) - - data = { - "account_id": 0, - "message_body": "message body {{email}}", - "message_subject": "message subject", - "recipients": [self.contact.id, self.contact_user1.id], - "from_email": "jane@doe.com", - "timezone": "UTC", - } - response = self.client.post(reverse("accounts:create_mail"), data) - self.assertEqual(200, response.status_code) - - data = { - "account_id": self.account.id, - "message_body": "message body {{email}}", - "message_subject": "message subject", - "recipients": [self.contact.id, self.contact_user1.id], - "from_email": "jane@doe.com", - "timezone": "UTC", - "scheduled_later": "true", - "scheduled_date_time": timezone.now().strftime("%Y-%m-%d %H:%M"), - } - response = self.client.post(reverse("accounts:create_mail"), data) - self.assertEqual(200, response.status_code) - - -class test_account_models(AccountCreateTest, TestCase): - def test_account_model(self): - self.account.billing_address_line = "billing address line" - self.account.save() - self.assertEqual( - "billing address line, street name, city name, state, 1234, United States", - self.account.get_complete_address(), - ) - self.account.billing_street = "billing street" - self.account.save() - self.assertEqual( - "billing address line, billing street, city name, state, 1234, United States", - self.account.get_complete_address(), - ) - self.account.billing_city = None - self.account.billing_address_line = None - self.account.billing_street = None - self.account.save() - self.assertEqual( - "state, 1234, United States", self.account.get_complete_address() - ) - self.account.billing_state = None - self.account.save() - self.assertEqual("1234, United States", self.account.get_complete_address()) - self.account.billing_postcode = None - self.account.save() - self.assertEqual("United States", self.account.get_complete_address()) - self.account.billing_country = None - self.account.save() - self.assertEqual("", self.account.get_complete_address()) - self.account.billing_city = "city" - self.account.save() - self.assertEqual("city", self.account.get_complete_address()) - self.assertEqual("", self.account.contact_values) - - -class test_account_views_list(AccountCreateTest, TestCase): - def test_account_views(self): - self.client.login(email="janeAccount@example.com", password="password") - response = self.client.get(reverse("accounts:list")) - self.assertEqual(200, response.status_code) - response = self.client.get(reverse("accounts:list") + "?tag=1") - self.assertEqual(200, response.status_code) - response = self.client.post( - reverse("accounts:list"), - { - "industry": "industry", - "tag": [ - 1, - ], - "tab_status": "true", - }, - ) - self.assertEqual(200, response.status_code) - self.tag_name = Tags.objects.create(name="tag name") - self.team_account = Teams.objects.create(name="dev team") - self.team_account.users.add(self.user1.id) - self.client.logout() - self.client.login(email="johnAccount@example.com", password="password") - response = self.client.post( - reverse("accounts:new_account"), - { - "name": "account", - "email": "johndoe@example.com", - "phone": "+911234567894", - "billing_address_line": "address line", - "billing_street": "billing street", - "billing_city": "billing city", - "billing_state": "state", - "billing_postcode": "1234", - "billing_country": "IN", - "website": "www.example.com", - "industry": "SOFTWARE", - "description": "Testing", - "contacts": [ - self.contact_user1.id, - ], - "tags": self.tag_name.name, - "assigned_to": [ - self.user.id, - ], - "teams": [ - self.team_account.id, - ], - }, - HTTP_X_REQUESTED_WITH="XMLHttpRequest", - ) - - response = self.client.post( - reverse("accounts:new_account"), - { - "name": "account", - "email": "johndoe@example.com", - "phone": "+911234567894", - "billing_address_line": "address line", - "billing_street": "billing street", - "billing_city": "billing city", - "billing_state": "state", - "billing_postcode": "1234", - "billing_country": "IN", - "website": "www.example.com", - "industry": "SOFTWARE", - "description": "Testing", - "contacts": [ - self.contact_user1.id, - ], - "tags": self.tag_name.name, - "assigned_to": [ - self.user.id, - ], - "teams": [ - self.team_account.id, - ], - }, - ) - self.assertEqual(response.status_code, 302) - - response = self.client.post( - reverse("accounts:new_account"), - { - "name": "account", - "email": "johndoe@example.com", - "phone": "+911234567894", - "billing_address_line": "address line", - "billing_street": "billing street", - "billing_city": "billing city", - "billing_state": "state", - "billing_postcode": "1234", - "billing_country": "IN", - "website": "www.example.com", - "industry": "SOFTWARE", - "description": "Testing", - "contacts": [ - self.contact_user1.id, - ], - "tags": self.tag_name.name, - "assigned_to": [ - self.user.id, - ], - "teams": [ - self.team_account.id, - ], - "savenewform": "true", - }, - ) - self.assertEqual(response.status_code, 302) - - response = self.client.post( - reverse("accounts:new_account"), - { - "name": "account", - "email": "johndoe@example.com", - "phone": "+91123456789", - "billing_address_line": "address line", - "billing_street": "billing street", - "billing_city": "billing city", - "billing_state": "state", - "billing_postcode": "1234", - "billing_country": "IN", - "website": "www.example.com", - "industry": "SOFTWARE", - "description": "Testing", - "tags": self.tag_name.name, - "assigned_to": [ - 0, - ], - "teams": [ - 0, - ], - }, - HTTP_X_REQUESTED_WITH="XMLHttpRequest", - ) - self.assertEqual(response.status_code, 200) - - self.client.logout() - self.client.login(email="janeAccount@example.com", password="password") - response = self.client.get( - reverse("accounts:view_account", args=(self.account.id,)) - ) - self.assertEqual(403, response.status_code) - - self.client.logout() - self.client.login(email="johnAccount@example.com", password="password") - response = self.client.post( - reverse("accounts:new_account"), - { - "name": "account", - "email": "johndoe@example.com", - "phone": "+91-123-456-789", - "billing_address_line": "address line", - "billing_street": "billing street", - "billing_city": "billing city", - "billing_state": "state", - "billing_postcode": "1234", - "billing_country": "IN", - "website": "www.example.com", - "industry": "SOFTWARE", - "description": "Testing", - "contacts": [ - self.contact_user1.id, - ], - "tags": self.tag_name.name, - "assigned_to": [ - self.user.id, - ], - "teams": [ - self.team_account.id, - ], - }, - HTTP_X_REQUESTED_WITH="XMLHttpRequest", - ) - self.assertEqual(200, response.status_code) - - self.account_edit = Account.objects.create( - name="account edit", - email="johndoe@example.com", - phone="123456789", - billing_address_line="", - billing_street="street name", - billing_city="city name", - billing_state="state", - billing_postcode="1234", - billing_country="US", - website="www.example.como", - created_by=self.user, - status="open", - industry="SOFTWARE", - description="Testing", - ) - self.account_by_user = Account.objects.create( - name="account edit", - email="johndoe@example.com", - phone="123456789", - billing_address_line="", - billing_street="street name", - billing_city="city name", - billing_state="state", - billing_postcode="1234", - billing_country="US", - website="www.example.como", - created_by=self.user, - status="open", - industry="SOFTWARE", - description="Testing", - ) - upload_file = open("static/images/user.png", "rb") - response = self.client.post( - reverse("accounts:edit_account", args=(self.account_edit.id,)), - { - "name": "account", - "email": "johndoe@example.com", - "phone": "+91-123-456-7894", - "billing_address_line": "address line", - "billing_street": "billing street", - "billing_city": "billing city", - "billing_state": "state", - "billing_postcode": "1234", - "billing_country": "IN", - "website": "www.example.com", - "industry": "SOFTWARE", - "description": "Testing", - "contacts": [ - self.contact_user1.id, - ], - "tags": self.tag_name.name + ", another tag edit", - "assigned_to": [ - self.user.id, - ], - "teams": [ - self.team_account.id, - ], - "savenewform": "true", - "account_attachment": SimpleUploadedFile( - upload_file.name, upload_file.read() - ), - }, - ) - self.assertEqual(response.status_code, 302) - response = self.client.post( - reverse("accounts:edit_account", args=(self.account_edit.id,)), - { - "name": "account", - "email": "johndoe@example.com", - "phone": "+91-123-456-7894", - "billing_address_line": "address line", - "billing_street": "billing street", - "billing_city": "billing city", - "billing_state": "state", - "billing_postcode": "1234", - "billing_country": "IN", - "website": "www.example.com", - "industry": "SOFTWARE", - "description": "Testing", - "contacts": [ - self.contact_user1.id, - ], - "tags": self.tag_name.name + ", another tag edit", - "teams": [ - self.team_account.id, - ], - "savenewform": "true", - }, - HTTP_X_REQUESTED_WITH="XMLHttpRequest", - ) - self.assertEqual(response.status_code, 200) - response = self.client.post( - reverse("accounts:edit_account", args=(self.account_edit.id,)), - { - "name": "account", - "email": "johndoe@example.com", - "phone": "+91-123-456 ", - "billing_address_line": "address line", - "billing_street": "billing street", - "billing_city": "billing city", - "billing_state": "state", - "billing_postcode": "1234", - "billing_country": "IN", - "website": "www.example.com", - "industry": "SOFTWARE", - "description": "Testing", - "contacts": [ - self.contact_user1.id, - ], - "tags": self.tag_name.name + ", another tag edit", - "teams": [ - self.team_account.id, - ], - "savenewform": "true", - }, - HTTP_X_REQUESTED_WITH="XMLHttpRequest", - ) - self.assertEqual(response.status_code, 200) - - self.client.logout() - self.client.login(email="janeAccount@example.com", password="password") - response = self.client.get( - reverse("accounts:edit_account", args=(self.account_by_user.id,)), {} - ) - self.assertEqual(403, response.status_code) - self.account_by_user1 = Account.objects.create( - name="account edit", - email="johndoe@example.com", - phone="123456789", - billing_address_line="", - billing_street="street name", - billing_city="city name", - billing_state="state", - billing_postcode="1234", - billing_country="US", - website="www.example.como", - created_by=self.user1, - status="open", - industry="SOFTWARE", - description="Testing", - ) - response = self.client.get( - reverse("accounts:edit_account", args=(self.account_by_user1.id,)), {} - ) - self.assertEqual(200, response.status_code) - response = self.client.get( - reverse("accounts:remove_account", args=(self.account_by_user.id,)), {} - ) - self.assertEqual(403, response.status_code) - - response = self.client.post( - reverse("accounts:add_comment"), {"accountid": self.account_by_user.id} - ) - self.assertEqual(200, response.status_code) - - response = self.client.post( - reverse("accounts:edit_comment"), {"commentid": self.comment.id} - ) - self.assertEqual(200, response.status_code) - - self.client.logout() - self.client.login(email="johnAccount@example.com", password="password") - - response = self.client.post( - reverse("accounts:edit_comment"), - {"commentid": self.comment.id, "comment": ""}, - ) - self.assertEqual(200, response.status_code) - - self.client.logout() - self.client.login(email="janeAccount@example.com", password="password") - response = self.client.post( - reverse("accounts:remove_comment"), - {"comment_id": self.comment.id, "comment": ""}, - ) - self.assertEqual(200, response.status_code) - - self.client.logout() - self.client.login(email="johnAccount@example.com", password="password") - - response = self.client.post( - reverse("accounts:add_attachment"), - {"accountid": self.account.id, "comment": ""}, - ) - self.assertEqual(200, response.status_code) - - email_str = Email.objects.create( - message_subject="message subject", message_body="message body" - ) - self.assertEqual(str(email_str), "message subject") - - response = self.client.post( - reverse("accounts:get_contacts_for_account"), - {"account_id": self.account.id}, - ) - self.assertEqual(200, response.status_code) - - self.account.contacts.add(self.contact.id, self.contact_user1.id) - - response = self.client.post( - reverse("accounts:get_contacts_for_account"), - {"account_id": self.account.id}, - ) - self.assertEqual(200, response.status_code) - - response = self.client.get( - reverse("accounts:get_contacts_for_account"), - {"account_id": self.account.id}, - ) - self.assertEqual(200, response.status_code) - - response = self.client.post( - reverse("accounts:get_email_data_for_account"), - {"email_account_id": email_str.id}, - ) - self.assertEqual(200, response.status_code) - - response = self.client.get( - reverse("accounts:get_email_data_for_account"), - {"email_account_id": email_str.id}, - ) - self.assertEqual(200, response.status_code) - - -class TestAccountUserMentions(AccountCreateTest, TestCase): - def test_account_views(self): - self.company, _ = Company.objects.get_or_create( - name="test company", - address="IN", - sub_domain="test", - country="IN", - ) - self.user_created_by = User.objects.create( - first_name="jane", - username="janeAccountCreatedBy", - email="janeAccountCreatedBy@example.com", - role="USER", - has_sales_access=True, - company=self.company, - ) - self.user_created_by.set_password("password") - self.user_created_by.save() - - self.user_assigned_to = User.objects.create( - first_name="jane", - username="janeAccountUserAssigned", - email="janeAccountUserAssigned@example.com", - role="USER", - has_sales_access=True, - company=self.company, - ) - self.user_assigned_to.set_password("password") - self.user_assigned_to.save() - - self.account = Account.objects.create( - name="john doe acc created by", - email="johndoe@example.com", - phone="123456789", - billing_address_line="", - billing_street="street name", - billing_city="city name", - billing_state="state", - billing_postcode="1234", - billing_country="US", - website="www.example.como", - created_by=self.user_created_by, - status="open", - industry="SOFTWARE", - description="Testing", - ) - - self.account.assigned_to.add(self.user_assigned_to.id) - self.client.logout() - self.client.login(email="janeAccountCreatedBy@example.com", password="password") - response = self.client.get( - reverse("accounts:view_account", args=(self.account.id,)) - ) - self.assertEqual(200, response.status_code) - - self.client.logout() - self.client.login( - email="janeAccountUserAssigned@example.com", password="password" - ) - response = self.client.get( - reverse("accounts:view_account", args=(self.account.id,)) - ) - self.assertEqual(200, response.status_code) diff --git a/accounts/urls.py b/accounts/urls.py deleted file mode 100644 index 2e0a642..0000000 --- a/accounts/urls.py +++ /dev/null @@ -1,47 +0,0 @@ -from django.urls import path -from accounts.views import ( - AccountsListView, - CreateAccountView, - AccountDetailView, - AccountUpdateView, - AccountDeleteView, - AddCommentView, - UpdateCommentView, - DeleteCommentView, - AddAttachmentView, - DeleteAttachmentsView, - create_mail, # get_account_details, - get_contacts_for_account, - get_email_data_for_account, - get_teams_and_users, -) - -app_name = "accounts" - -urlpatterns = [ - path("", AccountsListView.as_view(), name="list"), - path("create/", CreateAccountView.as_view(), name="new_account"), - path("/view/", AccountDetailView.as_view(), name="view_account"), - path("/edit/", AccountUpdateView.as_view(), name="edit_account"), - path("/delete/", AccountDeleteView.as_view(), name="remove_account"), - path("comment/add/", AddCommentView.as_view(), name="add_comment"), - path("comment/edit/", UpdateCommentView.as_view(), name="edit_comment"), - path("comment/remove/", DeleteCommentView.as_view(), name="remove_comment"), - path("attachment/add/", AddAttachmentView.as_view(), name="add_attachment"), - path( - "attachment/remove/", DeleteAttachmentsView.as_view(), name="remove_attachment" - ), - path("create-mail", create_mail, name="create_mail"), - path( - "get_contacts_for_account/", - get_contacts_for_account, - name="get_contacts_for_account", - ), - path( - "get_email_data_for_account/", - get_email_data_for_account, - name="get_email_data_for_account", - ), - path("get_teams_and_users/", get_teams_and_users, name="get_teams_and_users"), - # path('get-account-details//', get_account_details, name="get_account_details"), -] diff --git a/accounts/views.py b/accounts/views.py deleted file mode 100644 index 3280ecc..0000000 --- a/accounts/views.py +++ /dev/null @@ -1,805 +0,0 @@ -import pytz -from django.conf import settings -from django.contrib.auth.decorators import login_required -from django.contrib.auth.mixins import LoginRequiredMixin -from django.contrib.sites.shortcuts import get_current_site -from django.core.exceptions import PermissionDenied -from django.db.models import Q -from django.http import HttpResponse, JsonResponse -from django.shortcuts import get_object_or_404, redirect, render -from django.urls import reverse, reverse_lazy -from django.views.generic import ( - CreateView, - DeleteView, - DetailView, - FormView, - TemplateView, - UpdateView, - View, -) - -from accounts.forms import ( - AccountAttachmentForm, - AccountCommentForm, - AccountForm, - EmailForm, -) -from accounts.models import Account, Email, Tags -from accounts.tasks import send_email, send_email_to_assigned_user -from cases.models import Case -from common.access_decorators_mixins import ( - MarketingAccessRequiredMixin, - SalesAccessRequiredMixin, - marketing_access_required, - sales_access_required, -) -from common.models import Attachments, Comment, User -from common.tasks import send_email_user_mentions -from common.utils import ( - CASE_TYPE, - COUNTRIES, - CURRENCY_CODES, - INDCHOICES, - PRIORITY_CHOICE, - STATUS_CHOICE, -) -from contacts.models import Contact -from leads.models import Lead -from opportunity.models import SOURCES, STAGES, Opportunity -from teams.models import Teams - - -@login_required -def get_teams_and_users(request): - data = {} - teams = Teams.objects.all() - teams_data = [ - {"team": team.id, "users": [user.id for user in team.users.all()]} - for team in teams - ] - users = User.objects.all().values_list("id", flat=True) - data["teams"] = teams_data - data["users"] = list(users) - return JsonResponse(data) - - -class AccountsListView(SalesAccessRequiredMixin, LoginRequiredMixin, TemplateView): - model = Account - context_object_name = "accounts_list" - template_name = "accounts.html" - - def get_queryset(self): - queryset = self.model.objects.all() - if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: - queryset = queryset.filter( - Q(created_by=self.request.user) | Q(assigned_to=self.request.user) - ).distinct() - - if self.request.GET.get("tag", None): - queryset = queryset.filter(tags__in=self.request.GET.getlist("tag")) - - request_post = self.request.POST - if request_post: - if request_post.get("name"): - queryset = queryset.filter(name__icontains=request_post.get("name")) - if request_post.get("city"): - queryset = queryset.filter( - billing_city__contains=request_post.get("city") - ) - if request_post.get("industry"): - queryset = queryset.filter( - industry__icontains=request_post.get("industry") - ) - if request_post.get("tag"): - queryset = queryset.filter(tags__in=request_post.getlist("tag")) - - return queryset.filter(company=self.request.company).distinct() - - def get_context_data(self, **kwargs): - context = super(AccountsListView, self).get_context_data(**kwargs) - open_accounts = self.get_queryset().filter(status="open") - close_accounts = self.get_queryset().filter(status="close") - context["accounts_list"] = self.get_queryset() - context["users"] = User.objects.filter(is_active=True).order_by("email") - context["open_accounts"] = open_accounts - context["close_accounts"] = close_accounts - context["industries"] = INDCHOICES - context["per_page"] = self.request.POST.get("per_page") - tag_ids = list(set(Account.objects.values_list("tags", flat=True))) - context["tags"] = Tags.objects.filter(id__in=tag_ids) - if self.request.POST.get("tag", None): - context["request_tags"] = self.request.POST.getlist("tag") - elif self.request.GET.get("tag", None): - context["request_tags"] = self.request.GET.getlist("tag") - else: - context["request_tags"] = None - - search = False - if ( - self.request.POST.get("name") - or self.request.POST.get("city") - or self.request.POST.get("industry") - or self.request.POST.get("tag") - ): - search = True - - context["search"] = search - - tab_status = "Open" - if self.request.POST.get("tab_status"): - tab_status = self.request.POST.get("tab_status") - context["tab_status"] = tab_status - TIMEZONE_CHOICES = [(tz, tz) for tz in pytz.common_timezones] - context["timezones"] = TIMEZONE_CHOICES - context["settings_timezone"] = settings.TIME_ZONE - - return context - - def get(self, request, *args, **kwargs): - context = self.get_context_data(**kwargs) - return self.render_to_response(context) - - def post(self, request, *args, **kwargs): - context = self.get_context_data(**kwargs) - return self.render_to_response(context) - - -class CreateAccountView(SalesAccessRequiredMixin, LoginRequiredMixin, CreateView): - model = Account - form_class = AccountForm - template_name = "create_account.html" - - def dispatch(self, request, *args, **kwargs): - if self.request.user.role == "ADMIN" or self.request.user.is_superuser: - self.users = User.objects.filter( - is_active=True, company=request.company - ).order_by("email") - elif request.user.google.all(): - self.users = [] - else: - self.users = User.objects.filter( - role="ADMIN", company=request.company - ).order_by("email") - return super(CreateAccountView, self).dispatch(request, *args, **kwargs) - - def get_form_kwargs(self): - kwargs = super(CreateAccountView, self).get_form_kwargs() - kwargs.update({"account": True}) - kwargs.update({"request_user": self.request.user}) - kwargs.update({"request_obj": self.request}) - # if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: - # kwargs.update({"request_user": self.request.user}) - return kwargs - - def post(self, request, *args, **kwargs): - self.object = None - form = self.get_form() - if form.is_valid(): - return self.form_valid(form) - - return self.form_invalid(form) - - def form_valid(self, form): - # Save Account - account_object = form.save(commit=False) - account_object.created_by = self.request.user - account_object.company = self.request.company - account_object.save() - - if self.request.POST.get("tags", ""): - tags = self.request.POST.get("tags") - splitted_tags = tags.split(",") - for t in splitted_tags: - tag = Tags.objects.filter(name=t) - if tag: - tag = tag[0] - else: - tag = Tags.objects.create(name=t) - account_object.tags.add(tag) - if self.request.POST.getlist("contacts", []): - account_object.contacts.add(*self.request.POST.getlist("contacts")) - if self.request.POST.getlist("assigned_to", []): - account_object.assigned_to.add(*self.request.POST.getlist("assigned_to")) - if self.request.FILES.get("account_attachment"): - attachment = Attachments() - attachment.created_by = self.request.user - attachment.file_name = self.request.FILES.get("account_attachment").name - attachment.account = account_object - attachment.attachment = self.request.FILES.get("account_attachment") - attachment.save() - if self.request.POST.getlist("teams", []): - user_ids = Teams.objects.filter( - id__in=self.request.POST.getlist("teams") - ).values_list("users", flat=True) - assinged_to_users_ids = account_object.assigned_to.all().values_list( - "id", flat=True - ) - for user_id in user_ids: - if user_id not in assinged_to_users_ids: - account_object.assigned_to.add(user_id) - if self.request.POST.getlist("teams", []): - account_object.teams.add(*self.request.POST.getlist("teams")) - - assigned_to_list = list( - account_object.assigned_to.all().values_list("id", flat=True) - ) - current_site = get_current_site(self.request) - recipients = assigned_to_list - send_email_to_assigned_user.delay( - recipients, - account_object.id, - domain=current_site.domain, - protocol=self.request.scheme, - ) - - if self.request.POST.get("savenewform"): - return redirect("accounts:new_account") - - if self.request.is_ajax(): - data = { - "success_url": reverse_lazy("accounts:list"), - "error": False, - "message": "Account created successfully", - } - return JsonResponse(data) - - return redirect("accounts:list") - - def form_invalid(self, form): - if self.request.is_ajax(): - return JsonResponse({"error": True, "errors": form.errors}) - return self.render_to_response(self.get_context_data(form=form)) - - def get_context_data(self, **kwargs): - context = super(CreateAccountView, self).get_context_data(**kwargs) - context["account_form"] = context["form"] - context["users"] = self.users - context["industries"] = INDCHOICES - context["countries"] = COUNTRIES - # context["contact_count"] = Contact.objects.count() - if self.request.user.role == "ADMIN" or self.request.user.is_superuser: - context["leads"] = Lead.objects.exclude( - status__in=["converted", "closed"], - company=self.request.company, - ) - context["contacts"] = Contact.objects.filter( - company=self.request.company, - ) - else: - context["leads"] = ( - Lead.objects.filter( - Q(assigned_to__in=[self.request.user]) - | Q(created_by=self.request.user) - ) - .exclude(status__in=["converted", "closed"]) - .filter( - company=self.request.company, - ) - ) - context["lead_count"] = context["leads"].count() - if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: - context["lead_count"] = ( - Lead.objects.filter( - Q(assigned_to__in=[self.request.user]) - | Q(created_by=self.request.user) - ) - .filter( - company=self.request.company, - ) - .exclude(status="closed") - .count() - ) - context["contacts"] = Contact.objects.filter( - Q(assigned_to__in=[self.request.user]) | Q(created_by=self.request.user) - ).filter( - company=self.request.company, - ) - context["contact_count"] = context["contacts"].count() - context["teams"] = Teams.objects.filter( - company=self.request.company, - ) - return context - - -class AccountDetailView(SalesAccessRequiredMixin, LoginRequiredMixin, DetailView): - model = Account - context_object_name = "account_record" - template_name = "view_account.html" - - def dispatch(self, request, *args, **kwargs): - account = self.get_object() - if account.company != request.company: - raise PermissionDenied - return super(AccountDetailView, self).dispatch(request, *args, **kwargs) - - def get_context_data(self, **kwargs): - context = super(AccountDetailView, self).get_context_data(**kwargs) - account_record = context["account_record"] - if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: - if not ( - (self.request.user == account_record.created_by) - or (self.request.user in account_record.assigned_to.all()) - ): - raise PermissionDenied - - comment_permission = ( - True - if ( - self.request.user == account_record.created_by - or self.request.user.is_superuser - or self.request.user.role == "ADMIN" - ) - else False - ) - - if self.request.user.is_superuser or self.request.user.role == "ADMIN": - users_mention = list( - User.objects.filter( - is_active=True, - company=self.request.company, - ).values("username") - ) - elif self.request.user != account_record.created_by: - if account_record.created_by: - users_mention = [{"username": account_record.created_by.username}] - else: - users_mention = [] - else: - users_mention = [] - - context.update( - { - "comments": account_record.accounts_comments.all(), - "attachments": account_record.account_attachment.all(), - "opportunity_list": Opportunity.objects.filter(account=account_record), - "contacts": account_record.contacts.all(), - "users": User.objects.filter( - is_active=True, - company=self.request.company, - ).order_by("email"), - "cases": Case.objects.filter(account=account_record), - "stages": STAGES, - "sources": SOURCES, - "countries": COUNTRIES, - "currencies": CURRENCY_CODES, - "case_types": CASE_TYPE, - "case_priority": PRIORITY_CHOICE, - "case_status": STATUS_CHOICE, - "comment_permission": comment_permission, - "tasks": account_record.accounts_tasks.all(), - "invoices": account_record.accounts_invoices.all(), - "emails": account_record.sent_email.all(), - "users_mention": users_mention, - } - ) - return context - - -class AccountUpdateView(SalesAccessRequiredMixin, LoginRequiredMixin, UpdateView): - model = Account - form_class = AccountForm - template_name = "create_account.html" - - def dispatch(self, request, *args, **kwargs): - self.users = User.objects.filter(is_active=True).order_by("email") - lead_obj = self.get_object() - self.account_status = lead_obj.status - if lead_obj.company != request.company: - raise PermissionDenied - # if self.request.user.role == 'ADMIN' or self.request.user.is_superuser: - # elif request.user.google.all(): - # self.users = [] - # else: - # self.users = User.objects.filter(role='ADMIN').order_by('email') - return super(AccountUpdateView, self).dispatch(request, *args, **kwargs) - - def get_form_kwargs(self): - kwargs = super(AccountUpdateView, self).get_form_kwargs() - kwargs.update({"account": True}) - kwargs.update({"request_user": self.request.user}) - kwargs.update({"request_obj": self.request}) - # if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: - # kwargs.update({"request_user": self.request.user}) - return kwargs - - def post(self, request, *args, **kwargs): - self.object = self.get_object() - form = self.get_form() - if form.is_valid(): - return self.form_valid(form) - - return self.form_invalid(form) - - def form_valid(self, form): - # Save Account - account_object = form.save(commit=False) - account_object.save() - previous_assigned_to_users = list( - account_object.assigned_to.all().values_list("id", flat=True) - ) - account_object.tags.clear() - if self.request.POST.get("tags", ""): - tags = self.request.POST.get("tags") - splitted_tags = tags.split(",") - for t in splitted_tags: - tag = Tags.objects.filter(name=t.lower()) - if tag: - tag = tag[0] - else: - tag = Tags.objects.create(name=t.lower()) - account_object.tags.add(tag) - if self.request.POST.getlist("contacts", []): - account_object.contacts.clear() - account_object.contacts.add(*self.request.POST.getlist("contacts")) - if self.request.POST.getlist("assigned_to", []): - account_object.assigned_to.clear() - account_object.assigned_to.add(*self.request.POST.getlist("assigned_to")) - else: - account_object.assigned_to.clear() - if self.request.FILES.get("account_attachment"): - attachment = Attachments() - attachment.created_by = self.request.user - attachment.file_name = self.request.FILES.get("account_attachment").name - attachment.account = account_object - attachment.attachment = self.request.FILES.get("account_attachment") - attachment.save() - - if self.request.POST.getlist("teams", []): - account_object.teams.clear() - account_object.teams.add(*self.request.POST.getlist("teams")) - else: - account_object.teams.clear() - if self.request.POST.getlist("teams", []): - user_ids = Teams.objects.filter( - id__in=self.request.POST.getlist("teams") - ).values_list("users", flat=True) - assinged_to_users_ids = account_object.assigned_to.all().values_list( - "id", flat=True - ) - for user_id in user_ids: - if user_id not in assinged_to_users_ids: - account_object.assigned_to.add(user_id) - - assigned_to_list = list( - account_object.assigned_to.all().values_list("id", flat=True) - ) - current_site = get_current_site(self.request) - recipients = list(set(assigned_to_list) - set(previous_assigned_to_users)) - send_email_to_assigned_user.delay( - recipients, - account_object.id, - domain=current_site.domain, - protocol=self.request.scheme, - ) - message = "Account updated successfully" - if self.account_status != account_object.status: - if account_object.status == "open": - message = "Account opened successfully" - else: - message = "Account closed successfully" - if self.request.is_ajax(): - data = { - "success_url": reverse_lazy("accounts:list"), - "error": False, - "message": message, - } - return JsonResponse(data) - return redirect("accounts:list") - - def form_invalid(self, form): - if self.request.is_ajax(): - return JsonResponse({"error": True, "errors": form.errors}) - return self.render_to_response(self.get_context_data(form=form)) - - def get_context_data(self, **kwargs): - context = super(AccountUpdateView, self).get_context_data(**kwargs) - context["account_obj"] = self.object - if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: - if (self.request.user != context["account_obj"].created_by) and ( - self.request.user not in context["account_obj"].assigned_to.all() - ): - raise PermissionDenied - context["account_form"] = context["form"] - if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: - self.users = self.users.filter( - Q(role="ADMIN") - | Q( - id__in=[ - self.request.user.id, - ] - ) - ) - context["users"] = self.users - context["industries"] = INDCHOICES - context["countries"] = COUNTRIES - context["contact_count"] = Contact.objects.count() - context["edit_view"] = True - if self.request.user.role == "ADMIN": - context["leads"] = Lead.objects.exclude(status__in=["converted", "closed"]) - else: - context["leads"] = Lead.objects.filter( - Q(assigned_to__in=[self.request.user]) | Q(created_by=self.request.user) - ).exclude(status__in=["converted", "closed"]) - context["lead_count"] = context["leads"].count() - if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: - context["lead_count"] = ( - Lead.objects.filter( - Q(assigned_to__in=[self.request.user]) - | Q(created_by=self.request.user) - ) - .exclude(status="closed") - .count() - ) - context["teams"] = Teams.objects.all() - return context - - -class AccountDeleteView(SalesAccessRequiredMixin, LoginRequiredMixin, DeleteView): - model = Account - template_name = "view_account.html" - - def get(self, request, *args, **kwargs): - self.object = self.get_object() - if self.object.company != request.company: - raise PermissionDenied - if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: - if self.request.user != self.object.created_by: - raise PermissionDenied - self.object.delete() - return redirect("accounts:list") - - -class AddCommentView(LoginRequiredMixin, CreateView): - model = Comment - form_class = AccountCommentForm - http_method_names = ["post"] - - def post(self, request, *args, **kwargs): - self.object = None - self.account = get_object_or_404(Account, id=request.POST.get("accountid")) - if ( - request.user == self.account.created_by - or request.user.is_superuser - or request.user.role == "ADMIN" - or request.user in self.account.assigned_to.all() - ): - form = self.get_form() - if form.is_valid(): - return self.form_valid(form) - return self.form_invalid(form) - - data = {"error": "You don't have permission to comment for this account."} - return JsonResponse(data) - - def form_valid(self, form): - comment = form.save(commit=False) - comment.commented_by = self.request.user - comment.account = self.account - comment.save() - comment_id = comment.id - current_site = get_current_site(self.request) - send_email_user_mentions.delay( - comment_id, - "accounts", - domain=current_site.domain, - protocol=self.request.scheme, - ) - - return JsonResponse( - { - "comment_id": comment.id, - "comment": comment.comment, - "commented_on": comment.commented_on, - "commented_on_arrow": comment.commented_on_arrow, - "commented_by": comment.commented_by.email, - } - ) - - def form_invalid(self, form): - return JsonResponse({"error": form["comment"].errors}) - - -class UpdateCommentView(LoginRequiredMixin, View): - http_method_names = ["post"] - - def post(self, request, *args, **kwargs): - self.comment_obj = get_object_or_404(Comment, id=request.POST.get("commentid")) - if request.user == self.comment_obj.commented_by: - form = AccountCommentForm(request.POST, instance=self.comment_obj) - if form.is_valid(): - return self.form_valid(form) - - return self.form_invalid(form) - - data = {"error": "You don't have permission to edit this comment."} - return JsonResponse(data) - - def form_valid(self, form): - self.comment_obj.comment = form.cleaned_data.get("comment") - self.comment_obj.save(update_fields=["comment"]) - comment_id = self.comment_obj.id - current_site = get_current_site(self.request) - send_email_user_mentions.delay( - comment_id, - "accounts", - domain=current_site.domain, - protocol=self.request.scheme, - ) - return JsonResponse( - { - "comment_id": self.comment_obj.id, - "comment": self.comment_obj.comment, - } - ) - - def form_invalid(self, form): - return JsonResponse({"error": form["comment"].errors}) - - -class DeleteCommentView(LoginRequiredMixin, View): - def post(self, request, *args, **kwargs): - self.object = get_object_or_404(Comment, id=request.POST.get("comment_id")) - if request.user == self.object.commented_by: - self.object.delete() - data = {"cid": request.POST.get("comment_id")} - return JsonResponse(data) - - data = {"error": "You don't have permission to delete this comment."} - return JsonResponse(data) - - -class AddAttachmentView(LoginRequiredMixin, CreateView): - model = Attachments - form_class = AccountAttachmentForm - http_method_names = ["post"] - - def post(self, request, *args, **kwargs): - self.object = None - self.account = get_object_or_404(Account, id=request.POST.get("accountid")) - if ( - request.user == self.account.created_by - or request.user.is_superuser - or request.user.role == "ADMIN" - or request.user in self.account.assigned_to.all() - ): - form = self.get_form() - if form.is_valid(): - return self.form_valid(form) - - return self.form_invalid(form) - - data = { - "error": "You don't have permission to add attachment \ - for this account." - } - return JsonResponse(data) - - def form_valid(self, form): - attachment = form.save(commit=False) - attachment.created_by = self.request.user - attachment.file_name = attachment.attachment.name - attachment.account = self.account - attachment.save() - return JsonResponse( - { - "attachment_id": attachment.id, - "attachment": attachment.file_name, - "attachment_url": attachment.attachment.url, - "download_url": reverse( - "common:download_attachment", kwargs={"pk": attachment.id} - ), - "attachment_display": attachment.get_file_type_display(), - "created_on": attachment.created_on, - "created_on_arrow": attachment.created_on_arrow, - "created_by": attachment.created_by.email, - "file_type": attachment.file_type(), - } - ) - - def form_invalid(self, form): - return JsonResponse({"error": form["attachment"].errors}) - - -class DeleteAttachmentsView(LoginRequiredMixin, View): - def post(self, request, *args, **kwargs): - self.object = get_object_or_404( - Attachments, id=request.POST.get("attachment_id") - ) - if ( - request.user == self.object.created_by - or request.user.is_superuser - or request.user.role == "ADMIN" - ): - self.object.delete() - data = {"acd": request.POST.get("attachment_id")} - return JsonResponse(data) - - data = {"error": "You don't have permission to delete this attachment."} - return JsonResponse(data) - - -@login_required -def create_mail(request): - if request.method == "GET": - account = get_object_or_404(Account, pk=request.GET.get("account_id")) - contacts_list = list(account.contacts.all().values("email")) - TIMEZONE_CHOICES = [(tz, tz) for tz in pytz.common_timezones] - email_form = EmailForm(account=account) - return render( - request, - "create_mail_accounts.html", - { - "account_id": request.GET.get("account_id"), - "contacts_list": contacts_list, - "email_form": email_form, - "timezones": TIMEZONE_CHOICES, - "settings_timezone": settings.TIME_ZONE, - }, - ) - - if request.method == "POST": - account = Account.objects.filter(id=request.POST.get("account_id")).first() - if account: - form = EmailForm(request.POST, account=account) - if form.is_valid(): - contacts = form.data.get("recipients").split(",") - email_obj = Email.objects.create( - from_account=account, - message_body=form.cleaned_data.get("message_body"), - message_subject=form.cleaned_data.get("message_subject"), - from_email=form.cleaned_data.get("from_email"), - timezone=form.cleaned_data.get("timezone"), - ) - email_obj.recipients.add(*contacts) - if request.POST.get("scheduled_later") != "true": - send_email.delay(email_obj.id) - else: - email_obj.scheduled_later = True - email_obj.scheduled_date_time = form.cleaned_data.get( - "scheduled_date_time" - ) - email_obj.save() - - return JsonResponse({"error": False}) - else: - return JsonResponse({"error": True, "errors": form.errors}) - else: - return JsonResponse({"error": True, "message": "Account does not exist."}) - - -# @login_required -# @sales_access_required -# def create_mail(request, pk): -# account_obj = get_object_or_404(Account, pk=pk) -# if request.method == 'GET': -# context = {} -# context['account_obj'] = account_obj -# return render(request, 'create_email_for_contacts.html') - - -def get_contacts_for_account(request): - account_id = request.POST.get("account_id") - if account_id: - account_obj = Account.objects.filter(pk=account_id).first() - if account_obj: - if account_obj.contacts.all(): - data = list(account_obj.contacts.values("id", "email")) - import json - - return HttpResponse(json.dumps(data)) - return JsonResponse({}) - return JsonResponse({}) - - -def get_email_data_for_account(request): - email_obj = Email.objects.filter(id=request.POST.get("email_account_id")).first() - if email_obj: - ctx = {} - ctx["subject"] = email_obj.message_subject - ctx["body"] = email_obj.message_body - ctx["created_on"] = email_obj.created_on - ctx["contacts"] = list(email_obj.recipients.values("email")) - ctx["error"] = False - return JsonResponse(ctx) - else: - return JsonResponse({"error": True, "data": "No emails found."}) diff --git a/cases/api_views.py b/cases/api_views.py index 5d6e222..ce40b4b 100644 --- a/cases/api_views.py +++ b/cases/api_views.py @@ -36,6 +36,7 @@ from rest_framework.pagination import LimitOffsetPagination from drf_yasg.utils import swagger_auto_schema import json +from crm import settings class CaseListView(APIView, LimitOffsetPagination): @@ -50,10 +51,10 @@ def get_context_data(self, **kwargs): if len(self.request.data) == 0 else self.request.data ) - queryset = self.model.objects.filter(company=self.request.company) - accounts = Account.objects.filter(company=self.request.company) - contacts = Contact.objects.filter(company=self.request.company) - users = User.objects.filter(is_active=True, company=self.request.company) + queryset = self.model.objects.all() + accounts = Account.objects.all() + contacts = Contact.objects.all() + users = User.objects.filter(is_active=True) if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: queryset = queryset.filter( Q(created_by=self.request.user) | Q(assigned_to=self.request.user) @@ -110,9 +111,7 @@ def get_context_data(self, **kwargs): context["accounts_list"] = AccountSerializer(accounts, many=True).data context["contacts_list"] = ContactSerializer(contacts, many=True).data if self.request.user == "ADMIN": - context["teams_list"] = TeamsSerializer( - Teams.objects.filter(company=self.request.company), many=True - ).data + context["teams_list"] = TeamsSerializer(Teams.objects.all(), many=True).data return context @swagger_auto_schema( @@ -132,7 +131,6 @@ def post(self, request, *args, **kwargs): if serializer.is_valid(): cases_obj = serializer.save( created_by=request.user, - company=request.company, closed_on=params.get("closed_on"), case_type=params.get("type_of_case"), ) @@ -140,40 +138,45 @@ def post(self, request, *args, **kwargs): if params.get("contacts"): contacts = json.loads(params.get("contacts")) for contact in contacts: - obj_contact = Contact.objects.filter( - id=contact, company=request.company - ) + obj_contact = Contact.objects.filter(id=contact) if obj_contact: cases_obj.contacts.add(contact) else: cases_obj.delete() data["contacts"] = "Please enter valid contact" - return Response({"error": True, "errors": data}) + return Response( + {"error": True, "errors": data}, + status=status.HTTP_400_BAD_REQUEST, + ) if self.request.user.role == "ADMIN": if params.get("teams"): teams = json.loads(params.get("teams")) for team in teams: - obj_team = Teams.objects.filter( - id=team, company=request.company - ) + obj_team = Teams.objects.filter(id=team) if obj_team: cases_obj.teams.add(team) else: cases_obj.delete() data["team"] = "Please enter valid Team" - return Response({"error": True, "errors": data}) + return Response( + {"error": True, "errors": data}, + status=status.HTTP_400_BAD_REQUEST, + ) if params.get("assigned_to"): assinged_to_users_ids = json.loads(params.get("assigned_to")) for user_id in assinged_to_users_ids: - user = User.objects.filter(id=user_id, company=request.company) + user = User.objects.filter(id=user_id) if user: cases_obj.assigned_to.add(user_id) else: cases_obj.delete() data["assigned_to"] = "Please enter valid user" - return Response({"error": True, "errors": data}) + return Response( + {"error": True, "errors": data}, + status=status.HTTP_400_BAD_REQUEST, + ) if self.request.FILES.get("case_attachment"): attachment = Attachments() @@ -186,15 +189,17 @@ def post(self, request, *args, **kwargs): assigned_to_list = list( cases_obj.assigned_to.all().values_list("id", flat=True) ) - current_site = get_current_site(request) recipients = assigned_to_list send_email_to_assigned_user.delay( recipients, cases_obj.id, - domain=current_site.domain, + domain=settings.Domain, protocol=self.request.scheme, ) - return Response({"error": False, "message": "Case Created Successfully"}) + return Response( + {"error": False, "message": "Case Created Successfully"}, + status=status.HTTP_200_OK, + ) return Response( {"error": True, "errors": serializer.errors}, @@ -217,11 +222,6 @@ def put(self, request, pk, format=None): params = request.query_params if len(request.data) == 0 else request.data cases_object = self.get_object(pk=pk) data = {} - if cases_object.company != request.company: - return Response( - {"error": True, "errors": "User company doesnot match with header...."}, - status=status.HTTP_404_NOT_FOUND, - ) if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: if not ( (self.request.user == cases_object.created_by) @@ -232,7 +232,7 @@ def put(self, request, pk, format=None): "error": True, "errors": "You do not have Permission to perform this action", }, - status=status.HTTP_401_UNAUTHORIZED, + status=status.HTTP_403_FORBIDDEN, ) serializer = CaseCreateSerializer( @@ -253,39 +253,44 @@ def put(self, request, pk, format=None): if params.get("contacts"): contacts = json.loads(params.get("contacts")) for contact in contacts: - obj_contact = Contact.objects.filter( - id=contact, company=request.company - ) + obj_contact = Contact.objects.filter(id=contact) if obj_contact: cases_object.contacts.add(contact) else: data["contacts"] = "Please enter valid Contact" - return Response({"error": True, "errors": data}) + return Response( + {"error": True, "errors": data}, + status=status.HTTP_400_BAD_REQUEST, + ) if self.request.user.role == "ADMIN": cases_object.teams.clear() if params.get("teams"): teams = json.loads(params.get("teams")) for team in teams: - obj_team = Teams.objects.filter( - id=team, company=request.company - ) + obj_team = Teams.objects.filter(id=team) if obj_team: cases_object.teams.add(team) else: data["team"] = "Please enter valid Team" - return Response({"error": True, "errors": data}) + return Response( + {"error": True, "errors": data}, + status=status.HTTP_400_BAD_REQUEST, + ) cases_object.assigned_to.clear() if params.get("assigned_to"): assinged_to_users_ids = json.loads(params.get("assigned_to")) for user_id in assinged_to_users_ids: - user = User.objects.filter(id=user_id, company=request.company) + user = User.objects.filter(id=user_id) if user: cases_object.assigned_to.add(user_id) else: data["assigned_to"] = "Please enter valid User" - return Response({"error": True, "errors": data}) + return Response( + {"error": True, "errors": data}, + status=status.HTTP_400_BAD_REQUEST, + ) if self.request.FILES.get("case_attachment"): attachment = Attachments() @@ -298,12 +303,11 @@ def put(self, request, pk, format=None): assigned_to_list = list( cases_object.assigned_to.all().values_list("id", flat=True) ) - current_site = get_current_site(self.request) recipients = list(set(assigned_to_list) - set(previous_assigned_to_users)) send_email_to_assigned_user.delay( recipients, cases_object.id, - domain=current_site.domain, + domain=settings.Domain, protocol=self.request.scheme, ) return Response( @@ -316,21 +320,18 @@ def put(self, request, pk, format=None): ) @swagger_auto_schema( - tags=["Cases"], manual_parameters=swagger_params.cases_delete_params + tags=["Cases"], ) def delete(self, request, pk, format=None): self.object = self.get_object(pk) - if self.object.company != request.company: - return Response( - {"error": True, "errors": "User company doesnot match with header...."} - ) if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: if self.request.user != self.object.created_by: return Response( { "error": True, "errors": "You do not have Permission to perform this action", - } + }, + status=status.HTTP_403_FORBIDDEN, ) self.object.delete() return Response( @@ -339,15 +340,10 @@ def delete(self, request, pk, format=None): ) @swagger_auto_schema( - tags=["Cases"], manual_parameters=swagger_params.cases_delete_params + tags=["Cases"], ) def get(self, request, pk, format=None): self.cases = self.get_object(pk=pk) - if self.cases.company != request.company: - return Response( - {"error": True, "errors": "User company doesnot match with header...."}, - status=status.HTTP_404_NOT_FOUND, - ) context = {} context["cases_obj"] = CaseSerializer(self.cases).data if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: @@ -359,7 +355,8 @@ def get(self, request, pk, format=None): { "error": True, "errors": "You don't have Permission to perform this action", - } + }, + status=status.HTTP_403_FORBIDDEN, ) comment_permission = ( @@ -376,7 +373,6 @@ def get(self, request, pk, format=None): users_mention = list( User.objects.filter( is_active=True, - company=self.request.company, ).values("username") ) elif self.request.user != self.cases.created_by: @@ -400,7 +396,6 @@ def get(self, request, pk, format=None): "users": UserSerializer( User.objects.filter( is_active=True, - company=self.request.company, ).order_by("email"), many=True, ).data, @@ -424,11 +419,6 @@ def post(self, request, pk, **kwargs): ) context = {} self.cases_obj = Case.objects.get(pk=pk) - if self.cases_obj.company != request.company: - return Response( - {"error": True, "errors": "User company doesnot match with header...."} - ) - comment_serializer = CommentSerializer(data=params) if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: if not ( @@ -440,7 +430,7 @@ def post(self, request, pk, **kwargs): "error": True, "errors": "You don't have Permission to perform this action", }, - status=status.HTTP_401_UNAUTHORIZED, + status=status.HTTP_403_FORBIDDEN, ) if comment_serializer.is_valid(): if params.get("comment"): @@ -506,11 +496,12 @@ def put(self, request, pk, format=None): { "error": True, "errors": "You don't have permission to perform this action.", - } + }, + status=status.HTTP_403_FORBIDDEN, ) @swagger_auto_schema( - tags=["Cases"], manual_parameters=swagger_params.cases_delete_params + tags=["Cases"], ) def delete(self, request, pk, format=None): self.object = self.get_object(pk) @@ -529,7 +520,8 @@ def delete(self, request, pk, format=None): { "error": True, "errors": "You do not have permission to perform this action", - } + }, + status=status.HTTP_403_FORBIDDEN, ) @@ -539,7 +531,7 @@ class CaseAttachmentView(APIView): permission_classes = (IsAuthenticated,) @swagger_auto_schema( - tags=["Cases"], manual_parameters=swagger_params.cases_delete_params + tags=["Cases"], ) def delete(self, request, pk, format=None): self.object = self.model.objects.get(pk=pk) @@ -558,5 +550,6 @@ def delete(self, request, pk, format=None): { "error": True, "errors": "You don't have permission to perform this action.", - } + }, + status=status.HTTP_403_FORBIDDEN, ) diff --git a/cases/forms.py b/cases/forms.py deleted file mode 100644 index c052e12..0000000 --- a/cases/forms.py +++ /dev/null @@ -1,78 +0,0 @@ -from django import forms -from cases.models import Case -from common.models import Comment, Attachments -from teams.models import Teams - - -class CaseForm(forms.ModelForm): - teams_queryset = [] - teams = forms.MultipleChoiceField(choices=teams_queryset) - - def __init__(self, *args, **kwargs): - assigned_users = kwargs.pop("assigned_to", []) - case_accounts = kwargs.pop("account", []) - case_contacts = kwargs.pop("contacts", []) - request_obj = kwargs.pop("request_obj", []) - super(CaseForm, self).__init__(*args, **kwargs) - for field in self.fields.values(): - field.widget.attrs = {"class": "form-control"} - self.fields["description"].widget.attrs.update({"rows": "6"}) - if assigned_users: - self.fields["assigned_to"].queryset = assigned_users - self.fields["assigned_to"].required = False - self.fields["account"].queryset = case_accounts - self.fields["contacts"].queryset = case_contacts - self.fields["contacts"].required = False - for key, value in self.fields.items(): - value.widget.attrs["placeholder"] = value.label - - self.fields["teams"].choices = [ - (team.get("id"), team.get("name")) - for team in Teams.objects.filter(company=request_obj.company).values( - "id", "name" - ) - ] - self.fields["teams"].required = False - - class Meta: - model = Case - fields = ( - "assigned_to", - "name", - "status", - "priority", - "case_type", - "account", - "contacts", - "closed_on", - "description", - ) - - def clean_name(self): - name = self.cleaned_data["name"] - case = Case.objects.filter(name__iexact=name).exclude(id=self.instance.id) - if case: - raise forms.ValidationError("Case Already Exists with this Name") - else: - return name - - -class CaseCommentForm(forms.ModelForm): - comment = forms.CharField(max_length=255, required=True) - - class Meta: - model = Comment - - fields = ( - "comment", - "case", - "commented_by", - ) - - -class CaseAttachmentForm(forms.ModelForm): - attachment = forms.FileField(max_length=1001, required=True) - - class Meta: - model = Attachments - fields = ("attachment", "case") diff --git a/cases/migrations/0006_auto_20210323_1747.py b/cases/migrations/0006_auto_20210323_1747.py new file mode 100644 index 0000000..0612ae2 --- /dev/null +++ b/cases/migrations/0006_auto_20210323_1747.py @@ -0,0 +1,26 @@ +# Generated by Django 3.1.7 on 2021-03-23 12:17 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ("accounts", "0011_account_company"), + ("cases", "0005_case_company"), + ] + + operations = [ + migrations.AlterField( + model_name="case", + name="account", + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="accounts_cases", + to="accounts.account", + ), + ), + ] diff --git a/cases/migrations/0007_remove_case_company.py b/cases/migrations/0007_remove_case_company.py new file mode 100644 index 0000000..793a5ca --- /dev/null +++ b/cases/migrations/0007_remove_case_company.py @@ -0,0 +1,17 @@ +# Generated by Django 3.1.7 on 2021-03-24 04:51 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("cases", "0006_auto_20210323_1747"), + ] + + operations = [ + migrations.RemoveField( + model_name="case", + name="company", + ), + ] diff --git a/cases/models.py b/cases/models.py index 4b24059..944a4d6 100644 --- a/cases/models.py +++ b/cases/models.py @@ -5,7 +5,7 @@ from django.contrib.contenttypes.models import ContentType from accounts.models import Account from contacts.models import Contact -from common.models import User, Company +from common.models import User from common.utils import CASE_TYPE, PRIORITY_CHOICE, STATUS_CHOICE from planner.models import Event from teams.models import Teams @@ -36,9 +36,6 @@ class Case(models.Model): created_on = models.DateTimeField(_("Created on"), auto_now_add=True) is_active = models.BooleanField(default=False) teams = models.ManyToManyField(Teams, related_name="cases_teams") - company = models.ForeignKey( - Company, on_delete=models.SET_NULL, null=True, blank=True - ) class Meta: ordering = ["-created_on"] diff --git a/cases/serializer.py b/cases/serializer.py index d1070a7..4d957e3 100644 --- a/cases/serializer.py +++ b/cases/serializer.py @@ -1,6 +1,6 @@ from rest_framework import serializers from cases.models import Case -from common.serializer import UserSerializer, CompanySerializer +from common.serializer import UserSerializer from teams.serializer import TeamsSerializer from accounts.serializer import AccountSerializer from contacts.serializer import ContactSerializer @@ -12,7 +12,6 @@ class CaseSerializer(serializers.ModelSerializer): assigned_to = UserSerializer(read_only=True, many=True) created_by = UserSerializer(read_only=True) teams = TeamsSerializer(read_only=True, many=True) - company = CompanySerializer() class Meta: model = Case @@ -31,7 +30,6 @@ class Meta: "contacts", "teams", "assigned_to", - "company", "created_on_arrow", ) @@ -44,19 +42,17 @@ def __init__(self, *args, **kwargs): request_obj = kwargs.pop("request_obj", None) super(CaseCreateSerializer, self).__init__(*args, **kwargs) - self.company = request_obj.company - def validate_name(self, name): if self.instance: if ( - Case.objects.filter(name__iexact=name, company=self.company) + Case.objects.filter(name__iexact=name) .exclude(id=self.instance.id) .exists() ): raise serializers.ValidationError("Case already exists with this name") else: - if Case.objects.filter(name__iexact=name, company=self.company).exists(): + if Case.objects.filter(name__iexact=name).exists(): raise serializers.ValidationError("Case already exists with this name") return name @@ -71,6 +67,5 @@ class Meta: "created_on", "is_active", "account", - "company", "created_on_arrow", ) diff --git a/cases/swagger_params.py b/cases/swagger_params.py index 826eb3b..d1ed0ea 100644 --- a/cases/swagger_params.py +++ b/cases/swagger_params.py @@ -1,11 +1,6 @@ from drf_yasg import openapi -company_params_in_header = openapi.Parameter( - "company", openapi.IN_HEADER, required=True, type=openapi.TYPE_STRING -) - cases_list_get_params = [ - company_params_in_header, openapi.Parameter("name", openapi.IN_QUERY, type=openapi.TYPE_STRING), openapi.Parameter("status", openapi.IN_QUERY, type=openapi.TYPE_STRING), openapi.Parameter("priority", openapi.IN_QUERY, type=openapi.TYPE_STRING), @@ -13,7 +8,6 @@ ] cases_detail_get_params = [ - company_params_in_header, openapi.Parameter( "case_attachment", openapi.IN_QUERY, @@ -22,12 +16,7 @@ openapi.Parameter("comment", openapi.IN_QUERY, type=openapi.TYPE_STRING), ] -cases_delete_params = [ - company_params_in_header, -] - cases_create_post_params = [ - company_params_in_header, openapi.Parameter( "name", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING ), @@ -58,6 +47,5 @@ ] cases_comment_edit_params = [ - company_params_in_header, openapi.Parameter("comment", openapi.IN_QUERY, type=openapi.TYPE_STRING), ] diff --git a/cases/tasks.py b/cases/tasks.py index 7ff9c45..7c7176c 100644 --- a/cases/tasks.py +++ b/cases/tasks.py @@ -7,7 +7,6 @@ from accounts.models import User from cases.models import Case -from marketing.models import BlockedDomain, BlockedEmail app = Celery("redis://") @@ -19,31 +18,21 @@ def send_email_to_assigned_user( """ Send Mail To Users When they are assigned to a case """ case = Case.objects.get(id=case_id) created_by = case.created_by - blocked_domains = BlockedDomain.objects.values_list("domain", flat=True) - blocked_emails = BlockedEmail.objects.values_list("email", flat=True) for user in recipients: recipients_list = [] user = User.objects.filter(id=user, is_active=True).first() if user: - if (user.email not in blocked_emails) and ( - user.email.split("@")[-1] not in blocked_domains - ): - recipients_list.append(user.email) - context = {} - context["url"] = ( - protocol - + "://" - + domain - + reverse("cases:view_case", args=(case.id,)) - ) - context["user"] = user - context["case"] = case - context["created_by"] = created_by - subject = "Assigned to case." - html_content = render_to_string( - "assigned_to/cases_assigned.html", context=context - ) + recipients_list.append(user.email) + context = {} + context["url"] = protocol + "://" + domain + context["user"] = user + context["case"] = case + context["created_by"] = created_by + subject = "Assigned to case." + html_content = render_to_string( + "assigned_to/cases_assigned.html", context=context + ) - msg = EmailMessage(subject, html_content, to=recipients_list) - msg.content_subtype = "html" - msg.send() + msg = EmailMessage(subject, html_content, to=recipients_list) + msg.content_subtype = "html" + msg.send() diff --git a/cases/templates/cases.html b/cases/templates/cases.html deleted file mode 100644 index 87f8821..0000000 --- a/cases/templates/cases.html +++ /dev/null @@ -1,335 +0,0 @@ -{% extends 'sales/base.html' %} -{% load static %} -{% load paginate %} -{% block extralinks %} - -{% endblock %} -{% block content %} - -
- - -
-
-
-
-
-
-
Filters
-
-
-
- - -
-
-
-
- - -
-
-
-
- - -
-
-
-
- - - -
-
- -
-
- - Clear -
-
-
-
-
-
-
-
-
- - -
-
-
-
-
- Cases - {% if show_pageitems %} - {% show_pageitems %}{% else %}{{ cases|length }}{% endif %} - - - -
-
- - - {% if cases|length > 0 %} - - - - - - - - - - {% endif %} - - - {% if per_page %} - {% paginate per_page cases %} - {% else%} - {% paginate 10 cases%} - {% endif %} - {% for case in cases %} - - - - - - - - - - {% endfor %} - -
S.NoNameAccountStatusPriorityCreated OnActions
{{ forloop.counter }}{{ case.name }} - {% if case.account %} - {{ case.account }} - {% else %} - No Related Account - {% endif %} - {{ case.status }}{{ case.priority }}{{ case.created_on_arrow }} - - - {% if request.user == case.created_by or request.user.role == "ADMIN" or request.user.is_superuser %} - - {% if case.status != 'Closed' %} - - {% endif %} - {% endif %} -
-
- {% ifequal cases|length 0 %} -
No Cases Records Found
- {% endifequal %} -
- {% show_pages %} -
-
-
-
-
-
- - -{% for case_record in cases %} - - - - -{% endfor %} - - - -{% endblock %} -{% block js_block %} - -{% endblock js_block %} \ No newline at end of file diff --git a/cases/templates/cases_list.html b/cases/templates/cases_list.html deleted file mode 100644 index 320cd93..0000000 --- a/cases/templates/cases_list.html +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - {% ifequal cases|length 0 %} - - - - {% endifequal %} - {% for case in cases %} - - - - - {% endfor %} - -
- - Name - - - - - Status - -
- NO CASES FOUND!! -
- - {{ case.name }} - - - {{ case.status }} -
\ No newline at end of file diff --git a/cases/templates/comments.html b/cases/templates/comments.html deleted file mode 100644 index 17e8473..0000000 --- a/cases/templates/comments.html +++ /dev/null @@ -1,20 +0,0 @@ -{% for comment in comments %} -
  • -
    -
    - - -
    -
    -
    {{comment.comment_user}} Commented
    -
    {{comment.comment}}
    -
    {{comment.comment_time}}
    - {%if comment.get_file%}{{comment.get_file}}{% endif %} - {% endfor %} \ No newline at end of file diff --git a/cases/templates/create_cases.html b/cases/templates/create_cases.html deleted file mode 100644 index 601d696..0000000 --- a/cases/templates/create_cases.html +++ /dev/null @@ -1,476 +0,0 @@ -{% extends 'sales/base.html' %} -{% load static %} -{% block breadcrumb %} - -{% endblock %} -{% block content %} -
    -
    -
    -
    -
    -
    - {% if case_obj %}EDIT{% else %}CREATE{% endif %} CASE -
    -
    -
    -
    -
    - - {{ case_form.name }} - {{ case_form.name.errors }} -
    -
    -
    -
    - - {{ case_form.status }} - {{ case_form.status.errors }} -
    -
    -
    -
    - - {{ case_form.priority }} - {{ case_form.priority.errors }} -
    -
    -
    -
    - - {{ case_form.case_type }} - {{ case_form.case_type.errors }} -
    -
    -
    -
    -
    -
    - -
    - {{ case_form.closed_on }} - - - -
    - {{ case_form.closed_on.errors }} -
    -
    - {% if request.user.is_superuser or request.user.role == 'ADMIN' %} -
    -
    - - - {{ case_form.teams.errors }} -
    -
    - -
    -
    - - -
    -
    - - {% endif %} -
    -
    - - - {{ case_form.assigned_to.errors }} -
    -
    -
    -
    - - {% if account %} - - {% else %} - {{case_form.account}} - {% endif %} - {{case_form.account.errors}} -
    -
    -
    -
    - - - {% if case_obj.case_attachment.count %} - {% for attachment in case_obj.case_attachment.all %} -
    - {{ attachment.file_name }} - {% if not attachment.created_by.role == 'ADMIN' or attachment.created_by.role == request.user.role %} - X - {% endif %} -
    - {% endfor %} - {% endif %} - -
    -
    -
    -
    -
    -
    - - {{ case_form.contacts }} - {{case_form.contacts.errors}} -
    -
    -
    -
    - - {{ case_form.description }} - {{ case_form.description.errors }} -
    -
    -
    - - {% if request.GET.view_account %} - - {% endif %} - -
    -
    - - {% if not case_obj %} - - {% endif %} - Cancel -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    - -
    - 0% -
    -
    -
    -{% endblock %} -{% block js_block %} - - -{% endblock js_block %} \ No newline at end of file diff --git a/cases/templates/sel_contacts.html b/cases/templates/sel_contacts.html deleted file mode 100644 index 13abf0d..0000000 --- a/cases/templates/sel_contacts.html +++ /dev/null @@ -1,8 +0,0 @@ - \ No newline at end of file diff --git a/cases/templates/show_case.html b/cases/templates/show_case.html deleted file mode 100644 index 249aa75..0000000 --- a/cases/templates/show_case.html +++ /dev/null @@ -1,791 +0,0 @@ -{% extends 'sales/base.html' %} -{% load static %} -{% block content %} -
    -
    -
    -
    -
    - -
    -
    -
    -
    -
    -
    - -
    {{case.name}}
    -
    -
    -
    -
    - -
    {%ifequal case.status None%}Not Specified - {% else %}{{case.status}}{% endifequal %} -
    -
    -
    -
    -
    - -
    {%ifequal case.priority None%}Not Specified - {% else %}{{case.priority}}{% endifequal %} -
    -
    -
    -
    -
    - -
    - {%ifequal case.case_type None%}Not Specified - {% else %}{{case.case_type}}{% endifequal %} -
    -
    -
    -
    -
    -
    -
    - -
    {%ifequal case.account None%}Not Specified - {% else %}{{case.account}}{% endifequal %} -
    -
    -
    -
    -
    - -
    - {% ifequal contacts "None" %}Not Specified{% endifequal %} - {% for c in contacts %} -
    {{c.name}}
    - {% endfor %} -
    -
    -
    -
    -
    - -
    {% if case.description%}{{case.description}}{% else%}Not Specified{% endif%}
    -
    -
    - -
    - -
    -
    -
    -

    Comments

    -
    -
    - - - -
      - - - -
      - - -
        - {% for comment in comments %} -
      • -
        -
        - - -
        -
        -
        {{comment.comment_user}} Commented
        -
        {{comment.comment}}
        -
        {{comment.comment_time}}
        -
        {% for com in comment.get_files %} - - {% endfor %}
        - {% endfor %} -
      -
      - - - - - -
      -
      -
      -
      - -
      -
      -
      -
      Users
      -
      -
      -
      -
      -
      - -
      {{ a_user.username }}{% ifequal a_user "None" %}Not Specified{% endifequal %}
      -
      -
      -
      -
      -
      - -
      {{case.created}}
      -
      -
      -
      -
      - -
      {{case.userid}}
      -
      -
      -
      -
      -
      - -
      -
      -

      - Activities -

      -
      -
      - -
      -
      -
      -
      -
        - {% ifequal case.get_meetings|length 0 %} -
      • No Meetings
      • - {% else %} - {% for meet in case.get_meetings %} -
      • -
        -
        - - -
        -
        -
        - - - - - {{meet.name}} - -
        -
        - {{meet.start_date}} -
        -
      • - {% endfor %} - {% endifequal %} -
      -
      - -
      -
        - {% ifequal case.get_tasks|length 0 %} -
      • No Tasks
      • - {% else %} - {% for meet in case.get_tasks %} -
      • -
        -
        - - -
        -
        -
        - - - - - {{meet.name}} - -
        -
        - {{meet.start_date}} -
        -
      • - {% endfor %} - {% endifequal %} -
      -
      - - -
      -
        - {% ifequal case.get_calls|length 0 %} -
      • No Calls
      • - {% else %} - {% for call in case.get_calls %} -
      • -
        -
        - - -
        -
        -
        - - - - - {{call.name}} - -
        -
        - - {{call.start_date}} -
        -
      • - {% endfor %} - {% endifequal %} -
      -
      - -
      - -
      - -
      -
      -
      -
      -
      - - -
      -
      -

      - History -

      -
      -
      - -
      -
      -
      -
      -
        - {% ifequal case.get_completed_meetings|length 0 %} -
      • No Data
      • - {% else %} - {% for meet in case.get_completed_meetings %} -
      • -
        -
        - - -
        -
        -
        - - - - - {{meet.name}} | {{ meet.status }} - -
        -
        - {{meet.start_date}} -
        -
      • - {% endfor %} - {% endifequal %} -
      -
      - -
      -
        - {% ifequal case.get_completed_tasks|length 0 %} -
      • No Tasks
      • - {% else %} - {% for meet in case.get_completed_tasks %} -
      • -
        -
        - - -
        -
        -
        - - - - - {{meet.name}} | {{meet.status }} - -
        -
        - {{meet.start_date}} -
        -
      • - {% endfor %} - {% endifequal %} -
      -
      - - -
      -
        - {% ifequal case.get_completed_calls|length 0 %} -
      • No Calls
      • - {% else %} - {% for call in case.get_completed_calls %} -
      • -
        -
        - - -
        -
        -
        - - - - - {{ call.name }} | {{ call.status }} - -
        -
        - - {{ call.start_date }} -
        -
      • - {% endfor %} - {% endifequal %} -
      -
      -
      - -
      - -
      -
      -
      -
      -
      -
      - -
      - - - - - - - - -
      -
      -{% endblock %} -{% block js_block %} - - -{% endblock js_block %} \ No newline at end of file diff --git a/cases/templates/view_case.html b/cases/templates/view_case.html deleted file mode 100644 index d8cd2e1..0000000 --- a/cases/templates/view_case.html +++ /dev/null @@ -1,397 +0,0 @@ -{% extends 'sales/base.html' %} -{% load static %} -{% load thumbnail %} -{% block content %} -{% block extralinks %} - - -{% endblock extralinks %} - - -
      -
      -
      -
      -
      -
      -
      - Overview - - - -
      -
      -
      -
      -
      -
      - -
      {{ case_record.name }}
      -
      -
      -
      - {% if case_record.account %} -
      - -
      {{ case_record.account }}
      -
      - {% endif %} -
      -
      - {% if case_record.contacts.all %} -
      - -
      - {% for contact in case_record.contacts.all %} -
      {{ contact }}
      - {% endfor %} -
      -
      - {% endif %} -
      -
      - {% if case_record.closed_on %} -
      - -
      {{ case_record.closed_on|date }}
      -
      - {% endif %} -
      -
      -
      -
      -
      - -
      {{ case_record.status }}
      -
      -
      -
      -
      - -
      {{ case_record.priority }}
      -
      -
      -
      - {% if case_record.case_type %} -
      - -
      {{ case_record.case_type }}
      -
      - {% endif %} -
      -
      -
      -
      - {% if case_record.description %} -
      - -
      {{ case_record.description }}
      -
      - {% endif %} -
      -
      -
      -
      - Created by {{ case_record.created_by }} created on {{ case_record.created_on_arrow }} -
      -
      -
      -
      - -
      -
      -
      Attachments
      -
      -
      -
      -
      -
      - -
      - -
      -
      -
      - -
      -
      - -
      -
        - {% for attachment in attachments %} -
      • - {% if request.user.is_superuser or request.user.role == 'ADMIN' or request.user == attachment.created_by %} -
        -
        - -
        -
        - {% endif %} -
        - {% if attachment.attachment %} - {% if 'image' in attachment.file_type %} - {% thumbnail attachment.attachment "80x80" crop="center" as im %} - - {% endthumbnail %} - {% endif %} - {% endif %} -
          {{attachment.file_name}} Download
        -
        -
        -
         Uploaded by :{{ attachment.created_by }}
        -
        {{ attachment.created_on_arrow }}
        -
        -
      • - {% endfor %} -
      -
      -
      -
      - -
      -
      -
      Comments
      -
      -
      -
      -
      -
      - -
      - -
      -
      -
      - -
      -
      - -
      -
        - {% for comment in comments %} -
      • - {% if request.user.is_superuser or request.user.role == 'ADMIN' or request.user == comment.commented_by %} -
        -
        - - -
        -
        - {% endif %} -
        -
        {{ comment.comment }}
        -
        -
        -
        {{ comment.commented_by }}
        -
        {{ comment.commented_on_arrow }}
        -
        -
      • - {% endfor %} -
      -
      -
      - -
      - -
      -
      -
      - -
      - Processing File... -
      -
      -
      -
      - - -{% endblock %} -{% block js_block %} - - - - - -{% endblock js_block %} \ No newline at end of file diff --git a/cases/templates/view_contacts.html b/cases/templates/view_contacts.html deleted file mode 100644 index 4afc659..0000000 --- a/cases/templates/view_contacts.html +++ /dev/null @@ -1,3 +0,0 @@ -{% for c in contacts %} -
      {{c.name}}
      -{% endfor %} \ No newline at end of file diff --git a/cases/tests.py b/cases/tests.py deleted file mode 100644 index 918c429..0000000 --- a/cases/tests.py +++ /dev/null @@ -1,772 +0,0 @@ -from django.contrib.contenttypes.models import ContentType -from django.core.files.uploadedfile import SimpleUploadedFile -from django.test import TestCase -from django.urls import reverse -from django.utils.encoding import force_text - -from accounts.models import Account -from cases.models import Case -from common.models import Address, Attachments, Comment, User, Company -from contacts.models import Contact -from planner.models import Event, Reminder -from teams.models import Teams - - -class CaseCreation(object): - def setUp(self): - self.address = Address.objects.create( - street="street name", city="city name", postcode="1234", country="US" - ) - self.company, _ = Company.objects.get_or_create( - name="test company", address="IN", sub_domain="test", country="IN" - ) - self.user = User.objects.create( - first_name="john", - username="johnDoeCase", - email="johnDoeCase@example.com", - role="ADMIN", - company=self.company, - ) - self.user.set_password("password") - self.user.save() - self.user1 = User.objects.create( - first_name="jane", - username="janeDoeCase", - email="janeDoeCase@example.com", - role="USER", - company=self.company, - ) - self.user1.set_password("password") - self.user1.save() - self.client.login(email="johnDoeCase@example.com", password="password") - - self.account = Account.objects.create( - name="account name", - email="account@example.com", - phone="12345", - billing_address_line="", - billing_street="street", - billing_city="city", - billing_postcode="1234", - billing_country="US", - website="www.example.com", - description="account", - created_by=self.user, - ) - - self.contacts = Contact.objects.create( - first_name="john doe", - email="johnD@example.com", - phone="12345", - description="contact", - created_by=self.user, - address=self.address, - ) - - self.case = Case.objects.create( - name="case name", - case_type="Problem", - status="New", - account=self.account, - priority="Low", - description="something", - created_by=self.user, - closed_on="2016-05-04", - ) - self.comment = Comment.objects.create( - comment="sample comment", case=self.case, commented_by=self.user - ) - self.attachment = Attachments.objects.create( - attachment="image.png", - case=self.case, - created_by=self.user, - account=self.account, - ) - self.content_type = ContentType.objects.create(app_label="cases1", model="case") - - -class CaseViewTestCase(CaseCreation, TestCase): - def test_list_cases(self): - self.cases = Case.objects.all() - response = self.client.get(reverse("cases:list")) - self.assertEqual(response.status_code, 200) - self.assertEqual(response.context["cases"][0].id, self.case.id) - self.assertTrue(response.context["cases"]) - self.assertTemplateUsed(response, "cases.html") - - def test_list_cases_post(self): - self.cases = Case.objects.all() - data = { - "name": "name", - "status": "status", - "priority": "prioty", - "account": int(self.account.id), - } - response = self.client.post(reverse("cases:list"), data) - self.assertEqual(response.status_code, 200) - - -class CaseCreationUrlTestCase(CaseCreation, TestCase): - def test_create_cases(self): - upload_file = open("static/images/user.png", "rb") - response = self.client.post( - "/cases/create/", - { - "name": "new case", - "closed_on": "2019-03-14", - "status": "New", - "priority": "Low", - "created_by": self.user, - "assigned_to": str(self.user.id), - "contacts": str(self.contacts.id), - "case_attachment": SimpleUploadedFile( - upload_file.name, upload_file.read() - ), - }, - ) - self.assertEqual(response.status_code, 200) - - def test_create_cases_html(self): - response = self.client.post( - "/cases/create/", - { - "name": "new case", - "case_type": "Problem", - "status": "New", - "account": self.account, - "contacts": [self.contacts.id], - "priority": "Low", - "description": "something", - }, - ) - # self.assertTemplateUsed(response, 'create_cases.html') - self.assertEqual(response.status_code, 200) - - def test_create_case_get_request(self): - response = self.client.get("/cases/create/") - self.assertEqual(response.status_code, 200) - - -class CaseShowTestCase(CaseCreation, TestCase): - def test_show_case(self): - response = self.client.get("/cases/" + str(self.case.id) + "/view/") - self.assertEqual(response.status_code, 200) - self.assertEqual(response.context["case_record"].id, self.case.id) - - def test_show_case_html(self): - response = self.client.get("/cases/" + str(self.case.id) + "/view/") - self.assertTemplateUsed(response, "view_case.html") - - def test_show_case_invalid_data(self): - response = self.client.get("/cases/" + str(self.case.id) + "/view/") - self.assertEqual(response.status_code, 200) - - -class CaseRemoveTestCase(CaseCreation, TestCase): - def test_case_deletion_show_case(self): - response = self.client.get("/cases/" + str(self.case.id) + "/remove/") - self.assertEqual(response["location"], "/cases/") - - def test_case_delete(self): - response = self.client.post( - "/cases/" + str(self.case.id) + "/remove/", {"case_id": self.case.id} - ) - self.assertEqual(response.status_code, 200) - - -class CaseUpdateTestCase(CaseCreation, TestCase): - def test_update_case_view(self): - response = self.client.get("/cases/" + str(self.case.id) + "/edit_case/") - self.assertEqual(response.status_code, 200) - - def test_case_update(self): - upload_file = open("static/images/user.png", "rb") - response = self.client.post( - "/cases/" + str(self.case.id) + "/edit_case/", - { - "name": "new case", - "closed_on": "2019-03-14", - "status": "New", - "priority": "Low", - "created_by": self.user, - "assigned_to": str(self.user.id), - "contacts": str(self.contacts.id), - "case_attachment": SimpleUploadedFile( - upload_file.name, upload_file.read() - ), - }, - ) - self.assertEqual(response.status_code, 200) - - def test_case_update_html(self): - response = self.client.post( - "/cases/" + str(self.case.id) + "/edit_case/", {"hiddenval": self.case.id} - ) - # self.assertTemplateUsed(response, 'create_cases.html') - self.assertEqual(response.status_code, 200) - - -class CaseModelTestCase(CaseCreation, TestCase): - def test_string_representation(self): - case = Case( - name="name", - ) - self.assertEqual(str(case), case.name) - - -class CaseFormTestCase(CaseCreation, TestCase): - def test_case_creation_same_name(self): - response = self.client.post( - "/cases/create/", - { - "name": "john doe", - "case_type": "type", - "status": "status", - "account": self.account, - "contacts": [self.contacts.id], - "priority": "priority", - "description": "description content", - }, - ) - self.assertEqual(response.status_code, 200) - - def test_case_create_valid(self): - response = self.client.post( - "/cases/create/", - { - "name": "john doe", - "case_type": "case", - "status": "status", - "account": self.account, - "contacts": [self.contacts.id], - "priority": "priotiy", - "description": "description content", - }, - ) - self.assertEqual(response.status_code, 200) - - def test_close_case(self): - response = self.client.post("/cases/close_case/", {"case_id": self.case.id}) - self.assertEqual(response.status_code, 200) - - def test_comment_add(self): - self.client.login(email="janeDoeCase@example.com", password="password") - response = self.client.post("/cases/comment/add/", {"caseid": self.case.id}) - self.assertEqual(response.status_code, 200) - - def test_comment_form_valid(self): - response = self.client.post( - "/cases/comment/add/", {"caseid": self.case.id, "comment": "comment"} - ) - self.assertEqual(response.status_code, 200) - - def test_comment_edit(self): - response = self.client.post( - "/cases/comment/edit/", {"commentid": self.comment.id} - ) - self.assertEqual(response.status_code, 200) - - def test_comment_delete(self): - response = self.client.post( - "/cases/comment/remove/", {"comment_id": self.comment.id} - ) - self.assertEqual(response.status_code, 200) - - -class AttachmentTestCase(CaseCreation, TestCase): - def test_attachment_add(self): - upload_file = open("static/images/user.png", "rb") - response = self.client.post( - "/cases/attachment/add/", - { - "caseid": self.case.id, - "attachment": SimpleUploadedFile(upload_file.name, upload_file.read()), - }, - ) - self.assertEqual(response.status_code, 200) - - def test_attachment_creation(self): - self.client.login(email="janeDoeCase@example.com", password="password") - response = self.client.post("/cases/attachment/add/", {"caseid": self.case.id}) - self.assertEqual(response.status_code, 200) - - def test_attachment_delete(self): - response = self.client.post( - "/cases/attachment/remove/", {"attachment_id": self.attachment.id} - ) - self.assertEqual(response.status_code, 200) - - def test_attachment_deletion(self): - self.client.login(email="janeDoeCase@example.com", password="password") - response = self.client.post( - "/cases/attachment/remove/", {"attachment_id": self.attachment.id} - ) - self.assertEqual(response.status_code, 200) - - -class SelectViewTestCase(CaseCreation, TestCase): - def test_select_contact(self): - response = self.client.get("/cases/select_contacts/") - self.assertEqual(response.status_code, 200) - - -class TestCasesListViewForUser(CaseCreation, TestCase): - def test_queryset_for_user(self): - self.company, _ = Company.objects.get_or_create( - name="test company", address="IN", sub_domain="test", country="IN" - ) - - self.usermp = User.objects.create( - first_name="jane", - username="janeDoe@user.com", - email="janeDoe@user.com", - role="USER", - has_sales_access=True, - company=self.company, - ) - self.usermp.set_password("password") - self.usermp.save() - - self.usermp1 = User.objects.create( - first_name="john", - username="johnDoe@user.com", - email="johnDoe@user.com", - role="USER", - company=self.company, - ) - self.usermp1.set_password("password") - self.usermp1.save() - - self.comment_1 = Comment.objects.create( - comment="test comment", case=self.case, commented_by=self.usermp - ) - - self.account_mp = Account.objects.create( - name="account name", - email="johndoe@account.com", - phone="911234567892", - billing_address_line="", - billing_street="street name", - billing_city="city name", - billing_state="state name", - billing_postcode="1234", - billing_country="IN", - website="www.example.com", - created_by=self.usermp, - status="open", - industry="SOFTWARE", - description="test description", - ) - self.case_user = Case.objects.create( - name="case name", - case_type="Problem", - status="New", - account=self.account_mp, - priority="Low", - description="something", - created_by=self.usermp, - closed_on="2016-05-04", - ) - self.client.login(email="janeDoe@user.com", password="password") - response = self.client.get(reverse("cases:list")) - self.assertEqual(response.status_code, 200) - - self.address = Address.objects.create( - street="street name", - city="city", - state="state", - postcode=1234, - country="AD", - ) - - self.contact_mp = Contact.objects.create( - first_name="jane doe", - email="janeDoe@contact.com", - address=self.address, - description="contact", - created_by=self.usermp, - ) - self.contact_mp.assigned_to.add(self.usermp) - - response = self.client.get(reverse("cases:add_case")) - self.assertEqual(response.status_code, 200) - - def test_create_case(self): - upload_file = open("static/images/user.png", "rb") - response = self.client.post( - "/cases/create/", - { - "name": "new case", - "closed_on": "2019-03-14", - "status": "New", - "priority": "Low", - "created_by": self.user, - "assigned_to": str(self.user.id), - "contacts": str(self.contacts.id), - "case_attachment": SimpleUploadedFile( - upload_file.name, upload_file.read() - ), - "savenewform": True, - }, - ) - self.assertEqual(response.status_code, 200) - - def test_case_detail_view_error(self): - self.usermp1 = User.objects.create( - first_name="joe doe", - username="joedoe", - email="joeDoeCase@user.com", - role="USER", - company=self.company, - ) - self.usermp1.set_password("password") - self.usermp1.save() - self.client.login(email="joeDoeCase@user.com", password="password") - response = self.client.get(reverse("cases:view_case", args=(self.case.id,))) - self.assertEqual(response.status_code, 403) - - # def test_case_detail_view_assigned_users(self): - # self.usermp = User.objects.create( - # first_name="mpmp6", - # username='mpmp6', - # email='mpmp6@micropyramid.com', - # role="USER") - # self.usermp.set_password('mp') - # self.usermp.save() - # self.account_mp = Account.objects.create( - # name="mike", email="mike@micropyramid.com", phone="8322855552", - # billing_address_line="", billing_street="KPHB", - # billing_city="New York", - # billing_state="usa", billing_postcode="500073", - # billing_country="IN", - # website="www.mike.com", created_by=self.usermp, status="open", - # industry="SOFTWARE", description="Yes.. Testing Done") - # self.case_2 = Case.objects.create( - # name="mp_case_1", case_type="Problem", status="New", - # account=self.account_mp, - # priority="Low", description="something", - # created_by=self.usermp, closed_on="2016-05-04", assigned_to=str(self.user.id)) - # response = self.client.get(reverse('cases:view_case', args=(self.case_2.id,))) - # self.assertEqual(200, response.status_code) - - def test_case_update_test(self): - - response = self.client.post( - reverse("cases:edit_case", args=(self.case.id,)), - { - "name": "some case", - "status": "New", - "priority": "Low", - "closed_on": "2019-03-14", - }, - ) - self.assertEqual(response.status_code, 200) - - def test_permissions(self): - - self.user = User.objects.create( - first_name="joedoe", - username="joedoeCase6@user.com", - email="joedoeCase6@user.com", - role="USER", - company=self.company, - ) - self.user.set_password("password") - self.user.save() - - self.case_new = Case.objects.create( - name="joe doe", - case_type="Problem", - status="New", - priority="Low", - description="something", - created_by=self.user, - closed_on="2016-05-04", - ) - - self.usermp = User.objects.create( - first_name="joedoe", - username="joedoeCase7@user.com", - email="joedoeCase7@user.com", - role="USER", - company=self.company, - ) - self.usermp.set_password("password") - self.usermp.save() - self.client.login(username="joedoeCase7@user.com", password="password") - response = self.client.get( - reverse("cases:edit_case", args=(self.case_new.id,)), - { - "name": "some case", - "status": "New", - "priority": "Low", - "closed_on": "2019-03-14", - }, - ) - self.assertEqual(response.status_code, 403) - - response = self.client.get(reverse("cases:remove_case", args=(self.case.id,))) - self.assertEqual(response.status_code, 403) - - response = self.client.post( - reverse("cases:remove_case", args=(self.case.id,)), - {"case_id": self.case_new.id}, - ) - self.assertEqual(response.status_code, 403) - - response = self.client.post( - reverse("cases:close_case"), {"case_id": self.case.id} - ) - self.assertEqual(response.status_code, 403) - - self.client.login(email="johnDoeCase@example.com", password="password") - - self.team_case = Teams.objects.create(name="dev team case") - self.team_case.users.add(self.user1.id) - - response = self.client.post( - reverse("cases:add_case") + "?view_account={}".format(self.account.id), - { - "name": "team case", - "status": "New", - "priority": "Low", - "closed_on": "2019-03-14", - "teams": self.team_case.id, - "from_account": self.account.id, - }, - ) - self.assertEqual(200, response.status_code) - - response = self.client.get( - reverse("cases:add_case") + "?view_account={}".format(self.account.id) - ) - self.assertEqual(200, response.status_code) - - self.case_without_account = Case.objects.create( - name="case_without_account", - case_type="Problem", - status="New", - priority="Low", - description="something", - created_by=self.user, - closed_on="2016-05-04", - ) - - response = self.client.get( - reverse("cases:view_case", args=(self.case_without_account.id,)) - ) - self.assertEqual(200, response.status_code) - - self.account_user = Account.objects.create( - name="account name", - email="account@example.com", - phone="12345", - billing_address_line="", - billing_street="street", - billing_city="city", - billing_postcode="1234", - billing_country="US", - website="www.example.com", - description="account", - created_by=self.usermp, - ) - self.account_user.assigned_to.add(self.usermp.id) - - self.case_user = Case.objects.create( - name="case user", - case_type="Problem", - status="New", - priority="Low", - description="something", - account=self.account_user, - created_by=self.usermp, - closed_on="2016-05-04", - ) - - self.usermp.has_sales_access = True - self.usermp.save() - self.client.logout() - self.client.login(username="joedoeCase7@user.com", password="password") - response = self.client.get( - reverse("cases:view_case", args=(self.case_user.id,)) - ) - self.assertEqual(200, response.status_code) - - self.case_user_1 = Case.objects.create( - name="case user authorization", - case_type="Problem", - status="New", - priority="Low", - description="something", - created_by=self.user, - closed_on="2016-05-04", - ) - - self.case_user_1.assigned_to.add(self.user1, self.user) - self.case_user_1.save() - response = self.client.get( - reverse("cases:view_case", args=(self.case_user_1.id,)) - ) - self.assertEqual(403, response.status_code) - - self.client.logout() - self.client.login(username="joedoeCase7@user.com", password="password") - response = self.client.get( - reverse("cases:edit_case", args=(self.case_user.id,)) - ) - self.assertEqual(200, response.status_code) - - self.client.login(email="johnDoeCase@example.com", password="password") - data = { - "name": "case user", - "case_type": "Problem", - "status": "New", - "priority": "Low", - "description": "something", - "created_by": self.usermp, - "closed_on": "2016-05-04", - "teams": self.team_case.id, - "from_account": self.account.id, - } - response = self.client.post( - reverse("cases:edit_case", args=(self.case_user.id,)), - data, - HTTP_X_REQUESTED_WITH="XMLHttpRequest", - ) - self.assertEqual(200, response.status_code) - - response = self.client.get( - reverse("cases:edit_case", args=(self.case_user.id,)) - + "?view_account={}".format(self.account.id) - ) - self.assertEqual(200, response.status_code) - - self.client.logout() - self.client.login(username="joedoeCase7@user.com", password="password") - response = self.client.get(reverse("cases:edit_case", args=(self.case.id,))) - self.assertEqual(403, response.status_code) - - response = self.client.get( - reverse("cases:remove_case", args=(self.case_user_1.id,)) - + "?view_account={}".format(self.account.id) - ) - self.assertEqual(403, response.status_code) - - self.client.logout() - self.client.login(email="johnDoeCase@example.com", password="password") - response = self.client.get( - reverse("cases:remove_case", args=(self.case_user.id,)) - + "?view_account={}".format(self.account.id) - ) - self.assertEqual(302, response.status_code) - - self.case_user = Case.objects.create( - name="case user", - case_type="Problem", - status="New", - priority="Low", - description="something", - account=self.account_user, - created_by=self.usermp, - closed_on="2016-05-04", - ) - self.client.logout() - self.client.login(email="johnDoeCase@example.com", password="password") - response = self.client.post( - reverse("cases:remove_case", args=(self.case_user.id,)) - + "?view_account={}".format(self.account.id), - {"case_id": self.case_user.id}, - HTTP_X_REQUESTED_WITH="XMLHttpRequest", - ) - self.assertEqual(200, response.status_code) - - self.case_user = Case.objects.create( - name="case user", - case_type="Problem", - status="New", - priority="Low", - description="something", - account=self.account_user, - created_by=self.usermp, - closed_on="2016-05-04", - ) - - self.client.logout() - self.client.login(username="joedoeCase7@user.com", password="password") - response = self.client.post( - reverse("cases:remove_case", args=(self.case.id,)) - + "?view_account={}".format(self.account.id), - {"case_id": self.case.id}, - ) - self.assertEqual(403, response.status_code) - - data = { - "comment": "comment update", - "caseid": self.case.id, - "commentid": self.comment.id, - } - - response = self.client.post(reverse("cases:edit_comment"), data) - self.assertEqual(200, response.status_code) - - response = self.client.post( - reverse("cases:close_case") + "?view_account={}".format(self.account.id), - {"case_id": self.case.id}, - ) - self.assertEqual(403, response.status_code) - data = {"caseid": self.case.id, "comment": ""} - response = self.client.post(reverse("cases:add_comment"), data) - self.assertEqual(200, response.status_code) - - self.client.logout() - self.client.login(email="johnDoeCase@example.com", password="password") - response = self.client.get( - reverse("cases:select_contacts") + "?account={}".format(self.account.id) - ) - self.assertEqual(200, response.status_code) - - data = {"caseid": self.case.id, "comment": ""} - response = self.client.post(reverse("cases:add_comment"), data) - self.assertEqual(200, response.status_code) - - data = { - "comment": "comment update", - "caseid": self.case.id, - "commentid": self.comment.id, - } - - response = self.client.post(reverse("cases:edit_comment"), data) - self.assertEqual(200, response.status_code) - - data = {"comment": "", "caseid": self.case.id, "commentid": self.comment.id} - - response = self.client.post(reverse("cases:edit_comment"), data) - self.assertEqual(200, response.status_code) - - self.client.logout() - self.client.login(username="joedoeCase7@user.com", password="password") - data = {"comment_id": self.comment.id} - response = self.client.post(reverse("cases:remove_comment"), data) - self.assertEqual(200, response.status_code) - - self.client.logout() - self.client.login(email="johnDoeCase@example.com", password="password") - data = { - "caseid": self.case.id, - "attachment": "", - } - response = self.client.post(reverse("cases:add_attachment"), data) - self.assertEqual(200, response.status_code) - - # def test_comment_add_error(self): - # self.client.login(email='mpmp@micropyramid.com', password='mp') - # response = self.client.post(reverse('cases:add_comment'), {}) - # self.assertJSONEqual(force_text(response.content), {'error': ["This field is required."]}) - - # response = self.client.post(reverse('cases:edit_comment'), {}) - # self.assertJSONEqual(force_text(response.content), {'error': ["This field is required."]}) - - # def test_comment_edit_error(self): - # self.client.login(email='mpmp1@micropyramid.com', password='mp') - # response = self.client.post(reverse('cases:edit_comment'), {}) - # self.assertJSONEqual(force_text(response.content), {'error': "You don't have permission to edit this comment."}) diff --git a/cases/urls.py b/cases/urls.py deleted file mode 100644 index 47f6cb6..0000000 --- a/cases/urls.py +++ /dev/null @@ -1,38 +0,0 @@ -from django.urls import path -from cases.views import ( - CasesListView, - create_case, - CaseDetailView, - update_case, - RemoveCaseView, - CloseCaseView, - select_contact, - GetCasesView, - AddCommentView, - UpdateCommentView, - DeleteCommentView, - get_teams_and_users, - AddAttachmentView, - DeleteAttachmentsView, -) - -app_name = "cases" - -urlpatterns = [ - path("", CasesListView.as_view(), name="list"), - path("create/", create_case, name="add_case"), - path("/view/", CaseDetailView.as_view(), name="view_case"), - path("/edit_case/", update_case, name="edit_case"), - path("/remove/", RemoveCaseView.as_view(), name="remove_case"), - path("close_case/", CloseCaseView.as_view(), name="close_case"), - path("select_contacts/", select_contact, name="select_contacts"), - path("get/list/", GetCasesView.as_view(), name="get_cases"), - path("comment/add/", AddCommentView.as_view(), name="add_comment"), - path("comment/edit/", UpdateCommentView.as_view(), name="edit_comment"), - path("comment/remove/", DeleteCommentView.as_view(), name="remove_comment"), - path("attachment/add/", AddAttachmentView.as_view(), name="add_attachment"), - path( - "attachment/remove/", DeleteAttachmentsView.as_view(), name="remove_attachment" - ), - path("get_teams_and_users/", get_teams_and_users, name="get_teams_and_users"), -] diff --git a/cases/views.py b/cases/views.py deleted file mode 100644 index a4707f4..0000000 --- a/cases/views.py +++ /dev/null @@ -1,712 +0,0 @@ -import json -from django.contrib.auth.decorators import login_required -from django.contrib.auth.mixins import LoginRequiredMixin -from django.contrib.sites.shortcuts import get_current_site -from django.core.mail import EmailMessage -from django.db.models import Q -from django.http import JsonResponse -from django.shortcuts import get_object_or_404, redirect, render -from django.template.loader import render_to_string -from django.views.generic import CreateView, DetailView, ListView, TemplateView, View - -from cases.models import Case -from cases.forms import CaseForm, CaseCommentForm, CaseAttachmentForm -from common.models import User, Comment, Attachments -from accounts.models import Account -from contacts.models import Contact -from common.utils import PRIORITY_CHOICE, STATUS_CHOICE, CASE_TYPE -from django.urls import reverse -from django.core.exceptions import PermissionDenied -from common.tasks import send_email_user_mentions -from cases.tasks import send_email_to_assigned_user -from common.access_decorators_mixins import ( - sales_access_required, - marketing_access_required, - SalesAccessRequiredMixin, - MarketingAccessRequiredMixin, -) -from teams.models import Teams - - -@login_required -def get_teams_and_users(request): - data = {} - teams = Teams.objects.all() - teams_data = [ - {"team": team.id, "users": [user.id for user in team.users.all()]} - for team in teams - ] - users = User.objects.all().values_list("id", flat=True) - data["teams"] = teams_data - data["users"] = list(users) - return JsonResponse(data) - - -class CasesListView(SalesAccessRequiredMixin, LoginRequiredMixin, TemplateView): - model = Case - context_object_name = "cases" - template_name = "cases.html" - - def get_queryset(self): - queryset = self.model.objects.all().select_related("account") - if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: - queryset = queryset.filter( - Q(assigned_to__in=[self.request.user]) | Q(created_by=self.request.user) - ) - - request_post = self.request.POST - if request_post: - if request_post.get("name"): - queryset = queryset.filter(name__icontains=request_post.get("name")) - if request_post.get("account"): - queryset = queryset.filter(account_id=request_post.get("account")) - if request_post.get("status"): - queryset = queryset.filter(status=request_post.get("status")) - if request_post.get("priority"): - queryset = queryset.filter(priority=request_post.get("priority")) - return queryset.filter(company=self.request.company) - - def get_context_data(self, **kwargs): - context = super(CasesListView, self).get_context_data(**kwargs) - context["cases"] = self.get_queryset() - context["accounts"] = Account.objects.filter( - status="open", company=self.request.company - ) - context["per_page"] = self.request.POST.get("per_page") - context["acc"] = ( - int(self.request.POST.get("account")) - if self.request.POST.get("account") - else None - ) - context["case_priority"] = PRIORITY_CHOICE - context["case_status"] = STATUS_CHOICE - - search = False - if ( - self.request.POST.get("name") - or self.request.POST.get("account") - or self.request.POST.get("status") - or self.request.POST.get("priority") - ): - search = True - - context["search"] = search - return context - - def get(self, request, *args, **kwargs): - context = self.get_context_data(**kwargs) - return self.render_to_response(context) - - def post(self, request, *args, **kwargs): - context = self.get_context_data(**kwargs) - return self.render_to_response(context) - - -@login_required -@sales_access_required -def create_case(request): - users = [] - if request.user.role == "ADMIN" or request.user.is_superuser: - users = User.objects.filter(is_active=True, company=request.company).order_by( - "email" - ) - elif request.user.google.all(): - users = [] - else: - users = User.objects.filter(role="ADMIN", company=request.company).order_by( - "email" - ) - accounts = Account.objects.filter(status="open", company=request.company) - contacts = Contact.objects.filter(company=request.company) - if request.user.role != "ADMIN" and not request.user.is_superuser: - accounts = Account.objects.filter(created_by=request.user).filter( - company=request.company - ) - contacts = Contact.objects.filter( - Q(assigned_to__in=[request.user]) | Q(created_by=request.user) - ).filter(company=request.company) - kwargs_data = { - "assigned_to": users, - "account": accounts, - "contacts": contacts, - "request_obj": request, - } - form = CaseForm(**kwargs_data) - template_name = "create_cases.html" - - if request.POST: - form = CaseForm(request.POST, request.FILES, **kwargs_data) - if form.is_valid(): - case = form.save(commit=False) - case.created_by = request.user - case.company = request.company - case.save() - if request.POST.getlist("assigned_to", []): - case.assigned_to.add(*request.POST.getlist("assigned_to")) - assigned_to_list = request.POST.getlist("assigned_to") - # current_site = get_current_site(request) - # recipients = assigned_to_list - # send_email_to_assigned_user.delay(recipients, case.id, domain=current_site.domain, - # protocol=request.scheme) - # for assigned_to_user in assigned_to_list: - # user = get_object_or_404(User, pk=assigned_to_user) - # mail_subject = 'Assigned to case.' - # message = render_to_string( - # 'assigned_to/cases_assigned.html', { - # 'user': user, - # 'domain': current_site.domain, - # 'protocol': request.scheme, - # 'case': case - # }) - # email = EmailMessage( - # mail_subject, message, to=[user.email]) - # email.content_subtype = "html" - # email.send() - - if request.POST.getlist("contacts", []): - case.contacts.add(*request.POST.getlist("contacts")) - if request.POST.getlist("teams", []): - user_ids = Teams.objects.filter( - id__in=request.POST.getlist("teams") - ).values_list("users", flat=True) - assinged_to_users_ids = case.assigned_to.all().values_list( - "id", flat=True - ) - for user_id in user_ids: - if user_id not in assinged_to_users_ids: - case.assigned_to.add(user_id) - - if request.POST.getlist("teams", []): - case.teams.add(*request.POST.getlist("teams")) - - current_site = get_current_site(request) - recipients = list(case.assigned_to.all().values_list("id", flat=True)) - send_email_to_assigned_user.delay( - recipients, case.id, domain=current_site.domain, protocol=request.scheme - ) - if request.FILES.get("case_attachment"): - attachment = Attachments() - attachment.created_by = request.user - attachment.file_name = request.FILES.get("case_attachment").name - attachment.case = case - attachment.attachment = request.FILES.get("case_attachment") - attachment.save() - success_url = reverse("cases:list") - if request.POST.get("savenewform"): - success_url = reverse("cases:add_case") - if request.POST.get("from_account"): - from_account = request.POST.get("from_account") - success_url = reverse( - "accounts:view_account", kwargs={"pk": from_account} - ) - return JsonResponse({"error": False, "success_url": success_url}) - return JsonResponse({"error": True, "errors": form.errors}) - context = {} - context["case_form"] = form - context["accounts"] = accounts - if request.GET.get("view_account"): - context["account"] = get_object_or_404( - Account, id=request.GET.get("view_account") - ) - context["contacts"] = contacts - context["users"] = users - context["case_types"] = CASE_TYPE - context["case_priority"] = PRIORITY_CHOICE - context["case_status"] = STATUS_CHOICE - context["teams"] = Teams.objects.filter(company=request.company) - context["assignedto_list"] = [ - int(i) for i in request.POST.getlist("assigned_to", []) if i - ] - context["contacts_list"] = [ - int(i) for i in request.POST.getlist("contacts", []) if i - ] - return render(request, template_name, context) - - -class CaseDetailView(SalesAccessRequiredMixin, LoginRequiredMixin, DetailView): - model = Case - context_object_name = "case_record" - template_name = "view_case.html" - - def dispatch(self, request, *args, **kwargs): - case = self.get_object() - if case.company != request.company: - raise PermissionDenied - return super(CaseDetailView, self).dispatch(request, *args, **kwargs) - - def get_queryset(self): - queryset = super(CaseDetailView, self).get_queryset() - return queryset.prefetch_related("contacts", "account") - - def get_context_data(self, **kwargs): - context = super(CaseDetailView, self).get_context_data(**kwargs) - user_assgn_list = [ - assigned_to.id for assigned_to in context["object"].assigned_to.all() - ] - user_assigned_accounts = set( - self.request.user.account_assigned_users.values_list("id", flat=True) - ) - if context["object"].account: - case_account = set([context["object"].account.id]) - else: - case_account = set() - if user_assigned_accounts.intersection(case_account): - user_assgn_list.append(self.request.user.id) - if self.request.user == context["object"].created_by: - user_assgn_list.append(self.request.user.id) - if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: - if self.request.user.id not in user_assgn_list: - raise PermissionDenied - assigned_data = [] - for each in context["case_record"].assigned_to.all(): - assigned_dict = {} - assigned_dict["id"] = each.id - assigned_dict["name"] = each.email - assigned_data.append(assigned_dict) - - if self.request.user.is_superuser or self.request.user.role == "ADMIN": - users_mention = list( - User.objects.filter( - is_active=True, company=self.request.company - ).values("username") - ) - elif self.request.user != context["object"].created_by: - users_mention = [{"username": context["object"].created_by.username}] - else: - users_mention = list(context["object"].assigned_to.all().values("username")) - - context.update( - { - "comments": context["case_record"].cases.all(), - "attachments": context["case_record"].case_attachment.all(), - "users_mention": users_mention, - "assigned_data": json.dumps(assigned_data), - } - ) - return context - - -@login_required -@sales_access_required -def update_case(request, pk): - case_object = Case.objects.filter(pk=pk).first() - - if case_object.company != request.company: - raise PermissionDenied - - accounts = Account.objects.filter(status="open", company=request.company) - contacts = Contact.objects.filter(company=request.company) - if request.user.role != "ADMIN" and not request.user.is_superuser: - accounts = Account.objects.filter( - created_by=request.user, company=request.company - ) - contacts = Contact.objects.filter( - Q(assigned_to__in=[request.user]) | Q(created_by=request.user) - ).filter(company=request.company) - users = [] - if request.user.role == "ADMIN" or request.user.is_superuser: - users = User.objects.filter(is_active=True, company=request.company).order_by( - "email" - ) - elif request.user.google.all(): - users = [] - else: - users = User.objects.filter(role="ADMIN", company=request.company).order_by( - "email" - ) - kwargs_data = { - "assigned_to": users, - "account": accounts, - "contacts": contacts, - "request_obj": request, - } - form = CaseForm(instance=case_object, **kwargs_data) - - if request.POST: - form = CaseForm( - request.POST, request.FILES, instance=case_object, **kwargs_data - ) - if form.is_valid(): - assigned_to_ids = case_object.assigned_to.all().values_list("id", flat=True) - case_obj = form.save(commit=False) - case_obj.contacts.clear() - case_obj.save() - previous_assigned_to_users = list( - case_obj.assigned_to.all().values_list("id", flat=True) - ) - all_members_list = [] - - if request.POST.getlist("assigned_to", []): - current_site = get_current_site(request) - - assigned_form_users = form.cleaned_data.get("assigned_to").values_list( - "id", flat=True - ) - all_members_list = list( - set(list(assigned_form_users)) - set(list(assigned_to_ids)) - ) - # recipients = all_members_list - # send_email_to_assigned_user.delay(recipients, case_obj.id, domain=current_site.domain, - # protocol=request.scheme) - # if all_members_list: - # for assigned_to_user in all_members_list: - # user = get_object_or_404(User, pk=assigned_to_user) - # mail_subject = 'Assigned to case.' - # message = render_to_string( - # 'assigned_to/cases_assigned.html', { - # 'user': user, - # 'domain': current_site.domain, - # 'protocol': request.scheme, - # 'case': case_obj - # }) - # email = EmailMessage( - # mail_subject, message, to=[user.email]) - # email.content_subtype = "html" - # email.send() - - case_obj.assigned_to.clear() - case_obj.assigned_to.add(*request.POST.getlist("assigned_to")) - else: - case_obj.assigned_to.clear() - - if request.POST.getlist("teams", []): - user_ids = Teams.objects.filter( - id__in=request.POST.getlist("teams") - ).values_list("users", flat=True) - assinged_to_users_ids = case_obj.assigned_to.all().values_list( - "id", flat=True - ) - for user_id in user_ids: - if user_id not in assinged_to_users_ids: - case_obj.assigned_to.add(user_id) - - if request.POST.getlist("teams", []): - case_obj.teams.clear() - case_obj.teams.add(*request.POST.getlist("teams")) - else: - case_obj.teams.clear() - - current_site = get_current_site(request) - assigned_to_list = list( - case_obj.assigned_to.all().values_list("id", flat=True) - ) - recipients = list(set(assigned_to_list) - set(previous_assigned_to_users)) - send_email_to_assigned_user.delay( - recipients, - case_obj.id, - domain=current_site.domain, - protocol=request.scheme, - ) - - if request.POST.getlist("contacts", []): - case_obj.contacts.add(*request.POST.getlist("contacts")) - - success_url = reverse("cases:list") - if request.POST.get("from_account"): - from_account = request.POST.get("from_account") - success_url = reverse( - "accounts:view_account", kwargs={"pk": from_account} - ) - if request.FILES.get("case_attachment"): - attachment = Attachments() - attachment.created_by = request.user - attachment.file_name = request.FILES.get("case_attachment").name - attachment.case = case_obj - attachment.attachment = request.FILES.get("case_attachment") - attachment.save() - - return JsonResponse({"error": False, "success_url": success_url}) - return JsonResponse({"error": True, "errors": form.errors}) - context = {} - context["case_obj"] = case_object - user_assgn_list = [ - assgined_to.id for assgined_to in context["case_obj"].assigned_to.all() - ] - - if request.user == case_object.created_by: - user_assgn_list.append(request.user.id) - if request.user.role != "ADMIN" and not request.user.is_superuser: - if request.user.id not in user_assgn_list: - raise PermissionDenied - context["case_form"] = form - context["accounts"] = accounts - if request.GET.get("view_account"): - context["account"] = get_object_or_404( - Account, id=request.GET.get("view_account") - ) - context["contacts"] = contacts - context["users"] = kwargs_data["assigned_to"] - context["case_types"] = CASE_TYPE - context["case_priority"] = PRIORITY_CHOICE - context["case_status"] = STATUS_CHOICE - context["teams"] = Teams.objects.filter(company=request.company) - context["assignedto_list"] = [ - int(i) for i in request.POST.getlist("assigned_to", []) if i - ] - context["contacts_list"] = [ - int(i) for i in request.POST.getlist("contacts", []) if i - ] - - return render(request, "create_cases.html", context) - - -class RemoveCaseView(SalesAccessRequiredMixin, LoginRequiredMixin, View): - def get(self, request, *args, **kwargs): - case_id = kwargs.get("case_id") - self.object = get_object_or_404(Case, id=case_id) - if self.object.company != request.company: - raise PermissionDenied - - if ( - self.request.user.role == "ADMIN" - or self.request.user.is_superuser - or self.request.user == self.object.created_by - ): - self.object.delete() - if request.GET.get("view_account"): - account = request.GET.get("view_account") - return redirect("accounts:view_account", pk=account) - return redirect("cases:list") - raise PermissionDenied - - def post(self, request, *args, **kwargs): - case_id = kwargs.get("case_id") - self.object = get_object_or_404(Case, id=case_id) - if ( - self.request.user.role == "ADMIN" - or self.request.user.is_superuser - or self.request.user == self.object.created_by - ): - self.object.delete() - if request.is_ajax(): - return JsonResponse({"error": False}) - count = ( - Case.objects.filter( - Q(assigned_to__in=[request.user]) | Q(created_by=request.user) - ) - .distinct() - .count() - ) - data = {"case_id": case_id, "count": count} - return JsonResponse(data) - raise PermissionDenied - - -class CloseCaseView(SalesAccessRequiredMixin, LoginRequiredMixin, View): - def post(self, request, *args, **kwargs): - case_id = request.POST.get("case_id") - self.object = get_object_or_404(Case, id=case_id) - if ( - self.request.user.role == "ADMIN" - or self.request.user.is_superuser - or self.request.user == self.object.created_by - ): - self.object.status = "Closed" - self.object.save() - data = {"status": "Closed", "cid": case_id} - return JsonResponse(data) - raise PermissionDenied - - -def select_contact(request): - contact_account = request.GET.get("account") - if contact_account: - account = get_object_or_404(Account, id=contact_account) - contacts = account.contacts.all() - else: - contacts = Contact.objects.all() - data = {contact.pk: contact.first_name for contact in contacts.distinct()} - return JsonResponse(data) - - -class GetCasesView(LoginRequiredMixin, ListView): - model = Case - context_object_name = "cases" - template_name = "cases_list.html" - - -class AddCommentView(LoginRequiredMixin, CreateView): - model = Comment - form_class = CaseCommentForm - http_method_names = ["post"] - - def post(self, request, *args, **kwargs): - self.object = None - self.case = get_object_or_404(Case, id=request.POST.get("caseid")) - if ( - request.user in self.case.assigned_to.all() - or request.user == self.case.created_by - or request.user.is_superuser - or request.user.role == "ADMIN" - ): - form = self.get_form() - if form.is_valid(): - return self.form_valid(form) - - return self.form_invalid(form) - - data = {"error": "You don't have permission to comment."} - return JsonResponse(data) - - def form_valid(self, form): - comment = form.save(commit=False) - comment.commented_by = self.request.user - comment.case = self.case - comment.save() - comment_id = comment.id - current_site = get_current_site(self.request) - send_email_user_mentions.delay( - comment_id, - "cases", - domain=current_site.domain, - protocol=self.request.scheme, - ) - return JsonResponse( - { - "comment_id": comment.id, - "comment": comment.comment, - "commented_on": comment.commented_on, - "commented_on_arrow": comment.commented_on_arrow, - "commented_by": comment.commented_by.email, - } - ) - - def form_invalid(self, form): - return JsonResponse({"error": form["comment"].errors}) - - -class UpdateCommentView(LoginRequiredMixin, View): - http_method_names = ["post"] - - def post(self, request, *args, **kwargs): - self.comment_obj = get_object_or_404(Comment, id=request.POST.get("commentid")) - if ( - request.user == self.comment_obj.commented_by - or request.user.is_superuser - or request.user.role == "ADMIN" - ): - form = CaseCommentForm(request.POST, instance=self.comment_obj) - if form.is_valid(): - return self.form_valid(form) - - return self.form_invalid(form) - - data = {"error": "You don't have permission to edit this comment."} - return JsonResponse(data) - - def form_valid(self, form): - self.comment_obj.comment = form.cleaned_data.get("comment") - self.comment_obj.save(update_fields=["comment"]) - comment_id = self.comment_obj.id - current_site = get_current_site(self.request) - send_email_user_mentions.delay( - comment_id, - "cases", - domain=current_site.domain, - protocol=self.request.scheme, - ) - return JsonResponse( - { - "comment_id": self.comment_obj.id, - "comment": self.comment_obj.comment, - } - ) - - def form_invalid(self, form): - return JsonResponse({"error": form["comment"].errors}) - - -class DeleteCommentView(LoginRequiredMixin, View): - def post(self, request, *args, **kwargs): - self.object = get_object_or_404(Comment, id=request.POST.get("comment_id")) - if ( - request.user == self.object.commented_by - or request.user.is_superuser - or request.user.role == "ADMIN" - ): - self.object.delete() - data = {"cid": request.POST.get("comment_id")} - return JsonResponse(data) - - data = {"error": "You don't have permission to delete this comment."} - return JsonResponse(data) - - -class AddAttachmentView(LoginRequiredMixin, CreateView): - model = Attachments - form_class = CaseAttachmentForm - http_method_names = ["post"] - - def post(self, request, *args, **kwargs): - self.object = None - self.case = get_object_or_404(Case, id=request.POST.get("caseid")) - if ( - request.user in self.case.assigned_to.all() - or request.user == self.case.created_by - or request.user.is_superuser - or request.user.role == "ADMIN" - ): - form = self.get_form() - if form.is_valid(): - return self.form_valid(form) - - return self.form_invalid(form) - - data = { - "error": True, - "errors": "You don't have permission to add attachment for this case.", - } - return JsonResponse(data) - - def form_valid(self, form): - attachment = form.save(commit=False) - attachment.created_by = self.request.user - attachment.file_name = attachment.attachment.name - attachment.case = self.case - attachment.save() - # return JsonResponse({"error": False, "message": "Attachment Saved" - # }) - return JsonResponse( - { - "attachment_id": attachment.id, - "attachment": attachment.file_name, - "attachment_url": attachment.attachment.url, - "download_url": reverse( - "common:download_attachment", kwargs={"pk": attachment.id} - ), - "created_on": attachment.created_on, - "created_on_arrow": attachment.created_on_arrow, - "created_by": attachment.created_by.email, - "message": "attachment Created", - "attachment_display": attachment.get_file_type_display(), - "file_type": attachment.file_type(), - "error": False, - } - ) - - def form_invalid(self, form): - return JsonResponse({"error": True, "errors": form["attachment"].errors}) - - -class DeleteAttachmentsView(LoginRequiredMixin, View): - def post(self, request, *args, **kwargs): - self.object = get_object_or_404( - Attachments, id=request.POST.get("attachment_id") - ) - if ( - request.user == self.object.created_by - or request.user.is_superuser - or request.user.role == "ADMIN" - ): - self.object.delete() - data = { - "attachment_object": request.POST.get("attachment_id"), - "error": False, - } - return JsonResponse(data) - - data = { - "error": True, - "errors": "You don't have permission to delete this attachment.", - } - return JsonResponse(data) diff --git a/common/api_urls.py b/common/api_urls.py index 99a31f9..af7a23f 100644 --- a/common/api_urls.py +++ b/common/api_urls.py @@ -9,26 +9,24 @@ path("dashboard/", api_views.ApiHomeView.as_view()), path("auth/register/", api_views.RegistrationView.as_view()), path("auth/login/", api_views.LoginView.as_view()), - path("auth/validate-subdomain/", api_views.check_sub_domain), path("profile/", api_views.ProfileView.as_view()), path("users/get-teams-and-users/", api_views.GetTeamsAndUsersView.as_view()), path("profile/change-password/", api_views.ChangePasswordView.as_view()), path("auth/forgot-password/", api_views.ForgotPasswordView.as_view()), - path("auth/reset-password/", api_views.ResetPasswordView.as_view()), - path("users/", api_views.UsersListView.as_view()), - path("users//", api_views.UserDetailView.as_view()), - path("documents/", api_views.DocumentListView.as_view()), - path("documents//", api_views.DocumentDetailView.as_view()), - path("settings/contacts/", api_views.ContactsEmailCampaignListView.as_view()), path( - "settings/contacts//", - api_views.ContactsEmailCampaignDetailView.as_view(), + "auth/reset-password///", + api_views.ResetPasswordView.as_view(), ), - path("settings/block-domains/", api_views.BlockDomainsListView.as_view()), path( - "settings/block-domains//", api_views.BlockDomainsDetailView.as_view() + "auth/activate-user////", + api_views.ActivateUserView.as_view(), ), - path("settings/block-emails/", api_views.BlockEmailsListView.as_view()), - path("settings/block-emails//", api_views.BlockEmailsDetailView.as_view()), + path("auth/resend-activation-link/", api_views.ResendActivationLinkView.as_view()), + path("users/", api_views.UsersListView.as_view()), + path("users//", api_views.UserDetailView.as_view()), + path("documents/", api_views.DocumentListView.as_view()), + path("documents//", api_views.DocumentDetailView.as_view()), + path("api-settings/", api_views.DomainList.as_view()), + path("api-settings//", api_views.DomainDetailView.as_view()), path("users//status/", api_views.UserStatusView.as_view()), ] diff --git a/common/api_views.py b/common/api_views.py index 28b71c4..caaf0f4 100644 --- a/common/api_views.py +++ b/common/api_views.py @@ -2,7 +2,6 @@ from drf_yasg.utils import swagger_auto_schema from django.shortcuts import get_object_or_404 from rest_framework import status -from django.http import Http404 from accounts.serializer import AccountSerializer from contacts.serializer import ContactSerializer from opportunity.serializer import OpportunitySerializer @@ -12,19 +11,16 @@ from cases.serializer import CaseSerializer from accounts.models import Account, Contact from opportunity.models import Opportunity +from accounts.models import Tags from cases.models import Case from leads.models import Lead from teams.models import Teams -from common.forms import DocumentForm from common.utils import ROLES -from common.models import User, Company, Document -from common.access_decorators_mixins import ( - MarketingAccessRequiredMixin, - SalesAccessRequiredMixin, - admin_login_required, - marketing_access_required, - sales_access_required, +from common.serializer import ( + RegisterUserSerializer, + CreateUserSerializer, ) +from common.models import User, Company, Document, APISettings from common.tasks import ( resend_activation_link_to_user, send_email_to_new_user, @@ -40,19 +36,19 @@ from common.utils import jwt_payload_handler from rest_framework.exceptions import APIException from rest_framework.permissions import IsAuthenticated +from rest_framework.pagination import LimitOffsetPagination from common.custom_auth import JSONWebTokenAuthentication from common import swagger_params from django.db.models import Q from rest_framework.decorators import api_view import json -from marketing.models import BlockedDomain, BlockedEmail, ContactEmailCampaign -from marketing.serializer import ( - ContactEmailCampaignSerailizer, - BlockedDomainSerailizer, - BlockedEmailSerailizer, - BlockedDomainAddSerailizer, - BlockedEmailAddSerailizer, -) +from django.contrib.auth.tokens import default_token_generator +from django.utils.encoding import force_text +from django.utils.http import urlsafe_base64_decode +from common.token_generator import account_activation_token +from common.models import Profile +from django.utils import timezone +from crm import settings class GetTeamsAndUsersView(APIView): @@ -61,18 +57,18 @@ class GetTeamsAndUsersView(APIView): permission_classes = (IsAuthenticated,) @swagger_auto_schema( - tags=["Users"], manual_parameters=swagger_params.dashboard_params + tags=["Users"], ) def get(self, request, *args, **kwargs): if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: return Response( - {"error": True, "Message": "Permission Denied"}, + {"error": True, "errors": "Permission Denied"}, status=status.HTTP_403_FORBIDDEN, ) data = {} - teams = Teams.objects.filter(company=request.company) + teams = Teams.objects.filter.all() teams_data = TeamsSerializer(teams, many=True).data - users = User.objects.filter(company=request.company, is_active=True) + users = User.objects.filter(is_active=True) users_data = UserSerializer(users, many=True).data data["teams"] = teams_data data["users_data"] = users_data @@ -88,20 +84,21 @@ def get_object(self, pk): return user @swagger_auto_schema( - tags=["Users"], manual_parameters=swagger_params.dashboard_params + tags=["Users"], ) def get(self, request, pk, format=None): - if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: + user_obj = self.get_object(pk) + if ( + self.request.user.role != "ADMIN" + and not self.request.user.is_superuser + and self.request.user.id != user_obj.id + ): return Response( - {"error": True, "message": "Permission Denied"}, + {"error": True, "errors": "Permission Denied"}, status=status.HTTP_403_FORBIDDEN, ) - user_obj = self.get_object(pk) - if user_obj.company != request.company: - # return Response({'error': 'Id Not found'}, status=status.HTTP_404_NOT_FOUND) - raise Http404 users_data = [] - for each in User.objects.filter(company=request.company): + for each in User.objects.all(): assigned_dict = {} assigned_dict["id"] = each.id assigned_dict["name"] = each.username @@ -119,40 +116,44 @@ def get(self, request, pk, format=None): context["assigned_data"] = users_data comments = user_obj.user_comments.all() context["comments"] = CommentSerializer(comments, many=True).data - return Response({"error": False, "data": context}, status=status.HTTP_200_OK) + return Response( + {"error": False, "data": context}, + status=status.HTTP_200_OK, + ) @swagger_auto_schema( tags=["Users"], manual_parameters=swagger_params.user_update_params ) def put(self, request, pk, format=None): - if request.user.role != "ADMIN" and not request.user.is_superuser: + params = request.query_params if len(request.data) == 0 else request.data + user = self.get_object(pk) + if ( + self.request.user.role != "ADMIN" + and not self.request.user.is_superuser + and self.request.user.id != user.id + ): return Response( - {"error": True, "Message": "Permission Denied"}, + {"error": True, "errors": "Permission Denied"}, status=status.HTTP_403_FORBIDDEN, ) - # raise PermissionDenied - params = request.query_params if len(request.data) == 0 else request.data - user = self.get_object(pk) - if user.company != request.company: - # return Response({'error': 'Id Not found'}, status=status.HTTP_404_NOT_FOUND) - raise Http404 serializer = CreateUserSerializer(user, data=params, request_user=request.user) if serializer.is_valid(): user = serializer.save() - if params.getlist("teams"): - user_teams = user.user_teams.all() - - team_obj = Teams.objects.filter(company=request.company) - for team in params.getlist("teams"): - try: - team_obj = team_obj.filter(id=team).first() - if team_obj != user_teams: - team_obj.users.add(user) - except: - return Response( - {"detail": "No such Team Available"}, - status=status.HTTP_404_NOT_FOUND, - ) + if self.request.user.role == "ADMIN": + if params.getlist("teams"): + user_teams = user.user_teams.all() + + team_obj = Teams.objects.all() + for team in params.getlist("teams"): + try: + team_obj = team_obj.filter(id=team).first() + if team_obj != user_teams: + team_obj.users.add(user) + except: + return Response( + {"detail": "No such Team Available"}, + status=status.HTTP_404_NOT_FOUND, + ) return Response( {"error": False, "message": "User Updated Successfully"}, status=status.HTTP_200_OK, @@ -163,35 +164,29 @@ def put(self, request, pk, format=None): ) @swagger_auto_schema( - tags=["Users"], manual_parameters=swagger_params.dashboard_params + tags=["Users"], ) def delete(self, request, pk, format=None): if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: return Response( - {"error": True, "Message": "Permission Denied"}, + {"error": True, "errors": "Permission Denied"}, status=status.HTTP_403_FORBIDDEN, ) - # raise PermissionDenied self.object = self.get_object(pk) - if self.object.company == request.company: - if self.object.id == request.user.id: - return Response( - {"error": True, "Message": "Permission Denied"}, - status=status.HTTP_403_FORBIDDEN, - ) - current_site = request.get_host() - deleted_by = self.request.user.email - send_email_user_delete.delay( - self.object.email, - deleted_by=deleted_by, - domain=current_site, - protocol=request.scheme, + if self.object.id == request.user.id: + return Response( + {"error": True, "errors": "Permission Denied"}, + status=status.HTTP_403_FORBIDDEN, ) - self.object.delete() - return Response({"status": "success"}, status=status.HTTP_200_OK) - return Response( - {"error": True, "Message": "Id Not Found"}, status=status.HTTP_404_NOT_FOUND + deleted_by = self.request.user.email + send_email_user_delete.delay( + self.object.email, + deleted_by=deleted_by, + domain=settings.Domain, + protocol=request.scheme, ) + self.object.delete() + return Response({"status": "success"}, status=status.HTTP_200_OK) class ChangePasswordView(APIView): @@ -228,7 +223,8 @@ def post(self, request, format=None): if errors: return Response( - {"error": True, "errors": errors}, status=status.HTTP_400_BAD_REQUEST + {"error": True, "errors": errors}, + status=status.HTTP_400_BAD_REQUEST, ) user = request.user user.set_password(new_password) @@ -246,16 +242,14 @@ class ApiHomeView(APIView): permission_classes = (IsAuthenticated,) @swagger_auto_schema( - tags=["dashboard"], manual_parameters=swagger_params.dashboard_params + tags=["dashboard"], ) def get(self, request, format=None): - accounts = Account.objects.filter(status="open", company=request.company) - contacts = Contact.objects.filter(company=request.company) - leads = Lead.objects.filter(company=request.company).exclude( - Q(status="converted") | Q(status="closed") - ) - opportunities = Opportunity.objects.filter(company=request.company) + accounts = Account.objects.filter(status="open") + contacts = Contact.objects.all() + leads = Lead.objects.all().exclude(Q(status="converted") | Q(status="closed")) + opportunities = Opportunity.objects.all() if self.request.user.role == "ADMIN" or self.request.user.is_superuser: pass @@ -296,29 +290,26 @@ class LoginView(APIView): ) def post(self, request, format=None): params = request.query_params if len(request.data) == 0 else request.data - company = request.headers.get("company") username = params.get("email", None) password = params.get("password", None) - company_obj = Company.objects.filter(sub_domain=company).first() - if not company_obj: - company_field = "doesnot exit" - msg = _("company with this subdomin {company_field}") - msg = msg.format(company_field=company_field) - return Response( - {"error": True, "message": msg}, status=status.HTTP_400_BAD_REQUEST - ) if not username: username_field = "User Name/Email" msg = _('Must include "{username_field}"') msg = msg.format(username_field=username_field) return Response( - {"error": True, "message": msg}, status=status.HTTP_400_BAD_REQUEST + {"error": True, "errors": msg}, + status=status.HTTP_400_BAD_REQUEST, ) - user = User.objects.filter(email=username, company=company_obj).first() + user = User.objects.filter(email=username).first() if not user: return Response( - {"error": True, "message": "user not avaliable in our records"}, + {"error": True, "errors": "user not avaliable in our records"}, + status=status.HTTP_400_BAD_REQUEST, + ) + if not user.is_active: + return Response( + {"error": True, "errors": "Please activate account to proceed."}, status=status.HTTP_400_BAD_REQUEST, ) if user.check_password(password): @@ -326,16 +317,15 @@ def post(self, request, format=None): response_data = { "token": jwt_encode_handler(payload), "error": False, - "company": user.company.id, - "subdomin": company_obj.sub_domain, } - return Response(response_data) + return Response(response_data, status=status.HTTP_200_OK) else: password_field = "doesnot match" msg = _("Email and password {password_field}") msg = msg.format(password_field=password_field) return Response( - {"error": True, "message": msg}, status=status.HTTP_400_BAD_REQUEST + {"error": True, "errors": msg}, + status=status.HTTP_400_BAD_REQUEST, ) @@ -347,67 +337,40 @@ class RegistrationView(APIView): ) def post(self, request, format=None): params = request.query_params if len(request.data) == 0 else request.data - sub_domain = params.get("sub_domain", None) - username = params.get("username", None) - email = params.get("email", None) - password = params.get("password", None) + user_serializer = RegisterUserSerializer( + data=params, + request_user=request.user, + ) errors = {} - if sub_domain: - if Company.objects.filter(sub_domain__iexact=sub_domain): - errors["sub_domain"] = "company with this subdomin already exit" - - if username: - if User.objects.filter(username__iexact=username): - errors["username"] = "User name already exit." - if email: - if User.objects.filter(email__iexact=email): - errors["email"] = "Email already exit." - - if password: - if len(password) < 8: - errors["password"] = "Password must be at least 8 characters long!" - + if not user_serializer.is_valid(): + errors.update(user_serializer.errors) if errors: return Response( - {"error": True, "errors": errors}, status=status.HTTP_400_BAD_REQUEST + {"error": True, "errors": errors}, + status=status.HTTP_400_BAD_REQUEST, ) - else: - user = User.objects.create(username=username, email=email) - company = Company.objects.create(sub_domain=sub_domain) - company.save() - user.company = company - user.role = "ADMIN" - user.is_superuser = False - user.has_marketing_access = True - user.has_sales_access = True - user.is_admin = True - user.set_password(password) + if user_serializer.is_valid(): + user = user_serializer.save( + role="ADMIN", + is_superuser=False, + has_marketing_access=True, + has_sales_access=True, + is_admin=True, + ) + if params.get("password"): + user.set_password(params.get("password")) user.save() - return Response({"error": False}, status=status.HTTP_201_CREATED) - - -@swagger_auto_schema( - method="post", - tags=["Auth"], - manual_parameters=swagger_params.check_sub_domain_params, -) -@api_view(["POST"]) -def check_sub_domain(request): - if request.method == "POST": - params = request.query_params if len(request.data) == 0 else request.data - sub_domain = params.get("sub_domain", None) - msg = _("Given sub_domain {domain_name} is {validity_status}") - company = Company.objects.filter(sub_domain=sub_domain).first() - if company: - request.session["company"] = company.id - msg = msg.format(domain_name=sub_domain, validity_status="Valid") - status_code = status.HTTP_200_OK - status_msg = False - else: - msg = msg.format(domain_name=sub_domain, validity_status="Invalid") - status_code = status.HTTP_400_BAD_REQUEST - status_msg = True - return Response({"error": status_msg, "message": msg}, status=status_code) + protocol = request.scheme + send_email_to_new_user.delay( + user.email, + user.email, + domain=settings.Domain, + protocol=protocol, + ) + return Response( + {"error": False, "message": "User created Successfully."}, + status=status.HTTP_200_OK, + ) class ProfileView(APIView): @@ -415,7 +378,7 @@ class ProfileView(APIView): permission_classes = (IsAuthenticated,) @swagger_auto_schema( - tags=["Profile"], manual_parameters=swagger_params.dashboard_params + tags=["Profile"], ) def get(self, request, format=None): context = {} @@ -423,7 +386,7 @@ def get(self, request, format=None): return Response(context, status=status.HTTP_200_OK) -class UsersListView(APIView): +class UsersListView(APIView, LimitOffsetPagination): authentication_classes = (JSONWebTokenAuthentication,) permission_classes = (IsAuthenticated,) @@ -434,7 +397,7 @@ class UsersListView(APIView): def post(self, request, format=None): if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: return Response( - {"error": True, "Message": "Permission Denied"}, + {"error": True, "errors": "Permission Denied"}, status=status.HTTP_403_FORBIDDEN, ) else: @@ -447,15 +410,13 @@ def post(self, request, format=None): user = user_serializer.save() if params.get("password"): user.set_password(params.get("password")) - user.company = self.request.company - user.save() + user.is_active = False - current_site = request.get_host() protocol = request.scheme send_email_to_new_user.delay( user.email, self.request.user.email, - domain=current_site, + domain=settings.Domain, protocol=protocol, ) return Response( @@ -473,11 +434,11 @@ def post(self, request, format=None): def get(self, request, format=None): if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: return Response( - {"error": True, "Message": "Permission Denied"}, + {"error": True, "errors": "Permission Denied"}, status=status.HTTP_403_FORBIDDEN, ) else: - queryset = User.objects.filter(company=self.request.company) + queryset = User.objects.all() params = ( self.request.query_params if len(self.request.data) == 0 @@ -496,17 +457,40 @@ def get(self, request, format=None): queryset = queryset.filter(is_active=params.get("status")) context = {} - active_users = queryset.filter(is_active=True) - inactive_users = queryset.filter(is_active=False) - context["active_users"] = UserSerializer(active_users, many=True).data - context["inactive_users"] = UserSerializer(inactive_users, many=True).data + queryset_active_users = queryset.filter(is_active=True) + results_active_users = self.paginate_queryset( + queryset_active_users.distinct(), self.request, view=self + ) + active_users = UserSerializer(results_active_users, many=True).data + context["per_page"] = 10 + context["active_users"] = { + "active_users_count": self.count, + "next": self.get_next_link(), + "previous": self.get_previous_link(), + "page_number": int(self.offset / 10) + 1, + "active_users": active_users, + } + + queryset_inactive_users = queryset.filter(is_active=False) + results_inactive_users = self.paginate_queryset( + queryset_inactive_users.distinct(), self.request, view=self + ) + inactive_users = UserSerializer(results_inactive_users, many=True).data + context["inactive_users"] = { + "inactive_users_count": self.count, + "next": self.get_next_link(), + "previous": self.get_previous_link(), + "page_number": int(self.offset / 10) + 1, + "inactive_users": inactive_users, + } + context["admin_email"] = settings.ADMIN_EMAIL context["roles"] = ROLES context["status"] = [("True", "Active"), ("False", "In Active")] return Response(context) -class DocumentListView(APIView): +class DocumentListView(APIView, LimitOffsetPagination): authentication_classes = (JSONWebTokenAuthentication,) permission_classes = (IsAuthenticated,) model = Document @@ -517,7 +501,7 @@ def get_context_data(self, **kwargs): if len(self.request.data) == 0 else self.request.data ) - queryset = self.model.objects.filter(company=self.request.company) + queryset = self.model.objects.all() if self.request.user.is_superuser or self.request.user.role == "ADMIN": queryset = queryset else: @@ -546,13 +530,9 @@ def get_context_data(self, **kwargs): context = {} if self.request.user.role == "ADMIN" or self.request.user.is_superuser: - users = User.objects.filter( - is_active=True, company=self.request.company - ).order_by("email") + users = User.objects.filter(is_active=True).order_by("email") else: - users = User.objects.filter( - role="ADMIN", company=self.request.company - ).order_by("email") + users = User.objects.filter(role="ADMIN").order_by("email") search = False if ( params.get("document_file") @@ -561,12 +541,37 @@ def get_context_data(self, **kwargs): ): search = True context["search"] = search - context["documents_active"] = DocumentSerializer( - queryset.filter(status="active").distinct(), many=True - ).data - context["documents_inactive"] = DocumentSerializer( - queryset.filter(status="inactive").distinct(), many=True + + queryset_documents_active = queryset.filter(status="active") + results_documents_active = self.paginate_queryset( + queryset_documents_active.distinct(), self.request, view=self + ) + documents_active = DocumentSerializer(results_documents_active, many=True).data + context["per_page"] = 10 + context["documents_active"] = { + "documents_active_count": self.count, + "next": self.get_next_link(), + "previous": self.get_previous_link(), + "page_number": int(self.offset / 10) + 1, + "documents_active": documents_active, + } + + queryset_documents_inactive = queryset.filter(status="inactive") + results_documents_inactive = self.paginate_queryset( + queryset_documents_inactive.distinct(), self.request, view=self + ) + documents_inactive = DocumentSerializer( + results_documents_inactive, many=True ).data + + context["documents_inactive"] = { + "documents_inactive_count": self.count, + "next": self.get_next_link(), + "previous": self.get_previous_link(), + "page_number": int(self.offset / 10) + 1, + "documents_inactive": documents_inactive, + } + context["users"] = UserSerializer(users, many=True).data context["status_choices"] = Document.DOCUMENT_STATUS_CHOICE return context @@ -587,31 +592,32 @@ def post(self, request, *args, **kwargs): if serializer.is_valid(): doc = serializer.save( created_by=request.user, - company=request.company, document_file=request.FILES.get("document_file"), ) if params.get("shared_to"): assinged_to_users_ids = json.loads(params.get("shared_to")) for user_id in assinged_to_users_ids: - user = User.objects.filter(id=user_id, company=request.company) + user = User.objects.filter(id=user_id) if user: doc.shared_to.add(user_id) else: doc.delete() - return Response({"error": True, "error": "Enter Valid User"}) + return Response( + {"error": True, "errors": "Enter Valid User"}, + status=status.HTTP_400_BAD_REQUEST, + ) if self.request.user.role == "ADMIN": if params.get("teams"): teams = json.loads(params.get("teams")) for team in teams: - teams_ids = Teams.objects.filter( - id=team, company=request.company - ) + teams_ids = Teams.objects.filter(id=team) if teams_ids: doc.teams.add(team) else: doc.delete() return Response( - {"error": True, "error": "Enter Valid Team"} + {"error": True, "errors": "Enter Valid Team"}, + status=status.HTTP_400_BAD_REQUEST, ) return Response( @@ -632,13 +638,13 @@ def get_object(self, pk): return Document.objects.filter(id=pk).first() @swagger_auto_schema( - tags=["documents"], manual_parameters=swagger_params.dashboard_params + tags=["documents"], ) def get(self, request, pk, format=None): self.object = self.get_object(pk) - if not self.object or self.object.company != self.request.company: + if not self.object: return Response( - {"error": True, "errors": "User company doesnot match with header...."}, + {"error": True, "errors": "Document does not exist"}, status=status.HTTP_403_FORBIDDEN, ) if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: @@ -650,12 +656,11 @@ def get(self, request, pk, format=None): { "error": True, "errors": "You do not have Permission to perform this action", - } + }, + status=status.HTTP_403_FORBIDDEN, ) if request.user.role == "ADMIN" or request.user.is_superuser: - users = User.objects.filter( - is_active=True, company=request.company - ).order_by("email") + users = User.objects.filter(is_active=True).order_by("email") else: users = User.objects.filter(role="ADMIN").order_by("email") context = {} @@ -669,13 +674,13 @@ def get(self, request, pk, format=None): return Response(context, status=status.HTTP_200_OK) @swagger_auto_schema( - tags=["documents"], manual_parameters=swagger_params.dashboard_params + tags=["documents"], ) def delete(self, request, pk, format=None): document = self.get_object(pk) - if not document or document.company != self.request.company: + if not document: return Response( - {"error": True, "errors": "User company doesnot match with header...."}, + {"error": True, "errors": "Documdnt does not exist"}, status=status.HTTP_403_FORBIDDEN, ) @@ -702,9 +707,9 @@ def delete(self, request, pk, format=None): def put(self, request, pk, format=None): self.object = self.get_object(pk) params = request.query_params if len(request.data) == 0 else request.data - if not self.object or self.object.company != self.request.company: + if not self.object: return Response( - {"error": True, "errors": "User company doesnot match with header...."}, + {"error": True, "errors": "Document does not exist"}, status=status.HTTP_403_FORBIDDEN, ) if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: @@ -716,7 +721,8 @@ def put(self, request, pk, format=None): { "error": True, "errors": "You do not have Permission to perform this action", - } + }, + status=status.HTTP_403_FORBIDDEN, ) serializer = DocumentCreateSerializer( data=params, instance=self.object, request_obj=request @@ -730,25 +736,27 @@ def put(self, request, pk, format=None): if params.get("shared_to"): assinged_to_users_ids = json.loads(params.get("shared_to")) for user_id in assinged_to_users_ids: - user = User.objects.filter(id=user_id, company=request.company) + user = User.objects.filter(id=user_id) if user: doc.shared_to.add(user_id) else: - return Response({"error": True, "error": "Enter Valid User"}) + return Response( + {"error": True, "errors": "Enter Valid User"}, + status=status.HTTP_400_BAD_REQUEST, + ) if self.request.user.role == "ADMIN": doc.teams.clear() if params.get("teams"): teams = json.loads(params.get("teams")) for team in teams: - teams_ids = Teams.objects.filter( - id=team, company=request.company - ) + teams_ids = Teams.objects.filter(id=team) if teams_ids: doc.teams.add(team) else: return Response( - {"error": True, "error": "Enter Valid Team"} + {"error": True, "errors": "Enter Valid Team"}, + status=status.HTTP_400_BAD_REQUEST, ) return Response( {"error": False, "message": "Document Updated Successfully"}, @@ -769,10 +777,14 @@ def post(self, request, format=None): serializer = ForgotPasswordSerializer(data=params) if serializer.is_valid(): user = get_object_or_404(User, email=params.get("email")) - current_site = self.request.get_host() + if not user.is_active: + return Response( + {"error": True, "errors": "Please activate account to proceed."}, + status=status.HTTP_406_NOT_ACCEPTABLE, + ) protocol = self.request.scheme send_email_to_reset_password.delay( - user.email, protocol=protocol, domain=current_site + user.email, protocol=protocol, domain=settings.Domain ) data = { "error": False, @@ -789,7 +801,7 @@ class ResetPasswordView(APIView): @swagger_auto_schema( tags=["Auth"], manual_parameters=swagger_params.reset_password_params ) - def post(self, request, format=None): + def post(self, request, uid, token, format=None): params = request.query_params if len(request.data) == 0 else request.data serializer = ResetPasswordSerailizer(data=params) if serializer.is_valid(): @@ -806,47 +818,14 @@ def post(self, request, format=None): return Response(data, status=status.HTTP_400_BAD_REQUEST) -class ContactsEmailCampaignListView(APIView): - model = ContactEmailCampaign +class UserStatusView(APIView): authentication_classes = (JSONWebTokenAuthentication,) permission_classes = (IsAuthenticated,) - def get_context_data(self, **kwargs): - params = ( - self.request.query_params - if len(self.request.data) == 0 - else self.request.data - ) - queryset = self.model.objects.filter(company=self.request.company) - - context = {} - search = False - if params: - if params.get("name"): - queryset = queryset.filter( - Q(name__icontains=params.get("name")) - | Q(last_name__icontains=params.get("name")) - ) - if params.get("email"): - queryset = queryset.filter(email__icontains=params.get("email")) - if params.get("created_by"): - queryset = queryset.filter(created_by=params.get("created_by")) - search = True - - context["search"] = search - - context["contacts"] = ContactEmailCampaignSerailizer(queryset, many=True).data - users = User.objects.filter( - is_active=True, role="ADMIN", company=self.request.company - ).order_by("email") - - context["users"] = UserSerializer(users, many=True).data - return context - @swagger_auto_schema( - tags=["Settings"], manual_parameters=swagger_params.settings_contact_get_params + tags=["Users"], manual_parameters=swagger_params.users_status_params ) - def get(self, request, *args, **kwargs): + def post(self, request, pk, format=None): if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: return Response( { @@ -855,201 +834,77 @@ def get(self, request, *args, **kwargs): }, status=status.HTTP_403_FORBIDDEN, ) - context = self.get_context_data(**kwargs) - return Response(context) + params = request.query_params if len(request.data) == 0 else request.data + user = User.objects.get(id=pk) - @swagger_auto_schema( - tags=["Settings"], - manual_parameters=swagger_params.settings_contact_create_params, - ) - def post(self, request, *args, **kwargs): - if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: - return Response( - { - "error": True, - "errors": "You do not have permission to perform this action", - }, - status=status.HTTP_403_FORBIDDEN, - ) - params = ( - self.request.query_params - if len(self.request.data) == 0 - else self.request.data - ) + if params.get("status"): + status = params.get("status") + if status == "Active": + user.is_active = True + elif status == "Inactive": + user.is_active = False + else: + return Response( + {"error": True, "errors": "Please enter Valid Status for user"}, + status=status.HTTP_400_BAD_REQUEST, + ) + user.save() - serializer = ContactEmailCampaignSerailizer(data=params, request_obj=request) - if serializer.is_valid(): - serializer.save(created_by=request.user, company=request.company) - return Response( - {"error": False, "message": "Email for Campaign created Successfully"}, - status=status.HTTP_200_OK, - ) - return Response( - {"error": True, "errors": serializer.errors}, - status=status.HTTP_400_BAD_REQUEST, - ) + context = {} + users_Active = User.objects.filter(is_active=True) + users_Inactive = User.objects.filter(is_active=False) + context["Users_Active"] = UserSerializer(users_Active, many=True).data + context["Users_Inactive"] = UserSerializer(users_Inactive, many=True).data + return Response(context) -class ContactsEmailCampaignDetailView(APIView): - model = ContactEmailCampaign +class DomainList(APIView): + model = APISettings authentication_classes = (JSONWebTokenAuthentication,) permission_classes = (IsAuthenticated,) - def get_object(self, pk): - return self.model.objects.get(pk=pk) - - # def get_context_data(self, **kwargs): - # context = {} - # context["contacts"] = ContactEmailCampaignSerailizer( - # self.contact_obj).data - # users = User.objects.filter( - # is_active=True, - # role = "ADMIN", - # company=self.request.company).order_by("email") - - # context["users"] = UserSerializer(users, many=True).data - # return context - - # @swagger_auto_schema( - # tags=["Settings"], manual_parameters=swagger_params.dashboard_params - # ) - # def get(self, request, pk, **kwargs): - # if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: - # return Response({ - # "error": True, - # "errors": "You do not have permission to perform this action"}, - # status = status.HTTP_403_FORBIDDEN - # ) - # self.contact_obj = self.get_object(pk) - # if self.contact_obj.company != request.company: - # return Response( - # {"error": True, - # "errors": "User company doesnot match with header...."} - # ) - # context = self.get_context_data(**kwargs) - # return Response(context) - @swagger_auto_schema( tags=["Settings"], - manual_parameters=swagger_params.settings_contact_create_params, ) - def put(self, request, pk, format=None): - if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: - return Response( - { - "error": True, - "errors": "You do not have permission to perform this action", - }, - status=status.HTTP_403_FORBIDDEN, - ) - params = request.query_params if len(request.data) == 0 else request.data - obj = self.get_object(pk) - if obj.company != request.company: - return Response( - {"error": True, "errors": "User company doesnot match with header...."} - ) - serializer = ContactEmailCampaignSerailizer(obj, data=params) - if serializer.is_valid(): - serializer.save() - return Response( - {"error": False, "message": "Email for Campaign Updated Successfully"}, - status=status.HTTP_200_OK, - ) - return Response( - {"error": True, "errors": serializer.errors}, - status=status.HTTP_400_BAD_REQUEST, - ) - - @swagger_auto_schema( - tags=["Settings"], manual_parameters=swagger_params.dashboard_params - ) - def delete(self, request, pk, format=None): - if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: - return Response( - { - "error": True, - "errors": "You do not have permission to perform this action", - }, - status=status.HTTP_403_FORBIDDEN, - ) - self.object = self.get_object(pk) - if self.object.company != request.company: - return Response( - {"error": True, "errors": "User company doesnot match with header...."} - ) - self.object.delete() + def get(self, request, *args, **kwargs): + api_settings = APISettings.objects.all() + users = User.objects.filter(is_active=True).order_by("email") return Response( - {"error": True, "errors": "Email for Campaign Deleted Successfully"}, + { + "error": False, + "api_settings": APISettingsListSerializer(api_settings, many=True).data, + "users": UserSerializer(users, many=True).data, + }, status=status.HTTP_200_OK, ) - -class BlockDomainsListView(APIView): - model = BlockedDomain - authentication_classes = (JSONWebTokenAuthentication,) - permission_classes = (IsAuthenticated,) - - def get_context_data(self, **kwargs): - params = ( - self.request.query_params - if len(self.request.data) == 0 - else self.request.data - ) - queryset = self.model.objects.filter(company=self.request.company) - - context = {} - search = False - if params: - if params.get("domain"): - queryset = queryset.filter(Q(domain__icontains=params.get("domain"))) - search = True - - context["search"] = search - - context["blocked_domains"] = BlockedDomainSerailizer(queryset, many=True).data - return context - - @swagger_auto_schema( - tags=["Settings"], - manual_parameters=swagger_params.settings_blockdomains_create_params, - ) - def get(self, request, *args, **kwargs): - if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: - return Response( - { - "error": True, - "errors": "You do not have permission to perform this action", - }, - status=status.HTTP_403_FORBIDDEN, - ) - context = self.get_context_data(**kwargs) - return Response(context) - @swagger_auto_schema( - tags=["Settings"], - manual_parameters=swagger_params.settings_blockdomains_create_params, + tags=["Settings"], manual_parameters=swagger_params.api_setting_create_params ) def post(self, request, *args, **kwargs): - if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: - return Response( - { - "error": True, - "errors": "You do not have permission to perform this action", - }, - status=status.HTTP_403_FORBIDDEN, - ) params = ( self.request.query_params if len(self.request.data) == 0 else self.request.data ) - - serializer = BlockedDomainAddSerailizer(data=params, request_obj=request) + assign_to_list = [] + if params.get("lead_assigned_to"): + assign_to_list = json.loads(params.get("lead_assigned_to")) + serializer = APISettingsSerializer(data=params) if serializer.is_valid(): - serializer.save(created_by=request.user, company=request.company) + settings_obj = serializer.save(created_by=request.user) + if params.get("tags"): + tags = json.loads(params.get("tags")) + for tag in tags: + tag_obj = Tags.objects.filter(name=tag).first() + if not tag_obj: + tag_obj = Tags.objects.create(name=tag) + settings_obj.tags.add(tag_obj) + if assign_to_list: + settings_obj.lead_assigned_to.add(*assign_to_list) return Response( - {"error": False, "message": "Blocked Domain created Successfully"}, - status=status.HTTP_200_OK, + {"error": False, "message": "API key added sucessfully"}, + status=status.HTTP_201_CREATED, ) return Response( {"error": True, "errors": serializer.errors}, @@ -1057,159 +912,53 @@ def post(self, request, *args, **kwargs): ) -class BlockDomainsDetailView(APIView): - model = BlockedDomain +class DomainDetailView(APIView): + model = APISettings authentication_classes = (JSONWebTokenAuthentication,) permission_classes = (IsAuthenticated,) def get_object(self, pk): return self.model.objects.get(pk=pk) - # def get_context_data(self, **kwargs): - # context = {} - # context["blocked_domains"] = BlockedDomainSerailizer( - # self.obj).data - # return context - - # @swagger_auto_schema( - # tags=["Settings"], manual_parameters=swagger_params.dashboard_params - # ) - # def get(self, request, pk, **kwargs): - # if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: - # return Response({ - # "error": True, - # "errors": "You do not have permission to perform this action"}, - # status = status.HTTP_403_FORBIDDEN - # ) - # self.obj = self.get_object(pk) - # if self.obj.company != request.company: - # return Response( - # {"error": True, - # "errors": "User company doesnot match with header...."} - # ) - # context = self.get_context_data(**kwargs) - # return Response(context) - @swagger_auto_schema( tags=["Settings"], - manual_parameters=swagger_params.settings_blockdomains_create_params, ) - def put(self, request, pk, format=None): - if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: - return Response( - { - "error": True, - "errors": "You do not have permission to perform this action", - }, - status=status.HTTP_403_FORBIDDEN, - ) - params = request.query_params if len(request.data) == 0 else request.data - obj = self.get_object(pk) - if obj.company != request.company: - return Response( - {"error": True, "errors": "User company doesnot match with header...."} - ) - serializer = BlockedDomainAddSerailizer(obj, data=params, request_obj=request) - if serializer.is_valid(): - serializer.save() - return Response( - {"error": False, "message": "Blocked Domain Updated Successfully"}, - status=status.HTTP_200_OK, - ) - return Response( - {"error": True, "errors": serializer.errors}, - status=status.HTTP_400_BAD_REQUEST, - ) - - @swagger_auto_schema( - tags=["Settings"], manual_parameters=swagger_params.dashboard_params - ) - def delete(self, request, pk, format=None): - if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: - return Response( - { - "error": True, - "errors": "You do not have permission to perform this action", - }, - status=status.HTTP_403_FORBIDDEN, - ) - self.object = self.get_object(pk) - if self.object.company != request.company: - return Response( - {"error": True, "errors": "User company doesnot match with header...."} - ) - self.object.delete() + def get(self, request, pk, format=None): + api_setting = self.get_object(pk) return Response( - {"error": True, "errors": "Blocked Domain Deleted Successfully"}, + {"error": False, "domain": APISettingsListSerializer(api_setting).data}, status=status.HTTP_200_OK, ) - -class BlockEmailsListView(APIView): - model = BlockedEmail - authentication_classes = (JSONWebTokenAuthentication,) - permission_classes = (IsAuthenticated,) - - def get_context_data(self, **kwargs): - params = ( - self.request.query_params - if len(self.request.data) == 0 - else self.request.data - ) - queryset = self.model.objects.filter(company=self.request.company) - - context = {} - search = False - if params: - if params.get("email"): - queryset = queryset.filter(Q(email__icontains=params.get("email"))) - search = True - - context["search"] = search - - context["blocked_emails"] = BlockedEmailSerailizer(queryset, many=True).data - return context - - @swagger_auto_schema( - tags=["Settings"], - manual_parameters=swagger_params.settings_blockemails_create_params, - ) - def get(self, request, *args, **kwargs): - if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: - return Response( - { - "error": True, - "errors": "You do not have permission to perform this action", - }, - status=status.HTTP_403_FORBIDDEN, - ) - context = self.get_context_data(**kwargs) - return Response(context) - @swagger_auto_schema( - tags=["Settings"], - manual_parameters=swagger_params.settings_blockemails_create_params, + tags=["Settings"], manual_parameters=swagger_params.api_setting_create_params ) - def post(self, request, *args, **kwargs): - if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: - return Response( - { - "error": True, - "errors": "You do not have permission to perform this action", - }, - status=status.HTTP_403_FORBIDDEN, - ) + def put(self, request, pk, **kwargs): + api_setting = self.get_object(pk) params = ( self.request.query_params if len(self.request.data) == 0 else self.request.data ) - - serializer = BlockedEmailAddSerailizer(data=params, request_obj=request) + assign_to_list = [] + if params.get("lead_assigned_to"): + assign_to_list = json.loads(params.get("lead_assigned_to")) + serializer = APISettingsSerializer(data=params, instance=api_setting) if serializer.is_valid(): - serializer.save(created_by=request.user, company=request.company) + api_setting = serializer.save() + api_setting.tags.clear() + api_setting.lead_assigned_to.clear() + if params.get("tags"): + tags = json.loads(params.get("tags")) + for tag in tags: + tag_obj = Tags.objects.filter(name=tag).first() + if not tag_obj: + tag_obj = Tags.objects.create(name=tag) + api_setting.tags.add(tag_obj) + if assign_to_list: + api_setting.lead_assigned_to.add(*assign_to_list) return Response( - {"error": False, "message": "Blocked Email added Successfully"}, + {"error": False, "message": "API setting Updated sucessfully"}, status=status.HTTP_200_OK, ) return Response( @@ -1217,137 +966,85 @@ def post(self, request, *args, **kwargs): status=status.HTTP_400_BAD_REQUEST, ) - -class BlockEmailsDetailView(APIView): - model = BlockedEmail - authentication_classes = (JSONWebTokenAuthentication,) - permission_classes = (IsAuthenticated,) - - def get_object(self, pk): - return self.model.objects.get(pk=pk) - - # def get_context_data(self, **kwargs): - # context = {} - # context["blocked_emails"] = BlockedEmailSerailizer( - # self.obj).data - # return context - - # @swagger_auto_schema( - # tags=["Settings"], - # manual_parameters=swagger_params.dashboard_params - # ) - # def get(self, request, pk, **kwargs): - # if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: - # return Response({ - # "error": True, - # "errors": "You do not have permission to perform this action"}, - # status = status.HTTP_403_FORBIDDEN - # ) - # self.obj = self.get_object(pk) - # if self.obj.company != request.company: - # return Response( - # {"error": True, - # "errors": "User company doesnot match with header...."} - # ) - # context = self.get_context_data(**kwargs) - # return Response(context) - @swagger_auto_schema( tags=["Settings"], - manual_parameters=swagger_params.settings_blockemails_create_params, ) - def put(self, request, pk, format=None): - if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: - return Response( - { - "error": True, - "errors": "You do not have permission to perform this action", - }, - status=status.HTTP_403_FORBIDDEN, - ) - params = request.query_params if len(request.data) == 0 else request.data - obj = self.get_object(pk) - if obj.company != request.company: - return Response( - {"error": True, "errors": "User company doesnot match with header...."} - ) - serializer = BlockedEmailAddSerailizer(obj, data=params, request_obj=request) - if serializer.is_valid(): - serializer.save() - return Response( - {"error": False, "message": "Blocked Email Updated Successfully"}, - status=status.HTTP_200_OK, - ) + def delete(self, request, pk, **kwargs): + api_setting = self.get_object(pk) + if api_setting: + api_setting.delete() return Response( - {"error": True, "errors": serializer.errors}, - status=status.HTTP_400_BAD_REQUEST, + {"error": False, "message": "API setting deleted sucessfully"}, + status=status.HTTP_200_OK, ) + +class ActivateUserView(APIView): @swagger_auto_schema( - tags=["Settings"], manual_parameters=swagger_params.dashboard_params + tags=["Auth"], ) - def delete(self, request, pk, format=None): - if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: - return Response( - { - "error": True, - "errors": "You do not have permission to perform this action", - }, - status=status.HTTP_403_FORBIDDEN, - ) - self.object = self.get_object(pk) - if self.object.company != request.company: - return Response( - {"error": True, "errors": "User company doesnot match with header...."} - ) - self.object.delete() - return Response( - {"error": True, "errors": "Blocked Email Deleted Successfully"}, - status=status.HTTP_200_OK, - ) - + def post(self, request, uid, token, activation_key, format=None): + profile = get_object_or_404(Profile, activation_key=activation_key) + if profile.user: + if timezone.now() > profile.key_expires: + protocol = request.scheme + resend_activation_link_to_user.delay( + profile.user.email, + domain=settings.Domain, + protocol=protocol, + ) + return Response( + { + "error": False, + "message": "Link expired. Please use the Activation link sent now to your mail.", + }, + status=status.HTTP_406_NOT_ACCEPTABLE, + ) + else: + try: + uid = force_text(urlsafe_base64_decode(uid)) + user = User.objects.get(pk=uid) + except (TypeError, ValueError, OverflowError, User.DoesNotExist): + user = None + if user is not None and account_activation_token.check_token( + user, token + ): + user.is_active = True + user.save() + return Response( + { + "error": False, + "message": "Thank you for your email confirmation. Now you can login to your account.", + }, + status=status.HTTP_200_OK, + ) + else: + return Response( + {"error": True, "errors": "Activation link is invalid!"}, + status=status.HTTP_400_BAD_REQUEST, + ) -class UserStatusView(APIView): - authentication_classes = (JSONWebTokenAuthentication,) - permission_classes = (IsAuthenticated,) +class ResendActivationLinkView(APIView): @swagger_auto_schema( - tags=["Users"], manual_parameters=swagger_params.users_status_params + tags=["Auth"], manual_parameters=swagger_params.forgot_password_params ) - def post(self, request, pk, format=None): - if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: - return Response( - { - "error": True, - "errors": "You do not have permission to perform this action", - } - ) + def post(self, request, format=None): params = request.query_params if len(request.data) == 0 else request.data - user = User.objects.get(id=pk, company=request.company) - if user.company != request.company: + user = get_object_or_404(User, email=params.get("email")) + if user.is_active: return Response( - { - "error": True, - "errors": "User company does not match with the header", - }, - status=status.HTTP_404_NOT_FOUND, + {"error": False, "message": "Account is active. Please login"}, + status=status.HTTP_200_OK, ) - - if params.get("status"): - status = params.get("status") - if status == "Active": - user.is_active = True - elif status == "Inactive": - user.is_active = False - else: - return Response( - {"error": True, "errors": "Please enter Valid Status for user"} - ) - user.save() - - context = {} - users_Active = User.objects.filter(is_active=True, company=request.company) - users_Inactive = User.objects.filter(is_active=False, company=request.company) - context["Users_Active"] = UserSerializer(users_Active, many=True).data - context["Users_Inactive"] = UserSerializer(users_Inactive, many=True).data - return Response(context) + protocol = request.scheme + resend_activation_link_to_user.delay( + user.email, + domain=settings.Domain, + protocol=protocol, + ) + data = { + "error": False, + "message": "Please use the Activation link sent to your mail to activate account.", + } + return Response(data, status=status.HTTP_200_OK) diff --git a/common/app_urls/__init__.py b/common/app_urls/__init__.py index 3b78a11..3e1ae22 100644 --- a/common/app_urls/__init__.py +++ b/common/app_urls/__init__.py @@ -13,5 +13,4 @@ path("tasks/", include("tasks.api_urls", namespace="api_tasks")), path("events/", include("events.api_urls", namespace="api_events")), path("cases/", include("cases.api_urls", namespace="api_cases")), - path("invoices/", include("invoices.api_urls", namespace="api_invoices")), ] diff --git a/common/custom_auth.py b/common/custom_auth.py index e7a44a9..65b56a5 100644 --- a/common/custom_auth.py +++ b/common/custom_auth.py @@ -68,10 +68,6 @@ def authenticate_credentials(self, payload): raise exceptions.AuthenticationFailed(msg) try: account = User.objects.get(pk=account_id) - if account.company.sub_domain != self.company: - raise exceptions.AuthenticationFailed( - "user company doesnot match with header...." - ) except User.DoesNotExist: msg = _("Invalid signature.") diff --git a/common/forms.py b/common/forms.py deleted file mode 100644 index 412f2bf..0000000 --- a/common/forms.py +++ /dev/null @@ -1,372 +0,0 @@ -import re - -from common.models import Address, APISettings, Comment, Company, Document, User -from django import forms -from django.contrib.auth import authenticate, password_validation -from django.contrib.auth.forms import PasswordResetForm -from teams.models import Teams - - -class BillingAddressForm(forms.ModelForm): - class Meta: - model = Address - fields = ("address_line", "street", "city", "state", "postcode", "country") - - def __init__(self, *args, **kwargs): - account_view = kwargs.pop("account", False) - - super(BillingAddressForm, self).__init__(*args, **kwargs) - for field in self.fields.values(): - field.widget.attrs = {"class": "form-control"} - self.fields["address_line"].widget.attrs.update({"placeholder": "Address Line"}) - self.fields["street"].widget.attrs.update({"placeholder": "Street"}) - self.fields["city"].widget.attrs.update({"placeholder": "City"}) - self.fields["state"].widget.attrs.update({"placeholder": "State"}) - self.fields["postcode"].widget.attrs.update({"placeholder": "Postcode"}) - self.fields["country"].choices = [("", "--Country--"),] + list( - self.fields["country"].choices - )[1:] - - if account_view: - self.fields["address_line"].required = True - self.fields["street"].required = True - self.fields["city"].required = True - self.fields["state"].required = True - self.fields["postcode"].required = True - self.fields["country"].required = True - - -class ShippingAddressForm(forms.ModelForm): - class Meta: - model = Address - fields = ("address_line", "street", "city", "state", "postcode", "country") - - def __init__(self, *args, **kwargs): - super(ShippingAddressForm, self).__init__(*args, **kwargs) - for field in self.fields.values(): - field.widget.attrs = {"class": "form-control"} - self.fields["address_line"].widget.attrs.update({"placeholder": "Address Line"}) - self.fields["street"].widget.attrs.update({"placeholder": "Street"}) - self.fields["city"].widget.attrs.update({"placeholder": "City"}) - self.fields["state"].widget.attrs.update({"placeholder": "State"}) - self.fields["postcode"].widget.attrs.update({"placeholder": "Postcode"}) - self.fields["country"].choices = [("", "--Country--"),] + list( - self.fields["country"].choices - )[1:] - - -class UserForm(forms.ModelForm): - - password = forms.CharField(max_length=100, required=False) - # sales = forms.BooleanField(required=False) - # marketing = forms.BooleanField(required=False) - - class Meta: - model = User - fields = [ - "email", - "first_name", - "last_name", - "username", - "role", - "profile_pic", - "has_sales_access", - "has_marketing_access", - ] - - def __init__(self, *args, **kwargs): - self.request_user = kwargs.pop("request_user", None) - super(UserForm, self).__init__(*args, **kwargs) - self.fields["first_name"].required = True - if not self.instance.pk: - self.fields["password"].required = True - - # self.fields['password'].required = True - - # def __init__(self, args: object, kwargs: object) -> object: - # super(UserForm, self).__init__(*args, **kwargs) - # - # self.fields['first_name'].required = True - # self.fields['username'].required = True - # self.fields['email'].required = True - # - # if not self.instance.pk: - # self.fields['password'].required = True - - def clean_password(self): - password = self.cleaned_data.get("password") - if password: - if len(password) < 4: - raise forms.ValidationError( - "Password must be at least 4 characters long!" - ) - return password - - def clean_has_sales_access(self): - sales = self.cleaned_data.get("has_sales_access", False) - user_role = self.cleaned_data.get("role") - if user_role == "ADMIN": - is_admin = True - else: - is_admin = False - if self.request_user.role == "ADMIN" or self.request_user.is_superuser: - if not is_admin: - marketing = self.data.get("has_marketing_access", False) - if not sales and not marketing: - raise forms.ValidationError("Select atleast one option.") - # if not (self.instance.role == 'ADMIN' or self.instance.is_superuser): - # marketing = self.data.get('has_marketing_access', False) - # if not sales and not marketing: - # raise forms.ValidationError('Select atleast one option.') - if self.request_user.role == "USER": - sales = self.instance.has_sales_access - return sales - - def clean_has_marketing_access(self): - marketing = self.cleaned_data.get("has_marketing_access", False) - if self.request_user.role == "USER": - marketing = self.instance.has_marketing_access - return marketing - - def clean_email(self): - email = self.cleaned_data.get("email") - if self.instance.id: - if self.instance.email != email: - if not User.objects.filter( - email=self.cleaned_data.get("email") - ).exists(): - return self.cleaned_data.get("email") - raise forms.ValidationError("Email already exists") - else: - return self.cleaned_data.get("email") - else: - if not User.objects.filter(email=self.cleaned_data.get("email")).exists(): - return self.cleaned_data.get("email") - raise forms.ValidationError("User already exists with this email") - - -class RegistrationForm(forms.ModelForm): - sub_domain = forms.CharField(max_length=100) - - class Meta: - model = User - fields = ["username", "email", "password"] - - def __init__(self, *args, **kwargs): - super(RegistrationForm, self).__init__(*args, **kwargs) - for field in self.fields.values(): - field.widget.attrs = {"class": "form-control"} - - def clean_password(self): - password = self.cleaned_data.get("password") - if password: - if len(password) < 4: - raise forms.ValidationError( - "Password must be at least 8 characters long!" - ) - return password - - def clean_sub_domain(self): - sub_domain = self.cleaned_data.get("sub_domain") - if Company.objects.filter(sub_domain__iexact=sub_domain): - raise forms.ValidationError("Company subdomain already exists.") - return sub_domain - - -class CompanyLoginForm(forms.ModelForm): - # sub_domain = forms.CharField(max_length=100) - - class Meta: - model = User - fields = ["email", "password"] - - def __init__(self, *args, **kwargs): - self.request = kwargs.pop("request", None) - super(CompanyLoginForm, self).__init__(*args, **kwargs) - - # def clean_sub_domain(self): - # subdomain = self.cleaned_data.get("sub_domain") - # if Company.objects.get(sub_domain__iexact=subdomain): - # return subdomain - # raise forms.ValidationError("Company with this sub_domain doesnot exists") - - def clean(self): - email = self.cleaned_data.get("email") - password = self.cleaned_data.get("password") - - if email and password: - self.user = authenticate(username=email, password=password) - if self.user: - if not self.user.is_active: - pass - # raise forms.ValidationError("User is Inactive") - else: - pass - # raise forms.ValidationError("Invalid email and password") - return self.cleaned_data - - -class LoginForm(forms.ModelForm): - email = forms.EmailField() - password = forms.CharField(widget=forms.PasswordInput) - - class Meta: - model = User - fields = ["email", "password"] - - def __init__(self, *args, **kwargs): - self.request = kwargs.pop("request", None) - super(LoginForm, self).__init__(*args, **kwargs) - - def clean_password(self): - password = self.cleaned_data.get("password") - if password: - if len(password) < 4: - raise forms.ValidationError( - "Password must be at least 4 characters long!" - ) - return password - - def clean(self): - email = self.cleaned_data.get("email") - password = self.cleaned_data.get("password") - - if email and password: - self.user = authenticate(username=email, password=password) - if self.user: - if not self.user.is_active: - pass - # raise forms.ValidationError("User is Inactive") - else: - pass - # raise forms.ValidationError("Invalid email and password") - return self.cleaned_data - - -class ChangePasswordForm(forms.Form): - # CurrentPassword = forms.CharField(max_length=100) - Newpassword = forms.CharField(max_length=100) - confirm = forms.CharField(max_length=100) - - def __init__(self, *args, **kwargs): - self.user = kwargs.pop("user", None) - super(ChangePasswordForm, self).__init__(*args, **kwargs) - - def clean_confirm(self): - # if len(self.data.get('confirm')) < 4: - # raise forms.ValidationError( - # 'Password must be at least 4 characters long!') - if self.data.get("confirm") != self.cleaned_data.get("Newpassword"): - raise forms.ValidationError( - "Confirm password do not match with new password" - ) - password_validation.validate_password( - self.cleaned_data.get("Newpassword"), user=self.user - ) - return self.data.get("confirm") - - -class PasswordResetEmailForm(PasswordResetForm): - def clean_email(self): - email = self.cleaned_data.get("email") - if not User.objects.filter(email__iexact=email, is_active=True).exists(): - raise forms.ValidationError("User doesn't exist with this Email") - return email - - -class DocumentForm(forms.ModelForm): - teams_queryset = [] - teams = forms.MultipleChoiceField(choices=teams_queryset) - - def __init__(self, *args, **kwargs): - self.instance = kwargs.get("instance", None) - request_obj = kwargs.pop("request_obj", None) - users = kwargs.pop("users", []) - super(DocumentForm, self).__init__(*args, **kwargs) - - for field in self.fields.values(): - field.widget.attrs = {"class": "form-control"} - - self.fields["status"].choices = [ - (each[0], each[1]) for each in Document.DOCUMENT_STATUS_CHOICE - ] - self.fields["status"].required = False - self.fields["title"].required = True - if users: - self.fields["shared_to"].queryset = users - self.fields["shared_to"].required = False - self.fields["teams"].choices = [ - (team.get("id"), team.get("name")) - for team in Teams.objects.filter(company=request_obj.company).values( - "id", "name" - ) - ] - self.fields["teams"].required = False - - class Meta: - model = Document - fields = ["title", "document_file", "status", "shared_to"] - - def clean_title(self): - title = self.cleaned_data.get("title") - if not self.instance.id: - if Document.objects.filter(title=title).exists(): - raise forms.ValidationError("Document with this Title already exists") - return title - if Document.objects.filter(title=title).exclude(id=self.instance.id).exists(): - raise forms.ValidationError("Document with this Title already exists") - return title - return title - - -class UserCommentForm(forms.ModelForm): - comment = forms.CharField(max_length=64, required=True) - - class Meta: - model = Comment - fields = ("comment", "user", "commented_by") - - -def find_urls(string): - # website_regex = "^((http|https)://)?([A-Za-z0-9.-]+\.[A-Za-z]{2,63})?$" # (http(s)://)google.com or google.com - # website_regex = "^https?://([A-Za-z0-9.-]+\.[A-Za-z]{2,63})?$" # (http(s)://)google.com - # http(s)://google.com - website_regex = "^https?://[A-Za-z0-9.-]+\.[A-Za-z]{2,63}$" - # http(s)://google.com:8000 - website_regex_port = "^https?://[A-Za-z0-9.-]+\.[A-Za-z]{2,63}:[0-9]{2,4}$" - url = re.findall(website_regex, string) - url_port = re.findall(website_regex_port, string) - if url and url[0] != "": - return url - return url_port - - -class APISettingsForm(forms.ModelForm): - def __init__(self, *args, **kwargs): - assigned_users = kwargs.pop("assign_to", []) - super(APISettingsForm, self).__init__(*args, **kwargs) - for field in self.fields.values(): - field.widget.attrs = {"class": "form-control"} - self.fields["lead_assigned_to"].queryset = assigned_users - self.fields["lead_assigned_to"].required = False - - # self.fields['title'].widget.attrs.update({ - # 'placeholder': 'Project Name'}) - # self.fields['lead_assigned_to'].widget.attrs.update({ - # 'placeholder': 'Assign Leads To'}) - - class Meta: - model = APISettings - fields = ("title", "lead_assigned_to", "website") - - def clean_website(self): - website = self.data.get("website") - if website and not ( - website.startswith("http://") or website.startswith("https://") - ): - raise forms.ValidationError("Please provide valid schema") - if not len(find_urls(website)) > 0: - raise forms.ValidationError( - "Please provide a valid URL with schema and without trailing slash - Example: http://google.com" - ) - return website diff --git a/common/middleware/get_company.py b/common/middleware/get_company.py deleted file mode 100644 index 28c546d..0000000 --- a/common/middleware/get_company.py +++ /dev/null @@ -1,33 +0,0 @@ -from common.models import Company - - -class GetCompany(object): - def __init__(self, get_response): - self.get_response = get_response - - def __call__(self, request): - response = self.get_response(request) - return response - - def process_view(self, request, view_func, view_args, view_kwargs): - if request.headers.get("company"): - subdomain = request.headers.get("company") - company = Company.objects.filter(sub_domain=subdomain).first() - if company: - request.company = company - else: - request.company = None - # request.session["company"] = company.id - else: - company_id = request.session.get("company", None) - if company_id: - company = Company.objects.get(id=company_id) - request.company = company - request.session["company"] = company.id - else: - host_name = request.META.get("HTTP_HOST") - subdomain = host_name.split(".")[0] - company = Company.objects.filter(sub_domain=subdomain).first() - if company: - request.company = company - request.session["company"] = company.id diff --git a/marketing/migrations/0014_emailtemplate_company.py b/common/migrations/0023_apisettings_company.py similarity index 59% rename from marketing/migrations/0014_emailtemplate_company.py rename to common/migrations/0023_apisettings_company.py index 1353597..dc6357d 100644 --- a/marketing/migrations/0014_emailtemplate_company.py +++ b/common/migrations/0023_apisettings_company.py @@ -1,4 +1,4 @@ -# Generated by Django 3.1 on 2020-09-11 19:10 +# Generated by Django 3.1 on 2021-01-13 11:24 from django.db import migrations, models import django.db.models.deletion @@ -8,17 +8,16 @@ class Migration(migrations.Migration): dependencies = [ ("common", "0022_auto_20200609_1203"), - ("marketing", "0013_blockeddomain_blockedemail"), ] operations = [ migrations.AddField( - model_name="emailtemplate", + model_name="apisettings", name="company", field=models.ForeignKey( + blank=True, null=True, - on_delete=django.db.models.deletion.CASCADE, - related_name="marketing_emailtemplates_company", + on_delete=django.db.models.deletion.SET_NULL, to="common.company", ), ), diff --git a/common/migrations/0024_remove_user_company.py b/common/migrations/0024_remove_user_company.py new file mode 100644 index 0000000..7bb5ef6 --- /dev/null +++ b/common/migrations/0024_remove_user_company.py @@ -0,0 +1,17 @@ +# Generated by Django 3.1.7 on 2021-03-23 12:17 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("common", "0023_apisettings_company"), + ] + + operations = [ + migrations.RemoveField( + model_name="user", + name="company", + ), + ] diff --git a/common/migrations/0025_auto_20210324_1307.py b/common/migrations/0025_auto_20210324_1307.py new file mode 100644 index 0000000..c4ae0c5 --- /dev/null +++ b/common/migrations/0025_auto_20210324_1307.py @@ -0,0 +1,21 @@ +# Generated by Django 3.1.7 on 2021-03-24 07:37 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("common", "0024_remove_user_company"), + ] + + operations = [ + migrations.RemoveField( + model_name="apisettings", + name="company", + ), + migrations.RemoveField( + model_name="document", + name="company", + ), + ] diff --git a/common/migrations/0026_auto_20210325_1923.py b/common/migrations/0026_auto_20210325_1923.py new file mode 100644 index 0000000..b876414 --- /dev/null +++ b/common/migrations/0026_auto_20210325_1923.py @@ -0,0 +1,18 @@ +# Generated by Django 3.1.7 on 2021-03-25 13:53 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("common", "0025_auto_20210324_1307"), + ] + + operations = [ + migrations.AlterField( + model_name="profile", + name="activation_key", + field=models.CharField(max_length=150), + ), + ] diff --git a/common/models.py b/common/models.py index a6dc86d..f9b919e 100644 --- a/common/models.py +++ b/common/models.py @@ -51,9 +51,6 @@ class User(AbstractBaseUser, PermissionsMixin): ) has_sales_access = models.BooleanField(default=False) has_marketing_access = models.BooleanField(default=False) - company = models.ForeignKey( - Company, on_delete=models.CASCADE, null=True, blank=True - ) USERNAME_FIELD = "email" REQUIRED_FIELDS = [ @@ -65,13 +62,6 @@ class User(AbstractBaseUser, PermissionsMixin): def get_short_name(self): return self.username - @property - def get_app_name(self): - if self.company: - return self.company.sub_domain + "." + settings.APPLICATION_NAME - else: - return settings.APPLICATION_NAME - def documents(self): return self.document_uploaded.all() @@ -353,9 +343,6 @@ class Document(models.Model): ) shared_to = models.ManyToManyField(User, related_name="document_shared_to") teams = models.ManyToManyField("teams.Teams", related_name="document_teams") - company = models.ForeignKey( - Company, on_delete=models.SET_NULL, null=True, blank=True - ) class Meta: ordering = ("-created_on",) @@ -459,7 +446,7 @@ class Profile(models.Model): user = models.OneToOneField( User, related_name="profile", on_delete=models.CASCADE ) # 1 to 1 link with Django User - activation_key = models.CharField(max_length=50) + activation_key = models.CharField(max_length=150) key_expires = models.DateTimeField() def save(self, *args, **kwargs): diff --git a/common/serializer.py b/common/serializer.py index 936c5dc..0e3b20a 100644 --- a/common/serializer.py +++ b/common/serializer.py @@ -1,5 +1,14 @@ +import re from rest_framework import serializers -from common.models import User, Company, Comment, Address, Attachments, Document +from common.models import ( + User, + Company, + Comment, + Address, + Attachments, + Document, + APISettings, +) from django.utils.http import urlsafe_base64_decode from django.contrib.auth.tokens import default_token_generator @@ -28,8 +37,7 @@ class Meta: "profile_pic", "has_sales_access", "has_marketing_access", - "company", - "get_app_name", + # "get_app_name", ) @@ -65,6 +73,41 @@ class Meta: ) +class RegisterUserSerializer(serializers.ModelSerializer): + password = serializers.CharField() + + class Meta: + model = User + fields = ( + "email", + "username", + "password", + ) + + def __init__(self, *args, **kwargs): + self.request_user = kwargs.pop("request_user", None) + super(RegisterUserSerializer, self).__init__(*args, **kwargs) + if not self.instance: + self.fields["password"].required = True + else: + self.fields["password"].required = False + + def validate_password(self, password): + if password: + if len(password) < 4: + raise serializers.ValidationError( + "Password must be at least 4 characters long!" + ) + return password + + def validate_username(self, username): + if not username[0].isalpha(): + raise serializers.ValidationError("Username should start with Alphabet") + if User.objects.filter(username__iexact=username).exists(): + raise serializers.ValidationError("Username already exist") + return username + + class CreateUserSerializer(serializers.ModelSerializer): password = serializers.CharField() @@ -169,7 +212,7 @@ class ResetPasswordSerailizer(CheckTokenSerializer): new_password2 = serializers.CharField() def validate(self, data): - self.user = self.get_user(data.get("uidb64")) + self.user = self.get_user(data.get("uid")) if not self.user: raise serializers.ValidationError(self.error_message) is_valid_token = default_token_generator.check_token( @@ -220,7 +263,6 @@ class DocumentSerializer(serializers.ModelSerializer): shared_to = UserSerializer(read_only=True, many=True) teams = serializers.SerializerMethodField() created_by = UserSerializer() - company = CompanySerializer() def get_teams(self, obj): return obj.teams.all().values() @@ -236,7 +278,6 @@ class Meta: "teams", "created_on", "created_by", - "company", ] @@ -245,12 +286,11 @@ def __init__(self, *args, **kwargs): request_obj = kwargs.pop("request_obj", None) super(DocumentCreateSerializer, self).__init__(*args, **kwargs) self.fields["title"].required = True - self.company = request_obj.company def validate_title(self, title): if self.instance: if ( - Document.objects.filter(title__iexact=title, company=self.company) + Document.objects.filter(title__iexact=title) .exclude(id=self.instance.id) .exists() ): @@ -258,9 +298,7 @@ def validate_title(self, title): "Document with this Title already exists" ) else: - if Document.objects.filter( - title__iexact=title, company=self.company - ).exists(): + if Document.objects.filter(title__iexact=title).exists(): raise serializers.ValidationError( "Document with this Title already exists" ) @@ -272,5 +310,59 @@ class Meta: "title", "document_file", "status", - "company", + ] + + +def find_urls(string): + # website_regex = "^((http|https)://)?([A-Za-z0-9.-]+\.[A-Za-z]{2,63})?$" # (http(s)://)google.com or google.com + # website_regex = "^https?://([A-Za-z0-9.-]+\.[A-Za-z]{2,63})?$" # (http(s)://)google.com + # http(s)://google.com + website_regex = "^https?://[A-Za-z0-9.-]+\.[A-Za-z]{2,63}$" + # http(s)://google.com:8000 + website_regex_port = "^https?://[A-Za-z0-9.-]+\.[A-Za-z]{2,63}:[0-9]{2,4}$" + url = re.findall(website_regex, string) + url_port = re.findall(website_regex_port, string) + if url and url[0] != "": + return url + return url_port + + +class APISettingsSerializer(serializers.ModelSerializer): + def __init__(self, *args, **kwargs): + super(APISettingsSerializer, self).__init__(*args, **kwargs) + + class Meta: + model = APISettings + fields = ("title", "website") + + def validate_website(self, website): + if website and not ( + website.startswith("http://") or website.startswith("https://") + ): + raise serializers.ValidationError("Please provide valid schema") + if not len(find_urls(website)) > 0: + raise serializers.ValidationError( + "Please provide a valid URL with schema and without trailing slash - Example: http://google.com" + ) + return website + + +class APISettingsListSerializer(serializers.ModelSerializer): + created_by = UserSerializer() + lead_assigned_to = UserSerializer(read_only=True, many=True) + tags = serializers.SerializerMethodField() + + def get_tags(self, obj): + return obj.tags.all().values() + + class Meta: + model = APISettings + fields = [ + "title", + "apikey", + "website", + "created_on", + "created_by", + "lead_assigned_to", + "tags", ] diff --git a/common/swagger_params.py b/common/swagger_params.py index f2ebed7..41f4ffc 100644 --- a/common/swagger_params.py +++ b/common/swagger_params.py @@ -1,12 +1,6 @@ from drf_yasg import openapi -company_params_in_header = openapi.Parameter( - "company", openapi.IN_HEADER, required=True, type=openapi.TYPE_STRING -) - - login_page_params = [ - company_params_in_header, openapi.Parameter( "email", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING ), @@ -20,7 +14,6 @@ ] change_password_params = [ - company_params_in_header, openapi.Parameter( "old_password", openapi.IN_QUERY, @@ -44,10 +37,7 @@ ), ] -dashboard_params = [company_params_in_header] - user_update_params = [ - company_params_in_header, openapi.Parameter( "username", openapi.IN_QUERY, type=openapi.TYPE_STRING, required=True ), @@ -64,22 +54,12 @@ ] user_delete_params = [ - company_params_in_header, openapi.Parameter( "user_id", openapi.IN_QUERY, required=True, type=openapi.TYPE_NUMBER ), ] -check_sub_domain_params = [ - openapi.Parameter( - "sub_domain", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING - ), -] - registration_page_params = [ - openapi.Parameter( - "sub_domain", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING - ), openapi.Parameter( "username", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING ), @@ -100,13 +80,8 @@ "email", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING ), ] + reset_password_params = [ - openapi.Parameter( - "uidb64", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING - ), - openapi.Parameter( - "token", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING - ), openapi.Parameter( "new_password1", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING ), @@ -114,8 +89,8 @@ "new_password2", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING ), ] + user_list_params = [ - company_params_in_header, openapi.Parameter("username", openapi.IN_QUERY, type=openapi.TYPE_STRING), openapi.Parameter("email", openapi.IN_QUERY, type=openapi.TYPE_STRING), openapi.Parameter( @@ -130,7 +105,6 @@ ] user_create_params = [ - company_params_in_header, openapi.Parameter("username", openapi.IN_QUERY, type=openapi.TYPE_STRING), openapi.Parameter("email", openapi.IN_QUERY, type=openapi.TYPE_STRING), openapi.Parameter("role", openapi.IN_QUERY, type=openapi.TYPE_STRING), @@ -152,7 +126,6 @@ ] document_create_params = [ - company_params_in_header, openapi.Parameter( "title", openapi.IN_QUERY, type=openapi.TYPE_STRING, required=True ), @@ -164,7 +137,6 @@ ] document_get_params = [ - company_params_in_header, openapi.Parameter("title", openapi.IN_QUERY, type=openapi.TYPE_STRING), openapi.Parameter( "status", @@ -176,7 +148,6 @@ ] document_update_params = [ - company_params_in_header, openapi.Parameter( "title", openapi.IN_QUERY, type=openapi.TYPE_STRING, required=True ), @@ -193,32 +164,7 @@ ), ] -settings_contact_create_params = [ - company_params_in_header, - openapi.Parameter("name", openapi.IN_QUERY, type=openapi.TYPE_STRING), - openapi.Parameter("last_name", openapi.IN_QUERY, type=openapi.TYPE_STRING), - openapi.Parameter("email", openapi.IN_QUERY, type=openapi.TYPE_STRING), -] - -settings_contact_get_params = [ - company_params_in_header, - openapi.Parameter("name", openapi.IN_QUERY, type=openapi.TYPE_STRING), - openapi.Parameter("email", openapi.IN_QUERY, type=openapi.TYPE_STRING), - openapi.Parameter("created_by", openapi.IN_QUERY, type=openapi.TYPE_STRING), -] - -settings_blockdomains_create_params = [ - company_params_in_header, - openapi.Parameter("domain", openapi.IN_QUERY, type=openapi.TYPE_STRING), -] - -settings_blockemails_create_params = [ - company_params_in_header, - openapi.Parameter("email", openapi.IN_QUERY, type=openapi.TYPE_STRING), -] - users_status_params = [ - company_params_in_header, openapi.Parameter( "status", openapi.IN_QUERY, @@ -226,3 +172,18 @@ enum=["Active", "Inactive"], ), ] + +api_setting_create_params = [ + openapi.Parameter( + "title", openapi.IN_QUERY, type=openapi.TYPE_STRING, required=True + ), + openapi.Parameter( + "website", openapi.IN_QUERY, type=openapi.TYPE_STRING, required=True + ), + openapi.Parameter("lead_assigned_to", openapi.IN_QUERY, type=openapi.TYPE_STRING), + openapi.Parameter( + "tags", + openapi.IN_QUERY, + type=openapi.TYPE_STRING, + ), +] diff --git a/common/tasks.py b/common/tasks.py index 69e537c..4184584 100644 --- a/common/tasks.py +++ b/common/tasks.py @@ -13,7 +13,6 @@ from common.models import Comment, Profile, User from common.token_generator import account_activation_token from django.contrib.auth.tokens import default_token_generator -from marketing.models import BlockedDomain, BlockedEmail app = Celery("redis://") @@ -39,10 +38,16 @@ def send_email_to_new_user( ) context["token"] = context["token"] activation_key = context["token"] + time_delta_two_hours - Profile.objects.create(user=user_obj, activation_key=activation_key) - context["complete_url"] = context["url"] + reverse( - "common:activate_user", - args=(context["uid"][0], context["token"], activation_key), + profile_obj = Profile.objects.create( + user=user_obj, activation_key=activation_key + ) + profile_obj.save() + context["complete_url"] = context[ + "url" + ] + "/auth/activate-user/{}/{}/{}/".format( + context["uid"][0], + context["token"], + activation_key, ) recipients = [] recipients.append(user_email) @@ -83,94 +88,47 @@ def send_email_user_mentions( context["commented_by"] = comment.commented_by context["comment_description"] = comment.comment if called_from == "accounts": - context["url"] = ( - protocol - + "://" - + domain - + reverse("accounts:view_account", args=(comment.account.id,)) - ) + context["url"] = protocol + "://" + domain subject = "New comment on Account. " elif called_from == "contacts": - context["url"] = ( - protocol - + "://" - + domain - + reverse("contacts:view_contact", args=(comment.contact.id,)) - ) + context["url"] = protocol + "://" + domain subject = "New comment on Contact. " elif called_from == "leads": - context["url"] = ( - protocol - + "://" - + domain - + reverse("leads:view_lead", args=(comment.lead.id,)) - ) + context["url"] = protocol + "://" + domain subject = "New comment on Lead. " elif called_from == "opportunity": - context["url"] = ( - protocol - + "://" - + domain - + reverse("opportunity:opp_view", args=(comment.opportunity.id,)) - ) + context["url"] = protocol + "://" + domain subject = "New comment on Opportunity. " elif called_from == "cases": - context["url"] = ( - protocol - + "://" - + domain - + reverse("cases:view_case", args=(comment.case.id,)) - ) + context["url"] = protocol + "://" + domain subject = "New comment on Case. " elif called_from == "tasks": - context["url"] = ( - protocol - + "://" - + domain - + reverse("tasks:task_detail", args=(comment.task.id,)) - ) + context["url"] = protocol + "://" + domain subject = "New comment on Task. " elif called_from == "invoices": - context["url"] = ( - protocol - + "://" - + domain - + reverse("invoices:invoice_details", args=(comment.invoice.id,)) - ) + context["url"] = protocol + "://" + domain subject = "New comment on Invoice. " elif called_from == "events": - context["url"] = ( - protocol - + "://" - + domain - + reverse("events:detail_view", args=(comment.event.id,)) - ) + context["url"] = protocol + "://" + domain subject = "New comment on Event. " else: context["url"] = "" # subject = 'Django CRM : comment ' - blocked_domains = BlockedDomain.objects.values_list("domain", flat=True) - blocked_emails = BlockedEmail.objects.values_list("email", flat=True) if recipients: for recipient in recipients: - if (recipient not in blocked_emails) and ( - recipient.split("@")[-1] not in blocked_domains - ): - recipients_list = [ - recipient, - ] - context["mentioned_user"] = recipient - html_content = render_to_string( - "comment_email.html", context=context - ) - msg = EmailMessage( - subject, - html_content, - from_email=comment.commented_by.email, - to=recipients_list, - ) - msg.content_subtype = "html" - msg.send() + recipients_list = [ + recipient, + ] + context["mentioned_user"] = recipient + html_content = render_to_string("comment_email.html", context=context) + msg = EmailMessage( + subject, + html_content, + from_email=comment.commented_by.email, + to=recipients_list, + ) + msg.content_subtype = "html" + msg.send() @app.task @@ -254,9 +212,12 @@ def resend_activation_link_to_user( activation_key=activation_key, key_expires=timezone.now() + datetime.timedelta(hours=2), ) - context["complete_url"] = context["url"] + reverse( - "common:activate_user", - args=(context["uid"][0], context["token"], activation_key), + context["complete_url"] = context[ + "url" + ] + "/auth/activate_user/{}/{}/{}/".format( + context["uid"][0], + context["token"], + activation_key, ) recipients = [] recipients.append(user_email) @@ -282,14 +243,16 @@ def send_email_to_reset_password( context["token"] = context["token"] context["complete_url"] = context[ "url" - ] + "/api-common/reset-password/{uidb64}/{token}/".format( - uidb64=context["uid"], token=context["token"] + ] + "/auth/reset-password/{uidb64}/{token}/".format( + uidb64=context["uid"][0], token=context["token"] ) recipients = [] recipients.append(user_email) subject = "Password Reset" html_content = render_to_string("password_reset_email.html", context=context) if recipients: - msg = EmailMessage(subject, html_content, to=recipients) + msg = EmailMessage( + subject, html_content, from_email=settings.DEFAULT_FROM_EMAIL, to=recipients + ) msg.content_subtype = "html" msg.send() diff --git a/common/templates/create.html b/common/templates/create.html deleted file mode 100644 index 6ec7732..0000000 --- a/common/templates/create.html +++ /dev/null @@ -1,222 +0,0 @@ -{% extends 'sales/base.html' %} -{% load static %} -{% block breadcrumb %} - -{% endblock breadcrumb %} -{% block content %} -
      -
      -
      -
      -
      -
      - {% if user_obj %}EDIT{% else %}CREATE{% endif %} USER -
      -
      -
      -
      - - -
      - {{ errors.first_name }} -
      -
      -
      - - -
      - {{ errors.last_name }} -
      -
      -
      - - -
      - {{ errors.username }} -
      - -
      -
      - - {% if request.user.role == 'ADMIN' or request.user.is_superuser %} - - {% else %} - - {% endif %} - {{ user_form.role.errors }} -
      -
      - {% if not user_obj %} -
      -
      - - -
      - {{ errors.password }} -
      - {% endif %} -
      -
      - - -
      - - {% if user_obj %}{{user_profile_name }}{% endif %} - {{ errors.profile_pic }} - -
      - {% if request.user.is_superuser or request.user.role == 'ADMIN' %} -
      -
      - -
      - -
      - - -
      - - - -
      - -
      -
      -
      - - - - -
      - {{ errors.teams }} -
      - {% endif %} -
      -
      -

      - {% comment %} - {% if request.user.role == 'ADMIN' or request.user.is_superuser %} - {% if request.user.id|slugify in request.path %} -

      true

      - {% endif %} - {% endif %} - {% endcomment %} -
      - - Cancel -
      -
      -
      -
      -
      -{% endblock content %} -{% block js_block %} - -{% endblock js_block %} \ No newline at end of file diff --git a/common/templates/doc_create.html b/common/templates/doc_create.html deleted file mode 100644 index 3bf2327..0000000 --- a/common/templates/doc_create.html +++ /dev/null @@ -1,365 +0,0 @@ -{% extends 'sales/base.html' %} -{% load static %} - -{% block breadcrumb %} - -{% endblock breadcrumb %} -{% block content %} -
      -
      -
      -
      -
      -
      - {% if doc_obj %}EDIT{% else %}CREATE{% endif %} DOCUMENT -
      -
      -
      -
      -
      - - -
      - {{ errors.title }} -
      -
      -
      - - -
      - {% if doc_obj %}{{doc_file_name}}{% endif %} - {{ errors.document_file }} -
      - {% if request.user.is_superuser or request.user.role == 'ADMIN' %} -
      -
      - - - {{ doc_form.teams.errors }} -
      -
      - -
      -
      - - -
      -
      - - {% endif %} -
      -
      - - - {{ errors.shared_to.errors }} -
      -
      -

      - {% if doc_obj %} -
      -
      - - {{ doc_form.status }} - {{ doc_form.status.errors }} -
      -
      - {% endif %} -
      -
      -
      - - Cancel - -
      - -
      -
      -
      -
      -
      - -
      - -
      - 0% -
      -
      -
      - -{% endblock content %} -{% block js_block %} - -{% endblock js_block %} \ No newline at end of file diff --git a/common/templates/doc_detail.html b/common/templates/doc_detail.html deleted file mode 100644 index fca9940..0000000 --- a/common/templates/doc_detail.html +++ /dev/null @@ -1,99 +0,0 @@ -{% extends 'sales/base.html' %} -{% load static %} -{% load thumbnail %} -{% block content%} - - -
      -
      -
      -
      -
      -
      -
      - Document -
      - Edit -
      -
      -
      - {% if doc_obj.title %} -
      -
      - -
      {{ doc_obj.title }}
      -
      -
      - {% endif %} - {% if doc_obj.status %} -
      -
      - -
      {{ doc_obj.status }}
      -
      -
      - {% endif %} -
      -
      - -
      {{ doc_obj.created_by }}
      -
      -
      -
      -
      - -
      {{ doc_obj.created_on_arrow }}
      -
      -
      - {% with document_users=document.shared_to.all %} - {% if document_users %} -
      -
      - -
      - {% for user in document_users %} - {% if user.profile_pic %} - {% thumbnail user.profile_pic "40x40" crop="center" as im %} - - - - - - {% endthumbnail %} - {% else %} - - - - - - {% endif %} - {% empty %} - None - {% endfor %} -
      -
      - {% endif %} - {% endwith %} -
      -
      -
      - {% if doc_obj.document_file %} - - - Download - {% endif %} -
      -
      -
      -
      -
      -
      -
      -
      - -{% endblock %} \ No newline at end of file diff --git a/common/templates/doc_list.html b/common/templates/doc_list.html deleted file mode 100644 index 97aed8c..0000000 --- a/common/templates/doc_list.html +++ /dev/null @@ -1,336 +0,0 @@ -{% extends 'sales/base.html' %} -{% load static %} -{% load paginate %} -{% load thumbnail %} -{% block extralinks %} - -{% endblock %} -{% block content %} - -
      - - -
      -
      -
      -
      -
      -
      -
      Filters
      -
      -
      -
      - - -
      -
      -
      -
      - - -
      -
      -
      -
      - - -
      -
      -
      -
      - - Clear -
      -
      -
      -
      -
      -
      -
      -
      -
      - -
      -
      -
      -
      -
      - Documents - {% if show_pageitems %} {% show_pageitems %}{% else %} - {{documents|length}}{% endif %} - - - -
      -
      - - - {% if documents|length > 0 %} - - - - - - - - - - {% endif %} - - - {% if per_page %} - {% paginate per_page documents %} - {% else%} - {% paginate 10 documents %} - {% endif %} - {% for document in documents %} - - - - - - - - - - {% endfor %} - -
      S.NoTitleCreated ByCreated OnStatusShared ToActions
      {{ forloop.counter }}{% if document.title %}{{ document.title }}{% endif %} - {% if document.created_by %} - {% if document.created_by.profile_pic %} - {% thumbnail document.created_by.profile_pic "40x40" crop="center" as im %} - - {% endthumbnail %} - {% else %} - - {% endif %} - {% else %} - None - {% endif %} - {{document.created_on_arrow}}{{document.status}} - {% with document_users=document.shared_to.all %} - {% for user in document_users %} - {% if user.profile_pic %} - {% thumbnail user.profile_pic "40x40" crop="center" as im %} - - - - {% endthumbnail %} - {% else %} - - - - {% endif %} - {% empty %} - None - {% endfor %} - {% endwith %} - - {% if request.user == document.created_by or request.user.role == 'ADMIN' or request.user.has_sales_access %} - - - - {% endif %} - {% if request.user in document.shared_to.all or request.user == document.created_by or request.user.role == 'ADMIN' %} - - {% endif %} -
      -
      - {% ifequal documents|length 0 %} -
      No Documents Found
      - {% endifequal %} -
      - {% show_pages %} -
      -
      -
      -
      -
      -
      - - -
      - - - -{% for doc_obj in documents %} - - - - -{% endfor %} - - - - -{% endblock %} -{% block js_block %} - -{% endblock js_block %} \ No newline at end of file diff --git a/common/templates/doc_list_1.html b/common/templates/doc_list_1.html deleted file mode 100644 index e7abf1f..0000000 --- a/common/templates/doc_list_1.html +++ /dev/null @@ -1,386 +0,0 @@ -{% extends 'sales/base.html' %} -{% load static %} -{% load paginate %} -{% load thumbnail %} -{% block extralinks %} - -{% endblock %} -{% block content %} - -
      - - -
      -
      -
      -
      -
      -
      -
      Filters
      -
      -
      -
      - - -
      -
      -
      -
      - - -
      -
      -
      -
      - - -
      -
      -
      -
      - - Clear -
      -
      -
      -
      -
      -
      -
      -
      -
      - -
      -
      -
      -
      -
      - Documents - {% if show_pageitems %} {% show_pageitems %}{% else %} - {{documents|length}}{% endif %} - - - -
      - -
      - {% if per_page %} - {% paginate per_page documents %} - {% else%} - {% paginate 12 documents %} - {% endif %} - {% for document in documents %} -
      -
      - -
      -
      -
      - - {% if document.title %} - -
      - {{ document.title }} -
      -
      -
      {% endif %} -
      -
      - -
      - -
      - -
      -
      - -
      - {% if document.created_by %} - {% if document.created_by.profile_pic %} - {% thumbnail document.created_by.profile_pic "60x60" crop="center" as im %} - - {% endthumbnail %} - {% else %} - - {% endif %} - {% else %} - - {% endif %} -
      -
      -
      -
      Created On: {{document.created_on_arrow}}
      -
      Status: {{document.status}}
      -
      Shared To: - {% with document_users=document.get_team_and_assigned_users %} - {% for user in document_users %} - {% if user.profile_pic %} - {% thumbnail user.profile_pic "20x20" crop="center" as im %} - - - - {% endthumbnail %} - {% else %} - - - - {% endif %} - {% empty %} - None - {% endfor %} - {% endwith %} -
      -
      -
      -
      -
      - -
      - {% if request.user == document.created_by or request.user.role == 'ADMIN' or request.user.has_sales_access%} - - - - {% endif %} - {% if request.user in document.shared_to.all or request.user == document.created_by or request.user.role == 'ADMIN' %} - - {% endif %} -
      -
      -
      -
      -
      -
      - {% endfor %} - -
      - - -
      -
      -
      -
      - {% ifequal documents|length 0 %} -
      No Documents Found
      - {% endifequal %} -
      - {% show_pages %} -
      - - -
      - - - - -{% for doc_obj in documents %} - - - - -{% endfor %} - - - - -{% endblock %} -{% block js_block %} - -{% endblock js_block %} diff --git a/common/templates/landing_page.html b/common/templates/landing_page.html deleted file mode 100644 index c0aed4b..0000000 --- a/common/templates/landing_page.html +++ /dev/null @@ -1,11 +0,0 @@ -{% extends 'base.html' %} -{% block content %} - -
      - -

      bottlecrm

      -

      Coming soon ...

      - -
      - -{% endblock %} \ No newline at end of file diff --git a/common/templates/list.html b/common/templates/list.html deleted file mode 100644 index 965eb00..0000000 --- a/common/templates/list.html +++ /dev/null @@ -1,368 +0,0 @@ -{% extends 'sales/base.html' %} -{% load static %} -{% load paginate %} -{% block content %} - -
      - - - - - - - -
      -
      -
      -
      -
      -
      -
      Filters
      -
      -
      -
      - - -
      -
      -
      -
      - - -
      -
      - -
      -
      - - -
      -
      -
      -
      - - -
      -
      -
      -
      - - Clear -
      -
      -
      -
      -
      -
      -
      -
      -
      - - -
      -
      -
      -
      - -
      -
      -
      -
      -
      - Active Users - {% if show_pageitems %} - {% show_pageitems %}{% else %}{{active_users|length}}{% endif %} - - - -
      -
      - - - {% if active_users|length > 0 %} - - - - - - - - - - {% endif %} - - - {% if per_page %} - {% paginate per_page active_users %} - {% else %} - {% paginate 10 active_users %} - {% endif %} - {% for user in active_users %} - - - - - - - - - {% endfor %} - -
      UsernameCreatedEmail AddressUser RolePermissionsStatusActions
      {{ user.username }}{{user.created_on_arrow}} - {{ user.email }}{% if user.is_superuser %} ADMIN {% else %} {{user.role}} {% endif %} - - {% if user.is_superuser or user.role == 'ADMIN' %} - Sales, Marketing - {% else %} - {% if user.has_sales_access and user.has_marketing_access %} - Sales, Marketing - {% elif user.has_sales_access and not user.has_marketing_access %} - Sales - {% elif not user.has_sales_access and user.has_marketing_access %} - Marketing - {% else %} - {{''}} - {% endif %} - {% endif %} - - {% ifnotequal request.user user %} - - {% if user.is_active == True %} - Active - {% else %} - InActive - {% endif %} - - {% else %} - Active - {% endifnotequal %} - - - {% if user.email != admin_email or request.user.email == admin_email %} - Edit - {% endif %} - - {% if user.email != admin_email and request.user != user %} - - {% endif %} -
      -
      - {% ifequal active_users|length 0 %} -
      No Active Users Found
      - {% endifequal %} -
      - {% show_pages %} -
      -
      -
      -
      -
      -
      -
      -
      - Inactive Users - {% if show_pageitems %} - {% show_pageitems %}{% else %}{{inactive_users|length}}{% endif %} - - - -
      -
      - - - {% if inactive_users|length > 0 %} - - - - - - - - {% endif %} - - - {% if per_page %} - {% paginate per_page inactive_users %} - {% else %} - {% paginate 10 inactive_users %} - {% endif %} - {% for user in inactive_users %} - - - - - - - - {% endfor %} - -
      UsernameEmail AddressUser RoleStatusActions
      {{ user.username }}{{ user.email }}{% if user.is_superuser %} ADMIN {% else %} {{user.role}} {% endif %} - - {% ifnotequal request.user user %} - - {% if user.is_active == True %} - Active - {% else %} - InActive - {% endif %} - - {% else %} - Active - {% endifnotequal %} - - - {% if user.email != admin_email or request.user.email == admin_email %} - Edit - {% endif %} - - {% if user.email != admin_email and request.user != user %} - - {% endif %} -
      -
      - {% ifequal inactive_users|length 0 %} -
      There are no users
      - {% endifequal %} -
      - {% show_pages %} -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      - -{% endblock %} -{% block js_block %} - - -{% endblock js_block %} diff --git a/common/templates/password_reset_email.html b/common/templates/password_reset_email.html index 70a9344..16baac7 100644 --- a/common/templates/password_reset_email.html +++ b/common/templates/password_reset_email.html @@ -7,7 +7,7 @@ {% ifequal 'activated' message %} {% block content_body %} -You account has been activated by {{status_changed_user}}. You can login to your account and access all the features of +Your account has been activated by {{status_changed_user}}. You can login to your account and access all the features of Django CRM. {% endblock content_body %} {% block button_link %} diff --git a/common/templates/settings/create.html b/common/templates/settings/create.html deleted file mode 100644 index d8c5c31..0000000 --- a/common/templates/settings/create.html +++ /dev/null @@ -1,145 +0,0 @@ -{% extends 'sales/base.html' %} -{% load static %} -{% block extralinks %} -{% endblock %} -{% block breadcrumb %} - -{% endblock %} -{%block content%} -
      -
      -
      -
      -
      -
      - CREATE SETTINGS -
      -
      -
      -
      -
      - - - {{ settings_form.title.errors }} -
      -
      -
      -
      -
      -
      - - - {{ settings_form.website.errors }} -
      -
      -
      -
      -
      -
      - - - {{ settings_form.lead_assigned_to.errors }} -
      -
      -
      -
      -
      -
      - -
      -
      -
      -
      -
      -
      - -
      - - {% if not setting %} - - {% endif %} - Cancel -
      -
      -
      -
      -
      -
      - -
      -
      -{% endblock %} -{% block js_block %} - - -{% endblock js_block %} - diff --git a/common/templates/settings/list.html b/common/templates/settings/list.html deleted file mode 100644 index 394d958..0000000 --- a/common/templates/settings/list.html +++ /dev/null @@ -1,522 +0,0 @@ -{% extends 'sales/base.html' %} -{% load static %} -{% load paginate %} -{% load thumbnail %} -{% block content %} - - -
      - - - - - - - - -
      -
      -
      -
      -
      -
      -
      Filter Contacts
      -
      -
      -
      - - -
      -
      -
      -
      - - -
      -
      -
      -
      - - -
      -
      - - -
      -
      - - Clear -
      -
      -
      -
      -
      -
      -
      -
      -
      - - - - -
      -
      -
      -
      -
      -
      -
      Filter Domain
      -
      -
      -
      - - -
      -
      - - -
      -
      - - Clear -
      -
      -
      -
      -
      -
      -
      -
      -
      - - - -
      -
      -
      -
      -
      -
      -
      Filter Contacts
      -
      -
      -
      - - -
      -
      - - -
      -
      - - Clear -
      -
      -
      -
      -
      -
      -
      -
      -
      - - - - - -
      -
      -
      -
      - -
      -
      -
      -
      -
      - Contacts - {% if show_pageitems %} - {% show_pageitems %}{% else %} - {{ contacts|length }}{% endif %} - - - -
      -
      - - - {% if contacts|length > 0 %} - - - - - - - - - {% endif %} - - - {% if per_page %} - {% paginate per_page contacts %} - {% else %} - {% paginate 10 contacts %} - {% endif %} - {% for contact in contacts %} - - - - - - - - - {% endfor %} - -
      ID NameEmailCreated byCreated OnActions
      {{ forloop.counter }}{{ contact.name }} - {{contact.email}} - - {% if contact.created_by %} - {% if contact.created_by.profile_pic %} - {% thumbnail contact.created_by.profile_pic "40x40" crop="center" as im %} - - {% endthumbnail %} - {% else %} - - {% endif %} - {% else %} - - {% endif %} - {{ contact.created_on_arrow }} - {% if request.user.role == 'ADMIN' or request.user.is_superuser %} - - - {% endif %} -
      -
      - {%ifequal contacts|length 0%} -
      No Contacts Found
      - {%endifequal%} -
      - {% show_pages %} -
      -
      -
      -
      - - - -
      -
      -
      -
      - Blocked Domain - {% if show_pageitems %} - {% show_pageitems %}{% else %} - {{ blocked_domains|length }}{% endif %} - - - -
      -
      - - - {% if blocked_domains|length > 0 %} - - - - - - - - {% endif %} - - - {% if per_page %} - {% paginate per_page blocked_domains %} - {% else %} - {% paginate 10 blocked_domains %} - {% endif %} - {% for domain in blocked_domains %} - - - - - - - - {% endfor %} - -
      IDDomainCreated byCreated OnActions
      {{ forloop.counter }}{{ domain.domain }} - {% if domain.created_by %} - {% if domain.created_by.profile_pic %} - {% thumbnail domain.created_by.profile_pic "40x40" crop="center" as im %} - - {% endthumbnail %} - {% else %} - - {% endif %} - {% else %} - - {% endif %} - {{ domain.created_on_arrow }} - {% if request.user.role == 'ADMIN' or request.user.is_superuser %} - - - {% endif %} -
      -
      - {%ifequal blocked_domains|length 0%} -
      No Domains Found
      - {%endifequal%} -
      - {% show_pages %} -
      -
      -
      -
      - - - - -
      -
      -
      -
      - Blocked Emails - {% if show_pageitems %} - {% show_pageitems %}{% else %} - {{ blocked_emails|length }}{% endif %} - - - -
      -
      - - - {% if blocked_emails|length > 0 %} - - - - - - - - {% endif %} - - - {% if per_page %} - {% paginate per_page blocked_emails %} - {% else %} - {% paginate 10 blocked_emails %} - {% endif %} - {% for email in blocked_emails %} - - - - - - - - {% endfor %} - -
      IDEmailCreated byCreated OnActions
      {{ forloop.counter }}{{ email.email }} - {% if email.created_by %} - {% if email.created_by.profile_pic %} - {% thumbnail email.created_by.profile_pic "40x40" crop="center" as im %} - - {% endthumbnail %} - {% else %} - - {% endif %} - {% else %} - - {% endif %} - {{ email.created_on_arrow }} - {% if request.user.role == 'ADMIN' or request.user.is_superuser %} - - - {% endif %} -
      -
      - {%ifequal blocked_emails|length 0%} -
      No Email Found
      - {%endifequal%} -
      - {% show_pages %} -
      -
      -
      -
      - -
      -
      -
      -
      -
      -
      - -
      - -{% endblock %} -{% block js_block %} - -{% endblock js_block %} diff --git a/common/templates/settings/update.html b/common/templates/settings/update.html deleted file mode 100644 index 94e5725..0000000 --- a/common/templates/settings/update.html +++ /dev/null @@ -1,153 +0,0 @@ -{% extends 'sales/base.html' %} -{% load static %} -{% block breadcrumb %} - -{% endblock %} -{%block content%} -
      -
      -
      -
      -
      -
      - EDIT SETTINGS -
      -
      -
      -
      -
      - - - {{ settings_form.title.errors }} -
      -
      -
      -
      -
      -
      - - - {{ settings_form.website.errors }} -
      -
      -
      -
      -
      -
      - - - {{ settings_form.lead_assigned_to.errors }} -
      -
      -
      -
      -
      -
      - -
      -
      -
      -
      -
      -
      -
      - - {% if not setting %} - - {% endif %} - Cancel -
      -
      -
      -
      -
      -
      - -
      -
      -{% endblock %} -{% block js_block %} - -{% endblock js_block %} diff --git a/common/templates/settings/view.html b/common/templates/settings/view.html deleted file mode 100644 index 7e63dd4..0000000 --- a/common/templates/settings/view.html +++ /dev/null @@ -1,125 +0,0 @@ -{% extends 'sales/base.html' %} -{% load static %} -{% block breadcrumb %} - -{% endblock %} -{% block content %} -
      -
      -
      -
      -
      -
      -
      - Overview - - - -
      -
      -
      -
      - {% if setting.title %} -
      -
      - - -
      -
      - {% endif %} - {% if setting.website %} -
      -
      - - -
      -
      - {% endif %} - {% if setting.apikey %} -
      -
      - - -
      -
      - {% endif %} - {% if setting.lead_assigned_to.all|length > 0 %} -
      -
      - - -
      -
      - {% endif %} - {% if setting.tags.all|length > 0 %} -
      -
      - - -
      -
      - {% endif %} - {% if setting.created_by %} -
      -
      - - -
      -
      - {% endif %} - {% if setting.created_on %} -
      -
      - - -
      -
      - {% endif %} -
      -
      -
      -
      -
      -
      -
      -{% endblock content %} -{% block js_block %} - -{% endblock js_block %} diff --git a/common/templates/user_detail.html b/common/templates/user_detail.html deleted file mode 100644 index 1694414..0000000 --- a/common/templates/user_detail.html +++ /dev/null @@ -1,468 +0,0 @@ -{% extends 'sales/base.html' %} -{% load static %} -{% block breadcrumb %} -{% load thumbnail %} - - -{% endblock breadcrumb %} -{% block content %} - -
      -
      -
      -
      -
      -
      -
      - Overview - - - -
      -
      -
      -
      - {% if user_obj.first_name %} -
      -
      - - -
      -
      - {% endif %} - {% if user_obj.last_name %} -
      -
      - - -
      -
      - {% endif %} - {% if user_obj.email %} -
      -
      - - -
      -
      - {% endif %} - {% if user_obj.username %} -
      -
      - - -
      -
      - {% endif %} - {% if user_obj.role %} -
      -
      - - -
      -
      - {% endif %} -
      -
      -
      -
      - -
      - {% if user_obj.profile_pic %} - {% thumbnail user_obj.profile_pic "125x125" as im %} - - {% endthumbnail %} - {% else %} - - {% endif %} -
      -
      -
      - {% with teams=user_obj.user_teams.all %} - {% if teams %} -
      -
      - - {% for team in teams %} - - {% endfor %} -
      -
      - {% endif %} - {% endwith %} -
      -
      -
      -
      - -
      -
      -
      -
      -
      -
      -
      Comments
      -
      -
      -
      -
      -
      - -
      -
      -
      - -
      -
      - -
      -
        - {% for comment in comments %} -
      • - {% if request.user.is_superuser or request.user.role == 'ADMIN' or request.user == comment.commented_by %} -
        - - -
        - {% endif %} -
        -
        {{ comment.comment }}
        -
        -
        -
        {{ comment.commented_by }}
        -
        {{ comment.commented_on|date:'m/d/Y,  h:i:s A' }}
        -
        -
      • - {% endfor %} -
      -
      -
      - -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      - Accounts -
      -
      - - {% if accounts|length > 0 %} - - - - - - - - - {% endif %} - - {% for account in accounts %} - - - - - - - {% endfor %} - -
      S.NoAccount NamePhoneEmail
      {{ forloop.counter }}{{ account.name }}{{ account.phone }}{{ account.email }}
      -
      - {% ifequal accounts|length 0 %} -
      No Account Records Found
      - {% endifequal %} -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      - Contacts -
      -
      - - {% if contacts|length > 0 %} - - - - - - - - - {% endif %} - - {% for contact in contacts %} - - - - - - - {% endfor %} - -
      S.NoContact NamePhoneEmail
      {{ forloop.counter }}{{ contact.first_name }} - {{ contact.last_name }}{{ contact.phone }}{{ contact.email }}
      -
      - {% ifequal contacts|length 0 %} -
      No Contact Records Found
      - {% endifequal %} -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      - Opportunities -
      -
      - - {% if opportunity_list|length > 0 %} - - - - - - - - - {% endif %} - - {% for opportunity in opportunity_list %} - - - - - - - {% endfor %} - -
      S.NoNameStageProbability
      {{ forloop.counter }}{{opportunity.name}}{{opportunity.stage}}{{opportunity.probability}} {% if opportunity.probability %} % {% endif %}
      -
      - `{% ifequal opportunity_list|length 0 %} -
      No Opportunity Records Found
      - {% endifequal %} -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      - Cases -
      -
      - - {% if cases|length > 0 %} - - - - - - - - - {% endif %} - - {% for case in cases %} - - - - - - - {% endfor %} - -
      S.NoNameStatusPriority
      {{ forloop.counter }}{{ case.name }}{{ case.status }}{{ case.priority }}
      -
      - {% ifequal cases|length 0 %} -
      No Case Records Found
      - {% endifequal %} -
      -
      -
      -
      -
      -
      -
      -
      -
      - -{% endblock content %} -{% block js_block %} - - -{% endblock js_block %} \ No newline at end of file diff --git a/common/tests.py b/common/tests.py deleted file mode 100644 index de0dff9..0000000 --- a/common/tests.py +++ /dev/null @@ -1,1787 +0,0 @@ -from django.test import TestCase -from django.test import Client -from django.urls import reverse -from common.models import User, Document, Attachments, Company -from common.forms import * -from django.core.files.uploadedfile import SimpleUploadedFile -from leads.models import Lead -from teams.models import Teams -from django.utils.encoding import force_text -import json -import datetime - - -class ObjectsCreation(object): - def setUp(self): - self.client = Client() - # self.user = User.objects.create(first_name="admin", - # username='admin', - # email='admin@micropyramid.com', - # is_staff=True, - # is_admin=True, - # is_superuser=True, is_active=True) - - self.company, _ = Company.objects.get_or_create( - name="test company", address="IN", sub_domain="test", country="IN" - ) - - self.user_admin = User.objects.create( - first_name="john", - username="johndoeAdmin", - email="johndoe@admin.com", - is_staff=True, - is_admin=True, - is_superuser=True, - is_active=True, - role="ADMIN", - company=self.company, - ) - - self.user_admin.set_password("password") - self.user_admin.save() - self.user = User.objects.create( - first_name="jane", - username="janedoe", - email="janedoe@admin.com", - is_staff=True, - is_admin=True, - is_superuser=True, - is_active=False, - company=self.company, - ) - self.user.set_password("password") - self.user.save() - self.user1 = User.objects.create( - first_name="johnDoeCommon", - username="johnDoeCommon", - email="johnDoeCommon@user.com", - role="USER", - has_sales_access=True, - company=self.company, - ) - self.user1.set_password("password") - self.user1.save() - # self.user - self.client.login(username="johndoe@admin.com", password="password") - self.document = Document.objects.create( - title="abc", document_file="1.png", created_by=self.user - ) - - self.document_edit = Document.objects.create( - title="edit title", document_file="1.png", created_by=self.user - ) - - self.comment = Comment.objects.create( - comment="comment", user=self.user, commented_by=self.user - ) - - self.user2 = User.objects.create( - first_name="janeDoeCommon", - username="janeDoeCommon", - email="janeDoeCommon@user.com", - role="USER", - has_sales_access=True, - company=self.company, - ) - self.user2.set_password("password") - self.user2.save() - - -class TestHomePage(ObjectsCreation, TestCase): - def test_home_page(self): - response = self.client.get(reverse("common:dashboard")) - self.assertEqual(response.status_code, 200) - if response.status_code == 200: - self.assertIn("Micro", str(response.content)) - - def test_home_page1(self): - self.client.login(username="mp@micropyramid.com", password="mp") - response = self.client.get(reverse("common:dashboard")) - self.assertEqual(response.status_code, 200) - if response.status_code == 200: - self.assertIn("Micro", str(response.content)) - - # def test_404_page(self): - # # print("34792837471239407123742374") - # response = self.client.get('/sldkf') - # # print(response) - # self.assertEqual(response.status_code, 404) - - -class CommonModelTest(ObjectsCreation, TestCase): - def test_string_representation_user(self): - user = self.user - self.assertEqual(str(user.get_short_name()), user.username) - - -class UserCreateTestCase(ObjectsCreation, TestCase): - - # def test_user_create_url(self): - # url = '/users/create/' - # data = {'email': 'abc@micropyramid.com', 'username': 'user', 'role': 'USER'} - # response = self.client.post(url,data) - # self.assertEqual(response.status_code,200) - - def test_user_create_invalid(self): - response = self.client.post( - "/users/create/", - { - "email": "john@doe.com", - "first_name": "", - "last_name": "", - "username": "", - "role": "ADMIN", - }, - ) - self.assertEqual(response.status_code, 200) - - -class PasswordChangeTestCase(ObjectsCreation, TestCase): - def test_password_change(self): - self.client.login(username="johndoe@admin.com", password="password") - url = "/change-password/" - data = { - "CurrentPassword": "password", - "Newpassword": "strongpassword", - "confirm": "strongpassword", - } - response = self.client.post(url, data) - self.assertEqual(response.status_code, 302) - - def test_password_invalid(self): - self.client.login(username="johndoe@admin.com", password="password") - url = "/change-password/" - data = {"CurrentPassword": " ", "Newpassword": "test123", "confirm": " "} - response = self.client.post(url, data) - self.assertEqual(response.status_code, 200) - - def change_passsword_by_admin(self): - response = self.client.post( - "/change-password-by-admin//", - {"useer_id": self.user.id, "new_passwoord": "password"}, - ) - self.assertEqual(response.status_code, 302) - - -class ForgotPasswordViewTestCase(ObjectsCreation, TestCase): - def test_forgot_password(self): - url = "/forgot-password/" - response = self.client.get(url) - self.assertTemplateUsed(response, "forgot_password.html") - - -class LoginViewTestCase(ObjectsCreation, TestCase): - # user2 = User.objects.create(first_name="paul", username='paul', email='paul@micropyramid.com', - # is_staff=True, is_admin=True, is_superuser=True, is_active=False) - - def test_login_post(self): - self.client.logout() - data = {"email": "johndoe@admin.com", "password": "password"} - response = self.client.post( - reverse("common:login"), data, HTTP_HOST="test.bottlecrm.com" - ) - self.assertEqual(response.status_code, 302) - - def test_login_get_request(self): - data = {"email": "johndoe@admin.com", "password": "password"} - response = self.client.post( - reverse("common:login"), data, HTTP_HOST="test.bottlecrm.com" - ) - self.assertEqual(response.status_code, 302) - - def test_login_post_invalid(self): - self.client.logout() - data = {"email": "johndoe@admin.com", "password": "test123"} - response = self.client.post( - reverse("common:login"), data, HTTP_HOST="test.bottlecrm.com" - ) - self.assertEqual(response.status_code, 200) - - def test_login_inactive(self): - self.client.logout() - data = { - "email": "johndoe@admin.com", - "password": "password", - "is_active": False, - } - response = self.client.post( - reverse("common:login"), data, HTTP_HOST="test.bottlecrm.com" - ) - self.assertEqual(response.status_code, 302) - - def test_login_invalid(self): - self.client.logout() - data = {"email": "abc@abc.com", "password": "123"} - response = self.client.post("/login/", data) - self.assertEqual(response.status_code, 200) - - def test_logout(self): - self.client = Client() - self.client.login(username="johndoe@admin.com", password="password") - response = self.client.get("/logout/") - self.assertEqual(response.status_code, 302) - - -class UserTestCase(ObjectsCreation, TestCase): - def test_user_create_url(self): - response = self.client.get( - "/users/create/", - { - "first_name": "john", - "last_name": "doe", - "username": "john doe c", - "email": "johnC@doe.com", - "password": "password", - "role": "USER", - }, - ) - self.assertEqual(response.status_code, 200) - - def test_user_create_html(self): - response = self.client.get( - "/users/create/", - { - "first_name": "jane", - "last_name": "", - "username": "jane doe", - "email": "", - "password": "password", - }, - ) - - self.assertTemplateUsed(response, "create.html") - - -class UserListTestCase(ObjectsCreation, TestCase): - def test_users_list(self): - self.users = User.objects.all() - response = self.client.get("/users/list/") - # get_img_url = self.users.filter() - get_user = User.objects.get(email="johndoe@admin.com") - self.assertEqual(get_user.email, get_user.__str__()) - self.assertEqual(response.status_code, 200) - self.assertTemplateUsed(response, "list.html") - - def test_users_list_queryset(self): - self.user = User.objects.all() - data = { - "first_name": "john", - "username": "johndoeAdmin", - "email": "johndoe@admin.com", - "role": "ADMIN", - "status": "True", - } - response = self.client.post("/users/list/", data) - self.assertEqual(response.status_code, 200) - self.assertTemplateUsed(response, "list.html") - - -class UserRemoveTestCase(ObjectsCreation, TestCase): - def test_users_remove(self): - response = self.client.get("/users/" + str(self.user.id) + "/delete/") - self.assertEqual(response["location"], "/users/list/") - - # def test_user_remove_status(self): - # User.objects.filter(id=self.user.id).delete() - # response = self.client.get('/users/list/') - # self.assertEqual(response.status_code, 302) - - -class UserUpdateTestCase(ObjectsCreation, TestCase): - def test_users_update(self): - response = self.client.get( - "/users/" + str(self.user.id) + "/edit/", - { - "first_name": "john", - "user_name": "johndoeAdmin", - "email": "johndoe@admin.com", - }, - ) - self.assertEqual(response.status_code, 200) - self.assertTemplateUsed(response, "create.html") - - def test_accounts_update_post(self): - response = self.client.post( - "/users/" + str(self.user.id) + "/edit/", - { - "first_name": "john", - "user_name": "john doe search", - "email": "johnDoe@search.com", - "role": "USER", - "is_superuser": False, - }, - ) - self.assertEqual(response.status_code, 200) - self.assertTemplateUsed(response, "create.html") - - def test_accounts_update_status(self): - response = self.client.get("/users/" + str(self.user.id) + "/edit/") - self.assertEqual(response.status_code, 200) - - def test_accounts_update_html(self): - response = self.client.get("/users/" + str(self.user.id) + "/edit/") - self.assertTemplateUsed(response, "create.html") - - -# class DocumentCreateViewTestCase(ObjectsCreation,TestCase): -# def test_document_create(self): -# url = '/documents/create/' -# data = {'title':"xyz",'document_file':"2.png",'created_by':self.user} -# response = self.client.post(url,data) -# self.assertEqual(response.status_code,200) -# def test_update_document(self): -# url = "/documents/"+str(self.document.id)+"/edit/" -# data = {'title':"meg",'document_file':"image.png",'created_by':self.user} -# repsonse = self.client.post(url,data) -# self.assertEqual(response.status_code,200) - - -class ProfileViewTestCase(ObjectsCreation, TestCase): - def test_profile_view(self): - url = "/profile/" - response = self.client.get(url) - self.assertEqual(response.status_code, 200) - - # def test_context_data(self): - # user_login = self.client.login( - # username='admin@micropyramid.com', password='admin123') - # url = "/profile/" - # response = self.client.get(url) - # print(response, "hello") - # self.assertContains(response,'admin@micropyramid.com') - - -class UserDetailView(ObjectsCreation, TestCase): - def test_user_detail(self): - url = "/users/" + str(self.user.id) + "/view/" - response = self.client.get(url) - self.assertEqual(response.status_code, 200) - - -class DocumentDetailView(ObjectsCreation, TestCase): - def test_document_detail(self): - url = "/documents/" + str(self.document.id) + "/view/" - repsonse = self.client.get(url) - get_title = Document.objects.get(title="abc") - self.assertEqual(get_title.title, str(self.document)) - # print('-----------------',self.document.title) - self.assertEqual(repsonse.status_code, 200) - - -class CreateCommentFile(TestCase): - def test_invalid_user_form(self): - company, _ = Company.objects.get_or_create( - name="test company", address="IN", sub_domain="test", country="IN" - ) - user1 = User.objects.create( - username="janedoeUser", - first_name="jane", - last_name="doe", - email="janedoeUser@example.com", - role="USER", - profile_pic="", - password="password", - company=company, - ) - data = { - "email": user1.email, - "first_name": user1.first_name, - "last_name": user1.last_name, - "username": user1.username, - "role": user1.role, - "profile_pic": user1.profile_pic, - "password": user1.password, - } - form = UserForm(data=data, request_user=user1) - userr = User.objects.get(username="janedoeUser") - # print(userr) - self.assertEqual(len(userr.password), 8) - self.assertFalse(form.is_valid()) - # self.assertTrue(form.) - - -class CommentTestCase(ObjectsCreation, TestCase): - def test_comment_add(self): - response = self.client.post("/comment/add/", {"userid": self.user.id}) - self.assertEqual(response.status_code, 200) - - def test_comment_edit(self): - response = self.client.post( - reverse("common:edit_comment", kwargs={"pk": self.comment.id}) - ) - self.assertEqual(response.status_code, 200) - resp = self.client.post( - reverse("common:edit_comment", kwargs={"pk": self.comment.id}), - {"comment": "hello123"}, - ) - self.assertEqual(resp.status_code, 200) - - def test_comment_delete(self): - response = self.client.post("/comment/remove/", {"comment_id": self.comment.id}) - self.assertEqual(response.status_code, 200) - - def test_form_valid(self): - response = self.client.post( - "/comment/add/", {"userid": self.user.id, "comment": "hello"} - ) - self.assertEqual(response.status_code, 200) - - -class DocumentTestCase(ObjectsCreation, TestCase): - def test_document_add(self): - response = self.client.post("/documents/create/") - self.assertEqual(response.status_code, 200) - - def test_document_create(self): - response = self.client.post("/documents/create/") - self.assertEqual(response.status_code, 200) - - def test_document_edit(self): - upload_file = open("static/images/user.png", "rb") - data = { - "title": "doc", - "created_by": self.user, - "document_file": SimpleUploadedFile(upload_file.name, upload_file.read()), - "status": "active", - "shared_to": str(self.user.id), - } - response = self.client.get( - reverse("common:edit_doc", kwargs={"pk": self.document.id}), data - ) - self.assertEqual(response.status_code, 200) - - def test_document_valid(self): - upload_file = open("static/images/user.png", "rb") - response = self.client.post( - "/documents/create/", - { - "title": "doc", - "created_by": self.user, - "document_file": SimpleUploadedFile( - upload_file.name, upload_file.read() - ), - "status": "active", - "shared_to": str(self.user.id), - }, - ) - self.assertEqual(response.status_code, 200) - - def test_document_delete(self): - response = self.client.get( - reverse("common:remove_doc", kwargs={"pk": self.document.id}) - ) - self.assertEqual(response.status_code, 302) - - def test_document_list_view(self): - response = self.client.get(reverse("common:doc_list")) - self.assertEqual(response.status_code, 200) - response = self.client.post( - reverse("common:doc_list"), - {"doc_name": "doc", "status": "active", "shared_to": str(self.user.id)}, - ) - self.assertEqual(response.status_code, 200) - - -# class TestDownloadDocument(ObjectsCreation, TestCase): - -# def test_download_document(self): - -# self.document1 = Document.objects.create( -# title="abcd", document_file="2.png", created_by=self.user) - -# response = self.client.get(reverse('common:download_document', -# args=(self.document1.id,))) -# self.assertEqual(response.status_code, 200) - - -class TestChangeUserStatus(ObjectsCreation, TestCase): - def test_change_user_status(self): - response = self.client.get( - reverse("common:change_user_status", args=(self.user2.id,)) - ) - self.assertEqual(response.status_code, 302) - - -class TestDocumentListViewUser(ObjectsCreation, TestCase): - def test_document_list_view_user(self): - response = self.client.get(reverse("common:doc_list")) - self.assertEqual(response.status_code, 200) - - -class TestViewApiSettings(ObjectsCreation, TestCase): - def test_view_api_settings(self): - - self.api_settings = APISettings.objects.create( - title="api key", apikey="a45fds54fds54", website="https://micropyramid.com" - ) - - response = self.client.get(reverse("common:api_settings")) - self.assertEqual(response.status_code, 200) - - response = self.client.get( - reverse("common:view_api_settings", args=(self.api_settings.id,)) - ) - self.assertEqual(response.status_code, 200) - - -class TestDocumentDetailViewPermissionDenied(ObjectsCreation, TestCase): - def test_document_detail_view_permission(self): - self.client.login(username="janeDoeCommon@user.com", password="password") - response = self.client.get(reverse("common:view_doc", args=(self.document.id,))) - self.assertEqual(response.status_code, 403) - - -class TestChangePasswordByAdmin(ObjectsCreation, TestCase): - def test_change_password_by_admin(self): - response = self.client.post( - reverse("common:change_passsword_by_admin"), - {"useer_id": self.user2.id, "new_passwoord": "new password"}, - ) - self.assertEqual(response.status_code, 302) - - -class TestChangePasswordByAdminPermission(ObjectsCreation, TestCase): - def test_change_password_by_admin_permission(self): - self.client.login(username="janeDoeCommon@user.com", password="password") - response = self.client.post( - reverse("common:change_passsword_by_admin"), - {"useer_id": self.user2.id, "new_passwoord": "new password"}, - ) - self.assertEqual(response.status_code, 403) - self.client.logout() - - -class TestDocumentCreateForm(ObjectsCreation, TestCase): - def test_document_create_form(self): - upload_file = open("static/images/user.png", "rb") - response = self.client.post( - reverse("common:create_doc"), - { - "title": "doc", - "document_file": SimpleUploadedFile( - upload_file.name, upload_file.read() - ), - "shared_to": str(self.user1.id), - }, - ) - self.assertEqual(response.status_code, 200) - - -class TestCommentDelete(ObjectsCreation, TestCase): - def test_comment_delete_form(self): - self.lead = Lead.objects.create( - title="Sample lead title", - first_name="jan doe", - last_name="doe", - email="janeDoe@email.com", - address_line="", - street="street name", - city="city name", - state="state name", - postcode="1234", - country="AD", - website="www.example.com", - status="assigned", - source="Call", - opportunity_amount="700", - description="description lead", - created_by=self.user_admin, - ) - self.comment_user = Comment.objects.create( - comment="test comment", commented_by=self.user_admin, lead=self.lead - ) - response = self.client.post( - reverse("common:remove_comment"), {"comment_id": self.comment_user.id} - ) - self.assertJSONEqual( - force_text(response.content), {"cid": str(self.comment_user.id)} - ) - - -class TestCommentEditErrors(ObjectsCreation, TestCase): - def test_comment_edit_form(self): - self.lead = Lead.objects.create( - title="Sample lead title", - first_name="jan doe", - last_name="doe", - email="janeDoe@email.com", - address_line="", - street="street name", - city="city name", - state="state name", - postcode="1234", - country="AD", - website="www.example.com", - status="assigned", - source="Call", - opportunity_amount="700", - description="description lead", - created_by=self.user_admin, - ) - self.comment_user = Comment.objects.create( - comment="comment test", commented_by=self.user_admin, lead=self.lead - ) - response = self.client.post( - reverse("common:edit_comment", args=(self.comment_user.id,)), - {"pk": self.comment_user.id, "comment": ""}, - ) - self.assertJSONEqual( - force_text(response.content), {"error": ["This field is required."]} - ) - - response = self.client.post( - reverse("common:edit_comment", args=(self.comment_user.id,)), - {"pk": self.comment_user.id, "comment": "comment"}, - ) - - self.assertJSONEqual( - force_text(response.content), - {"comment_id": self.comment_user.id, "comment": "comment"}, - ) - - -class TestDocumentListUser(ObjectsCreation, TestCase): - def test_doc_list_user(self): - self.client.login(username="janeDoeCommon@user.com", password="password") - response = self.client.get(reverse("common:doc_list")) - self.assertEqual(response.status_code, 200) - - -class TestDocumentDelete(ObjectsCreation, TestCase): - def test_document_delete(self): - self.client.login(username="janeDoeCommon@user.com", password="password") - response = self.client.get( - reverse("common:remove_doc", args=(self.document.id,)) - ) - self.assertEqual(response.status_code, 403) - - -class TestDocumentUpdate(ObjectsCreation, TestCase): - def test_document_update(self): - response = self.client.get( - reverse("common:edit_doc", args=(self.document.id,)), - {"title": "title name"}, - ) - self.assertEqual(response.status_code, 200) - - -class TestUserUpdate(ObjectsCreation, TestCase): - def test_user_update(self): - response = self.client.post( - reverse("common:edit_user", args=(self.user2.id,)), {} - ) - self.assertTrue("error" in str(response.content)) - response = self.client.post( - reverse("common:edit_user", args=(self.user2.id,)), - { - "first_name": "janeDoe", - "last_name": "", - "username": "jane doe@common", - "role": "USER", - "email": "janeDoeCommon@user.com", - "has_sales_access": "true", - }, - HTTP_X_REQUESTED_WITH="XMLHttpRequest", - ) - self.assertEqual( - force_text(response.content), - json.dumps({"success_url": reverse("common:users_list"), "error": False}), - ) - - response = self.client.post( - reverse("common:edit_user", args=(self.user2.id,)), - {}, - HTTP_X_REQUESTED_WITH="XMLHttpRequest", - ) - self.assertJSONEqual( - force_text(response.content), - json.dumps( - { - "error": True, - "errors": { - "email": ["This field is required."], - "first_name": ["This field is required."], - "username": ["This field is required."], - "role": ["This field is required."], - "has_sales_access": ["Select atleast one option."], - }, - } - ), - ) - - def test_user_update_permissions(self): - company, _ = Company.objects.get_or_create( - name="test company", address="IN", sub_domain="test", country="IN" - ) - self.user_obj = User.objects.create( - first_name="joe", - username="doe", - email="joedoe@common.com", - role="USER", - company=company, - ) - self.user_obj.set_password("password") - self.user_obj.save() - self.client.login(username="janeDoeCommon@user.com", password="password") - response = self.client.post( - reverse("common:edit_user", args=(self.user_obj.id,)), - { - "first_name": "joe", - "last_name": "doe", - "username": "joe d", - "role": "USER", - "email": "jodoe@common.com", - "has_sales_access": "true", - }, - HTTP_X_REQUESTED_WITH="XMLHttpRequest", - ) - self.assertJSONEqual( - force_text(response.content), json.dumps({"error_403": True, "error": True}) - ) - - response = self.client.post( - reverse("common:edit_user", args=(self.user2.id,)), - { - "first_name": "janeDoeCommon", - "last_name": "jane doe", - "username": "janeDoeCommon", - "role": "USER", - "email": "janeDoeCommon@user.com", - "has_sales_access": "true", - }, - HTTP_X_REQUESTED_WITH="XMLHttpRequest", - ) - self.assertJSONEqual( - force_text(response.content), - json.dumps({"success_url": reverse("common:profile"), "error": False}), - ) - - -class TestAPISettingsDelete(ObjectsCreation, TestCase): - def test_api_settings_delete(self): - self.api_settings = APISettings.objects.create( - title="api key", apikey="a45fds54fds54", website="https://micropyramid.com" - ) - - response = self.client.get( - reverse("common:delete_api_settings", args=(self.api_settings.id,)) - ) - self.assertEqual(response.status_code, 302) - - response = self.client.get( - reverse("common:delete_api_settings", args=(self.api_settings.id,)) - ) - self.assertEqual(response.status_code, 302) - - -class TestGetFullNameModel(ObjectsCreation, TestCase): - def test_get_full_name(self): - self.assertEqual("janeDoeCommon ", self.user2.get_full_name()) - - def test_file_extensions(self): - self.document_txt = Document.objects.create( - title="txt", document_file="text.txt", created_by=self.user - ) - - self.document_csv = Document.objects.create( - title="csv", document_file="sheet.csv", created_by=self.user - ) - - self.document_zip = Document.objects.create( - title="zip", document_file="archive.zip", created_by=self.user - ) - - self.document_pdf = Document.objects.create( - title="pdf", document_file="doc.pdf", created_by=self.user - ) - - self.document_other_format = Document.objects.create( - title="file", document_file="doc_other_format", created_by=self.user - ) - - self.document_image = Document.objects.create( - title="image", document_file="doc_other.png", created_by=self.user - ) - - self.document_video = Document.objects.create( - title="video", document_file="doc.mp4", created_by=self.user - ) - - self.document_audio = Document.objects.create( - title="audio", document_file="doc.mp3", created_by=self.user - ) - - self.document_code = Document.objects.create( - title="code_file", document_file="doc.py", created_by=self.user - ) - - self.assertEqual(("text", "fa fa-file-alt"), self.document_txt.file_type()) - self.assertEqual(("sheet", "fa fa-file-excel"), self.document_csv.file_type()) - self.assertEqual(("zip", "fa fa-file-archive"), self.document_zip.file_type()) - self.assertEqual(("pdf", "fa fa-file-pdf"), self.document_pdf.file_type()) - self.assertEqual(("file", "fa fa-file"), self.document_other_format.file_type()) - self.assertEqual(("image", "fa fa-file-image"), self.document_image.file_type()) - self.assertEqual(("video", "fa fa-file-video"), self.document_video.file_type()) - self.assertEqual(("audio", "fa fa-file-audio"), self.document_audio.file_type()) - self.assertEqual(("code", "fa fa-file-code"), self.document_code.file_type()) - - -class TestUserCreationView(ObjectsCreation, TestCase): - def test_user_creation_view(self): - response = self.client.post( - reverse("common:create_user"), {}, HTTP_X_REQUESTED_WITH="XMLHttpRequest" - ) - self.assertEqual( - force_text(response.content), - json.dumps( - { - "error": True, - "errors": { - "email": ["This field is required."], - "first_name": ["This field is required."], - "username": ["This field is required."], - "role": ["This field is required."], - "has_sales_access": ["Select atleast one option."], - "password": ["This field is required."], - }, - } - ), - ) - - response = self.client.post( - reverse("common:create_user"), - { - "email": "johndoe@commonUser.com", - "first_name": "first name", - "username": "joe", - "role": "USER", - "password": "testpassword", - "has_sales_access": "true", - }, - HTTP_X_REQUESTED_WITH="XMLHttpRequest", - ) - self.assertEqual( - force_text(response.content), - json.dumps({"success_url": "/users/list/", "error": False}), - ) - - def test_add_api_settings(self): - response = self.client.post(reverse("common:add_api_settings"), {}) - self.assertTrue("error" in str(response.content)) - response = self.client.post( - reverse("common:add_api_settings"), - { - "title": "api title", - "lead_assigned_to": str(self.user2.id), - "website": "https://micropyramid.com", - "tags": "api_tag, tag1", - }, - ) - self.assertJSONEqual( - force_text(response.content), - json.dumps({"success_url": reverse("common:api_settings"), "error": False}), - ) - - response = self.client.post( - reverse("common:add_api_settings"), - { - "title": "api title", - "lead_assigned_to": str(self.user2.id), - "website": "https://micropyramid.com", - "tags": "api_tag, tag1", - "savenewform": "true", - }, - ) - self.assertJSONEqual( - force_text(response.content), - json.dumps( - {"success_url": reverse("common:add_api_settings"), "error": False} - ), - ) - - response = self.client.post( - reverse("common:add_api_settings"), - { - "title": "", - "lead_assigned_to": str(self.user2.id), - "website": "micropyramid.com", - "tags": "api_tag, tag1", - "savenewform": "true", - }, - ) - self.assertJSONEqual( - force_text(response.content), - json.dumps( - { - "error": True, - "errors": { - "title": ["This field is required."], - "website": ["Please provide valid schema"], - }, - } - ), - ) - - def test_update_api_settings(self): - self.api_settings_update = APISettings.objects.create( - title="api key update", apikey="asdfasd", website="https://example.com" - ) - response = self.client.post( - reverse("common:update_api_settings", args=(self.api_settings_update.id,)), - {}, - ) - self.assertTrue("error" in str(response.content)) - response = self.client.post( - reverse("common:update_api_settings", args=(self.api_settings_update.id,)), - { - "title": "api key update", - "apikey": "asdfasd", - "website": "http://example.com", - "lead_assigned_to": str(self.user2.id), - "tags": "api_tag_new, tag1", - }, - ) - - response = self.client.post( - reverse("common:update_api_settings", args=(self.api_settings_update.id,)), - { - "title": "api title", - "lead_assigned_to": str(self.user2.id), - "website": "https://micropyramid.com", - "tags": "api_tag, tag1", - "savenewform": "true", - }, - ) - self.assertJSONEqual( - force_text(response.content), - json.dumps( - {"success_url": reverse("common:add_api_settings"), "error": False} - ), - ) - - response = self.client.post( - reverse("common:update_api_settings", args=(self.api_settings_update.id,)), - { - "title": "", - "lead_assigned_to": str(self.user2.id), - "website": "micropyramid.com", - "tags": "api_tag, tag1", - "savenewform": "true", - }, - ) - self.assertJSONEqual( - force_text(response.content), - json.dumps( - { - "error": True, - "errors": { - "title": ["This field is required."], - "website": ["Please provide valid schema"], - }, - } - ), - ) - - def test_document_list_user_view(self): - self.client.login(username="janeDoeCommon@user.com", password="password") - self.document = Document.objects.create( - title="user 2 doc", document_file="1.png", created_by=self.user2 - ) - self.document.shared_to.add(self.user2.id) - response = self.client.get(reverse("common:doc_list")) - self.assertEqual(200, response.status_code) - - upload_file = open("static/images/user.png", "rb") - response = self.client.post( - reverse("common:edit_doc", args=(self.document.id,)), - { - "title": "user 2 doc", - "document_file": SimpleUploadedFile( - upload_file.name, upload_file.read() - ), - "shared_to": str(self.user2.id), - }, - ) - self.assertEqual(200, response.status_code) - # self.assertEqual(force_text(response.content), - # json.dumps({'success_url': reverse('common:doc_list'), 'error': False})) - - # response = self.client.get(reverse('common:download_document', args=(self.document.id,))) - # self.assertEqual(200, response.status_code) - - self.attachment = Attachments.objects.create( - attachment=SimpleUploadedFile(upload_file.name, upload_file.read()), - created_by=self.user, - ) - response = self.client.get( - reverse("common:download_attachment", kwargs=({"pk": self.attachment.id})) - ) - - def test_document_update(self): - self.client.login(username="johnDoeCommon@user.com", password="password") - response = self.client.get( - reverse("common:download_document", args=(self.document.id,)) - ) - self.assertEqual(403, response.status_code) - - def test_user_status(self): - company, _ = Company.objects.get_or_create( - name="test company", address="IN", sub_domain="test", country="IN" - ) - self.user_status = User.objects.create( - first_name="joedoe", - username="joedoe@commonUser", - email="joedoe@commonUser.com", - role="USER", - is_active=False, - company=company, - ) - self.user_status.set_password("password") - self.user_status.save() - response = self.client.get( - reverse("common:change_user_status", kwargs={"pk": self.user_status.id}) - ) - self.assertEqual(302, response.status_code) - - -class TestUserAuthorization(ObjectsCreation, TestCase): - def test_marketing_access_decorator(self): - self.client.login(username="johnDoeCommon@user.com", password="password") - response = self.client.get(reverse("marketing:dashboard")) - self.assertEqual(403, response.status_code) - - -class TestUserFormValidation(ObjectsCreation, TestCase): - def test_marketing_access_decorator(self): - self.client.login(username="janedoe@admin.com", password="password") - - data = {"Newpassword": "password", "confirm": "pas"} - response = self.client.post(reverse("common:change_password"), data) - self.assertEqual(200, response.status_code) - - def test_email_password_reset(self): - self.client.logout() - data = {"email": "some@random.email"} - response = self.client.post(reverse("common:password_reset"), data) - self.assertEqual(200, response.status_code) - - def test_document_unique_title(self): - self.client.login(username="janedoe@admin.com", password="password") - data = {"title": "edit title"} - response = self.client.post( - reverse("common:edit_doc", args=(self.document.id,)), data - ) - json_response = { - "error": True, - "errors": {"title": ["Document with this Title already exists"]}, - } - self.assertJSONEqual(force_text(response.content), json.dumps(json_response)) - - data = {"title": "edit title"} - response = self.client.post(reverse("common:create_doc"), data) - json_response = { - "error": True, - "errors": { - "title": ["Document\u00a0with this Title\u00a0already exists"], - "document_file": ["This field is required."], - }, - } - self.assertJSONEqual(force_text(response.content), json.dumps(json_response)) - - def test_api_setting_form(self): - data = {"website": "http://localhost:8000"} - response = self.client.post(reverse("common:add_api_settings"), data) - json_response = json.dumps( - { - "error": True, - "errors": { - "title": ["This field is required."], - "website": [ - "Please provide a valid URL with schema and without trailing slash - Example: http://google.com" - ], - }, - } - ) - self.assertJSONEqual(force_text(response.content), json_response) - - def test_get_complete_address(self): - - Address_obj_street = Address.objects.create(street="street") - Address_obj_city = Address.objects.create(city="city") - Address_obj_address_line = Address.objects.create(address_line="address_line") - Address_obj_state = Address.objects.create(state="state") - Address_obj_postcode = Address.objects.create(postcode="postcode") - Address_obj_country = Address.objects.create(country="IN") - Address_obj_street_city = Address.objects.create(street="street", city="city") - Address_obj_street_address_line = Address.objects.create( - street="street", address_line="address_line" - ) - Address_obj_street_state = Address.objects.create( - street="street", state="state" - ) - Address_obj_street_postcode = Address.objects.create( - street="street", postcode="postcode" - ) - Address_obj_street_country = Address.objects.create( - street="street", country="IN" - ) - Address_obj_city_address_line = Address.objects.create( - city="city", address_line="address_line" - ) - Address_obj_city_state = Address.objects.create(city="city", state="state") - Address_obj_city_postcode = Address.objects.create( - city="city", postcode="postcode" - ) - Address_obj_city_country = Address.objects.create(city="city", country="IN") - Address_obj_address_line_state = Address.objects.create( - address_line="address_line", state="state" - ) - Address_obj_address_line_postcode = Address.objects.create( - address_line="address_line", postcode="postcode" - ) - Address_obj_address_line_country = Address.objects.create( - address_line="address_line", country="IN" - ) - Address_obj_state_postcode = Address.objects.create( - state="state", postcode="postcode" - ) - Address_obj_state_country = Address.objects.create(state="state", country="IN") - Address_obj_postcode_country = Address.objects.create( - postcode="postcode", country="IN" - ) - Address_obj_street_city_address_line = Address.objects.create( - street="street", city="city", address_line="address_line" - ) - Address_obj_street_city_state = Address.objects.create( - street="street", city="city", state="state" - ) - Address_obj_street_city_postcode = Address.objects.create( - street="street", city="city", postcode="postcode" - ) - Address_obj_street_city_country = Address.objects.create( - street="street", city="city", country="IN" - ) - Address_obj_street_address_line_state = Address.objects.create( - street="street", address_line="address_line", state="state" - ) - Address_obj_street_address_line_postcode = Address.objects.create( - street="street", address_line="address_line", postcode="postcode" - ) - Address_obj_street_address_line_country = Address.objects.create( - street="street", address_line="address_line", country="IN" - ) - Address_obj_street_state_postcode = Address.objects.create( - street="street", state="state", postcode="postcode" - ) - Address_obj_street_state_country = Address.objects.create( - street="street", state="state", country="IN" - ) - Address_obj_street_postcode_country = Address.objects.create( - street="street", postcode="postcode", country="IN" - ) - Address_obj_city_address_line_state = Address.objects.create( - city="city", address_line="address_line", state="state" - ) - Address_obj_city_address_line_postcode = Address.objects.create( - city="city", address_line="address_line", postcode="postcode" - ) - Address_obj_city_address_line_country = Address.objects.create( - city="city", address_line="address_line", country="IN" - ) - Address_obj_city_state_postcode = Address.objects.create( - city="city", state="state", postcode="postcode" - ) - Address_obj_city_state_country = Address.objects.create( - city="city", state="state", country="IN" - ) - Address_obj_city_postcode_country = Address.objects.create( - city="city", postcode="postcode", country="IN" - ) - Address_obj_address_line_state_postcode = Address.objects.create( - address_line="address_line", state="state", postcode="postcode" - ) - Address_obj_address_line_state_country = Address.objects.create( - address_line="address_line", state="state", country="IN" - ) - Address_obj_address_line_postcode_country = Address.objects.create( - address_line="address_line", postcode="postcode", country="IN" - ) - Address_obj_state_postcode_country = Address.objects.create( - state="state", postcode="postcode", country="IN" - ) - Address_obj_street_city_address_line_state = Address.objects.create( - street="street", city="city", address_line="address_line", state="state" - ) - Address_obj_street_city_address_line_postcode = Address.objects.create( - street="street", - city="city", - address_line="address_line", - postcode="postcode", - ) - Address_obj_street_city_address_line_country = Address.objects.create( - street="street", city="city", address_line="address_line", country="IN" - ) - Address_obj_street_city_state_postcode = Address.objects.create( - street="street", city="city", state="state", postcode="postcode" - ) - Address_obj_street_city_state_country = Address.objects.create( - street="street", city="city", state="state", country="IN" - ) - Address_obj_street_city_postcode_country = Address.objects.create( - street="street", city="city", postcode="postcode", country="IN" - ) - Address_obj_street_address_line_state_postcode = Address.objects.create( - street="street", - address_line="address_line", - state="state", - postcode="postcode", - ) - Address_obj_street_address_line_state_country = Address.objects.create( - street="street", address_line="address_line", state="state", country="IN" - ) - Address_obj_street_address_line_postcode_country = Address.objects.create( - street="street", - address_line="address_line", - postcode="postcode", - country="IN", - ) - Address_obj_street_state_postcode_country = Address.objects.create( - street="street", state="state", postcode="postcode", country="IN" - ) - Address_obj_city_address_line_state_postcode = Address.objects.create( - city="city", address_line="address_line", state="state", postcode="postcode" - ) - Address_obj_city_address_line_state_country = Address.objects.create( - city="city", address_line="address_line", state="state", country="IN" - ) - Address_obj_city_address_line_postcode_country = Address.objects.create( - city="city", address_line="address_line", postcode="postcode", country="IN" - ) - Address_obj_city_state_postcode_country = Address.objects.create( - city="city", state="state", postcode="postcode", country="IN" - ) - Address_obj_address_line_state_postcode_country = Address.objects.create( - address_line="address_line", - state="state", - postcode="postcode", - country="IN", - ) - Address_obj_street_city_address_line_state_postcode = Address.objects.create( - street="street", - city="city", - address_line="address_line", - state="state", - postcode="postcode", - ) - Address_obj_street_city_address_line_state_country = Address.objects.create( - street="street", - city="city", - address_line="address_line", - state="state", - country="IN", - ) - Address_obj_street_city_address_line_postcode_country = Address.objects.create( - street="street", - city="city", - address_line="address_line", - postcode="postcode", - country="IN", - ) - Address_obj_street_city_state_postcode_country = Address.objects.create( - street="street", - city="city", - state="state", - postcode="postcode", - country="IN", - ) - Address_obj_street_address_line_state_postcode_country = Address.objects.create( - street="street", - address_line="address_line", - state="state", - postcode="postcode", - country="IN", - ) - Address_obj_city_address_line_state_postcode_country = Address.objects.create( - city="city", - address_line="address_line", - state="state", - postcode="postcode", - country="IN", - ) - Address_obj_street_city_address_line_state_postcode_country = ( - Address.objects.create( - street="street", - city="city", - address_line="address_line", - state="state", - postcode="postcode", - country="IN", - ) - ) - - self.assertEqual(Address_obj_street.get_complete_address(), "street") - self.assertEqual(Address_obj_city.get_complete_address(), "city") - self.assertEqual( - Address_obj_address_line.get_complete_address(), "address_line" - ) - self.assertEqual(Address_obj_state.get_complete_address(), "state") - self.assertEqual(Address_obj_postcode.get_complete_address(), "postcode") - self.assertEqual(Address_obj_country.get_complete_address(), "India") - self.assertEqual(Address_obj_street_city.get_complete_address(), "street, city") - self.assertEqual( - Address_obj_street_address_line.get_complete_address(), - "address_line, street", - ) - self.assertEqual( - Address_obj_street_state.get_complete_address(), "street, state" - ) - self.assertEqual( - Address_obj_street_postcode.get_complete_address(), "street, postcode" - ) - self.assertEqual( - Address_obj_street_country.get_complete_address(), "street, India" - ) - self.assertEqual( - Address_obj_city_address_line.get_complete_address(), "address_line, city" - ) - self.assertEqual(Address_obj_city_state.get_complete_address(), "city, state") - self.assertEqual( - Address_obj_city_postcode.get_complete_address(), "city, postcode" - ) - self.assertEqual(Address_obj_city_country.get_complete_address(), "city, India") - self.assertEqual( - Address_obj_address_line_state.get_complete_address(), "address_line, state" - ) - self.assertEqual( - Address_obj_address_line_postcode.get_complete_address(), - "address_line, postcode", - ) - self.assertEqual( - Address_obj_address_line_country.get_complete_address(), - "address_line, India", - ) - self.assertEqual( - Address_obj_state_postcode.get_complete_address(), "state, postcode" - ) - self.assertEqual( - Address_obj_state_country.get_complete_address(), "state, India" - ) - self.assertEqual( - Address_obj_postcode_country.get_complete_address(), "postcode, India" - ) - self.assertEqual( - Address_obj_street_city_address_line.get_complete_address(), - "address_line, street, city", - ) - self.assertEqual( - Address_obj_street_city_state.get_complete_address(), "street, city, state" - ) - self.assertEqual( - Address_obj_street_city_postcode.get_complete_address(), - "street, city, postcode", - ) - self.assertEqual( - Address_obj_street_city_country.get_complete_address(), - "street, city, India", - ) - self.assertEqual( - Address_obj_street_address_line_state.get_complete_address(), - "address_line, street, state", - ) - self.assertEqual( - Address_obj_street_address_line_postcode.get_complete_address(), - "address_line, street, postcode", - ) - self.assertEqual( - Address_obj_street_address_line_country.get_complete_address(), - "address_line, street, India", - ) - self.assertEqual( - Address_obj_street_state_postcode.get_complete_address(), - "street, state, postcode", - ) - self.assertEqual( - Address_obj_street_state_country.get_complete_address(), - "street, state, India", - ) - self.assertEqual( - Address_obj_street_postcode_country.get_complete_address(), - "street, postcode, India", - ) - self.assertEqual( - Address_obj_city_address_line_state.get_complete_address(), - "address_line, city, state", - ) - self.assertEqual( - Address_obj_city_address_line_postcode.get_complete_address(), - "address_line, city, postcode", - ) - self.assertEqual( - Address_obj_city_address_line_country.get_complete_address(), - "address_line, city, India", - ) - self.assertEqual( - Address_obj_city_state_postcode.get_complete_address(), - "city, state, postcode", - ) - self.assertEqual( - Address_obj_city_state_country.get_complete_address(), "city, state, India" - ) - self.assertEqual( - Address_obj_city_postcode_country.get_complete_address(), - "city, postcode, India", - ) - self.assertEqual( - Address_obj_address_line_state_postcode.get_complete_address(), - "address_line, state, postcode", - ) - self.assertEqual( - Address_obj_address_line_state_country.get_complete_address(), - "address_line, state, India", - ) - self.assertEqual( - Address_obj_address_line_postcode_country.get_complete_address(), - "address_line, postcode, India", - ) - self.assertEqual( - Address_obj_state_postcode_country.get_complete_address(), - "state, postcode, India", - ) - self.assertEqual( - Address_obj_street_city_address_line_state.get_complete_address(), - "address_line, street, city, state", - ) - self.assertEqual( - Address_obj_street_city_address_line_postcode.get_complete_address(), - "address_line, street, city, postcode", - ) - self.assertEqual( - Address_obj_street_city_address_line_country.get_complete_address(), - "address_line, street, city, India", - ) - self.assertEqual( - Address_obj_street_city_state_postcode.get_complete_address(), - "street, city, state, postcode", - ) - self.assertEqual( - Address_obj_street_city_state_country.get_complete_address(), - "street, city, state, India", - ) - self.assertEqual( - Address_obj_street_city_postcode_country.get_complete_address(), - "street, city, postcode, India", - ) - self.assertEqual( - Address_obj_street_address_line_state_postcode.get_complete_address(), - "address_line, street, state, postcode", - ) - self.assertEqual( - Address_obj_street_address_line_state_country.get_complete_address(), - "address_line, street, state, India", - ) - self.assertEqual( - Address_obj_street_address_line_postcode_country.get_complete_address(), - "address_line, street, postcode, India", - ) - self.assertEqual( - Address_obj_street_state_postcode_country.get_complete_address(), - "street, state, postcode, India", - ) - self.assertEqual( - Address_obj_city_address_line_state_postcode.get_complete_address(), - "address_line, city, state, postcode", - ) - self.assertEqual( - Address_obj_city_address_line_state_country.get_complete_address(), - "address_line, city, state, India", - ) - self.assertEqual( - Address_obj_city_address_line_postcode_country.get_complete_address(), - "address_line, city, postcode, India", - ) - self.assertEqual( - Address_obj_city_state_postcode_country.get_complete_address(), - "city, state, postcode, India", - ) - self.assertEqual( - Address_obj_address_line_state_postcode_country.get_complete_address(), - "address_line, state, postcode, India", - ) - self.assertEqual( - Address_obj_street_city_address_line_state_postcode.get_complete_address(), - "address_line, street, city, state, postcode", - ) - self.assertEqual( - Address_obj_street_city_address_line_state_country.get_complete_address(), - "address_line, street, city, state, India", - ) - self.assertEqual( - Address_obj_street_city_address_line_postcode_country.get_complete_address(), - "address_line, street, city, postcode, India", - ) - self.assertEqual( - Address_obj_street_city_state_postcode_country.get_complete_address(), - "street, city, state, postcode, India", - ) - self.assertEqual( - Address_obj_street_address_line_state_postcode_country.get_complete_address(), - "address_line, street, state, postcode, India", - ) - self.assertEqual( - Address_obj_city_address_line_state_postcode_country.get_complete_address(), - "address_line, city, state, postcode, India", - ) - self.assertEqual( - Address_obj_street_city_address_line_state_postcode_country.get_complete_address(), - "address_line, street, city, state, postcode, India", - ) - - self.assertEqual(str(Address_obj_street), "") - self.assertEqual(str(Address_obj_city), "city") - - def test_file_extensions_classes(self): - doc_mp3 = Attachments.objects.create( - file_name="file_mp3", attachment="file.mp3" - ) - doc_mp4 = Attachments.objects.create( - file_name="file_mp4", attachment="file.mp4" - ) - doc_png = Attachments.objects.create( - file_name="file_png", attachment="file.png" - ) - doc_pdf = Attachments.objects.create( - file_name="file_pdf", attachment="file.pdf" - ) - doc_json = Attachments.objects.create( - file_name="file_json", attachment="file.json" - ) - doc_txt = Attachments.objects.create( - file_name="file_txt", attachment="file.txt" - ) - doc_csv = Attachments.objects.create( - file_name="file_csv", attachment="file.csv" - ) - doc_zip = Attachments.objects.create( - file_name="file_zip", attachment="file.zip" - ) - doc_unknown_extension = Attachments.objects.create( - file_name="file_unknown_extension", attachment="file.unknown_extension" - ) - doc_without_extension = Attachments.objects.create( - file_name="file_unknown_extension", attachment="file_without_extension" - ) - doc_without_attachment = Attachments.objects.create( - file_name="file_unknown_extension" - ) - - self.assertEqual(doc_mp3.file_type(), ("audio", "fa fa-file-audio")) - self.assertEqual(doc_mp4.file_type(), ("video", "fa fa-file-video")) - self.assertEqual(doc_png.file_type(), ("image", "fa fa-file-image")) - self.assertEqual(doc_pdf.file_type(), ("pdf", "fa fa-file-pdf")) - self.assertEqual(doc_json.file_type(), ("code", "fa fa-file-code")) - self.assertEqual(doc_txt.file_type(), ("text", "fa fa-file-alt")) - self.assertEqual(doc_csv.file_type(), ("sheet", "fa fa-file-excel")) - self.assertEqual(doc_zip.file_type(), ("zip", "fa fa-file-archive")) - self.assertEqual(doc_unknown_extension.file_type(), ("file", "fa fa-file")) - self.assertEqual(doc_without_extension.file_type(), ("file", "fa fa-file")) - - self.assertEqual(doc_csv.get_file_type_display(), ("fa fa-file-excel")) - self.assertEqual(doc_without_attachment.get_file_type_display(), None) - # self.assertTrue(doc_csv.created_on_arrow in ["just now", "seconds ago"]) - # self.assertTrue(self.document.created_on_arrow in ["just now", "seconds ago"]) - - def test_api_settings_str(self): - api_obj = APISettings.objects.create(title="api setting") - self.assertEqual("api setting", str(api_obj)) - - def test_arrow_format(self): - date = datetime.datetime.today() + datetime.timedelta(days=-2) - self.comment = Comment.objects.create( - comment="comment", user=self.user, commented_by=self.user, commented_on=date - ) - # self.assertTrue(self.comment.commented_on_arrow in ["just now", "seconds ago"]) - - -class TestViewFunctions(ObjectsCreation, TestCase): - def test_404_handler(self): - self.client.login(username="johndoe@admin.com", password="password") - response = self.client.get("/not-existing-url") - self.assertTemplateUsed(response, "404.html") - - def test_admin_mixin(self): - self.client.login(username="janeDoeCommon@user.com", password="password") - response = self.client.get(reverse("common:users_list")) - self.assertEqual(403, response.status_code) - response = self.client.get(reverse("common:dashboard")) - self.assertEqual(200, response.status_code) - response = self.client.get(reverse("common:change_password")) - self.assertEqual(200, response.status_code) - - self.client.logout() - response = self.client.get(reverse("common:login")) - self.assertEqual(200, response.status_code) - - data = {"email": "janeDoeCommon@user.com", "password": "password"} - response = self.client.post( - reverse("common:login"), data, HTTP_HOST="test.bottlecrm.com" - ) - self.assertEqual(302, response.status_code) - - self.client.logout() - company, _ = Company.objects.get_or_create( - name="test company", address="IN", sub_domain="test", country="IN" - ) - self.user_marketing = User.objects.create( - first_name="johnDoeCommonMarketing", - username="johnDoeCommonMarketing", - email="johnDoeCommonMarketing@user.com", - role="USER", - has_marketing_access=True, - is_active=True, - company=company, - ) - self.user_marketing.set_password("password") - self.user_marketing.save() - data = {"email": "johnDoeCommonMarketing@user.com", "password": "password"} - response = self.client.post( - reverse("common:login"), data, HTTP_HOST="test.bottlecrm.com" - ) - self.assertEqual(302, response.status_code) - - self.user_marketing.is_active = False - self.user_marketing.save() - data = {"email": "johnDoeCommonMarketing@user.com", "password": "password"} - response = self.client.post(reverse("common:login"), data) - self.assertEqual(200, response.status_code) - - data = {"email": "invalid@account.com", "password": "password"} - response = self.client.post(reverse("common:login"), data) - self.assertEqual(200, response.status_code) - - def test_user_list(self): - self.client.login(username="johndoe@admin.com", password="password") - response = self.client.post(reverse("common:users_list"), data={"role": "USER"}) - self.assertEqual(200, response.status_code) - - def test_user_create_with_team(self): - self.client.login(username="johndoe@admin.com", password="password") - self.team_dev = Teams.objects.create(name="dev team") - response = self.client.post( - "/users/create/", - { - "email": "john@developer.com", - "first_name": "john", - "last_name": "dev", - "username": "john@developer.com", - "password": "password", - "role": "USER", - "teams": [ - self.team_dev.id, - ], - "has_sales_access": "on", - }, - HTTP_X_REQUESTED_WITH="XMLHttpRequest", - ) - self.assertEqual(response.status_code, 200) - # response = self.client.post('/users/create/', { - # 'email': 'jane@developer.com', - # 'first_name': 'jane', - # 'last_name': 'dev', - # 'username': 'jane@developer.com', - # 'password': 'password', - # 'role': 'USER', 'teams':[self.team_dev.id,], - # 'has_sales_access':'on'}) - # self.assertEqual(response.status_code, 302) - # response = self.client.post('/users/create/', { - # 'email': 'jane.com', - # 'first_name': 'jane', - # 'last_name': 'dev', - # 'username': 'jane@developer.com', - # 'password': 'password', - # 'role': 'USER', - # 'has_sales_access':'on'}) - # self.assertEqual(response.status_code, 200) - user_id = User.objects.filter(email="john@developer.com").first().id - user_edit_url = reverse("common:edit_user", args=(user_id,)) - self.team_test = Teams.objects.create(name="test team") - response = self.client.post( - user_edit_url, - { - "email": "john@developer.com", - "first_name": "john", - "last_name": "dev", - "username": "john@developer.com", - "password": "password", - "role": "USER", - "teams": [ - self.team_test.id, - ], - "has_sales_access": "on", - }, - HTTP_X_REQUESTED_WITH="XMLHttpRequest", - ) - self.assertEqual(response.status_code, 200) - - def test_admin_profile_edit(self): - self.client.login(username="johndoe@admin.com", password="password") - user_edit_url = reverse("common:edit_user", args=(self.user_admin.id,)) - response = self.client.post( - user_edit_url, - { - "email": "johndoe@admin.com", - "first_name": "john", - "username": "johndoeAdmin", - "role": "ADMIN", - }, - HTTP_X_REQUESTED_WITH="XMLHttpRequest", - ) - self.assertEqual(response.status_code, 200) - - def test_doc_create(self): - self.client.login(username="janeDoeCommon@user.com", password="password") - response = self.client.post(reverse("common:create_doc"), {}) - self.assertEqual(response.status_code, 200) - - self.team_test = Teams.objects.create(name="test team 1") - self.team_test.users.add(self.user1.id, self.user2.id) - - upload_file = open("static/images/user.png", "rb") - shared_user = User.objects.filter(email="johndoe@admin.com").first() - data = { - "title": "new doc", - "document_file": SimpleUploadedFile(upload_file.name, upload_file.read()), - "teams": [ - self.team_test.id, - ], - "shared_to": [ - shared_user.id, - ], - } - response = self.client.post( - reverse("common:create_doc"), data, HTTP_X_REQUESTED_WITH="XMLHttpRequest" - ) - self.assertEqual(response.status_code, 200) - - upload_file = open("static/images/user.png", "rb") - data = { - "title": "another new doc", - "document_file": SimpleUploadedFile(upload_file.name, upload_file.read()), - "teams": [ - self.team_test.id, - ], - "shared_to": [ - shared_user.id, - ], - } - response = self.client.post( - reverse("common:edit_doc", args=(self.document.id,)), - data, - HTTP_X_REQUESTED_WITH="XMLHttpRequest", - ) - self.assertEqual(response.status_code, 200) - - self.client.login(username="johndoe@admin.com", password="password") - response = self.client.get( - reverse("common:download_document", args=(self.document.id,)) - ) - self.assertEqual(200, response.status_code) diff --git a/common/tests_celery_tasks.py b/common/tests_celery_tasks.py index 6d5a074..7567d4a 100644 --- a/common/tests_celery_tasks.py +++ b/common/tests_celery_tasks.py @@ -5,7 +5,7 @@ from accounts.tests import AccountCreateTest from cases.tests import CaseCreation -from common.models import User, Comment, Company +from common.models import User, Comment from common.tasks import ( resend_activation_link_to_user, send_email_to_new_user, @@ -88,15 +88,11 @@ class TestUserMentionsForAccountComments(AccountCreateTest, TestCase): BROKER_BACKEND="memory", ) def test_user_mentions_for_account_comment(self): - self.company, _ = Company.objects.get_or_create( - name="test company", address="IN", sub_domain="test", country="IN" - ) self.user_comment = User.objects.create( first_name="johnComment", username="johnDoeComment", email="johnDoeComment@example.com", role="ADMIN", - company=self.company, ) self.user_comment.set_password("password") self.user_comment.save() @@ -121,15 +117,11 @@ class TestUserMentionsForContactsComments(ContactObjectsCreation, TestCase): BROKER_BACKEND="memory", ) def test_user_mentions_for_contacts_comments(self): - self.company, _ = Company.objects.get_or_create( - name="test company", address="IN", sub_domain="test", country="IN" - ) self.user_comment = User.objects.create( first_name="johnComment", username="johnDoeComment", email="johnDoeComment@example.com", role="ADMIN", - company=self.company, ) self.user_comment.set_password("password") self.user_comment.save() @@ -154,15 +146,11 @@ class TestUserMentionsForLeadsComments(TestLeadModel, TestCase): BROKER_BACKEND="memory", ) def test_user_mentions_for_leads_comments(self): - self.company, _ = Company.objects.get_or_create( - name="test company", address="IN", sub_domain="test", country="IN" - ) self.user_comment = User.objects.create( first_name="johnComment", username="johnDoeComment", email="johnDoeComment@example.com", role="ADMIN", - company=self.company, ) self.user_comment.set_password("password") self.user_comment.save() @@ -187,15 +175,11 @@ class TestUserMentionsForOpportunityComments(OpportunityModel, TestCase): BROKER_BACKEND="memory", ) def test_user_mentions_for_opportunity_comments(self): - self.company, _ = Company.objects.get_or_create( - name="test company", address="IN", sub_domain="test", country="IN" - ) self.user_comment = User.objects.create( first_name="johnComment", username="johnDoeComment", email="johnDoeComment@example.com", role="ADMIN", - company=self.company, ) self.user_comment.set_password("password") self.user_comment.save() @@ -220,15 +204,11 @@ class TestUserMentionsForCasesComments(CaseCreation, TestCase): BROKER_BACKEND="memory", ) def test_user_mentions_for_cases_comments(self): - self.company, _ = Company.objects.get_or_create( - name="test company", address="IN", sub_domain="test", country="IN" - ) self.user_comment = User.objects.create( first_name="johnComment", username="johnDoeComment", email="johnDoeComment@example.com", role="ADMIN", - company=self.company, ) self.user_comment.set_password("password") self.user_comment.save() @@ -253,15 +233,11 @@ class TestUserMentionsForTasksComments(TaskCreateTest, TestCase): BROKER_BACKEND="memory", ) def test_user_mentions_for_tasks_comments(self): - self.company, _ = Company.objects.get_or_create( - name="test company", address="IN", sub_domain="test", country="IN" - ) self.user_comment = User.objects.create( first_name="johnComment", username="johnDoeComment", email="johnDoeComment@example.com", role="ADMIN", - company=self.company, ) self.user_comment.set_password("password") self.user_comment.save() @@ -286,15 +262,11 @@ class TestUserMentionsForInvoiceComments(InvoiceCreateTest, TestCase): BROKER_BACKEND="memory", ) def test_user_mentions_for_invoice_comments(self): - self.company, _ = Company.objects.get_or_create( - name="test company", address="IN", sub_domain="test", country="IN" - ) self.user_comment = User.objects.create( first_name="johnComment", username="johnDoeComment", email="johnDoeComment@example.com", role="ADMIN", - company=self.company, ) self.user_comment.set_password("password") self.user_comment.save() @@ -319,15 +291,11 @@ class TestUserMentionsForEventsComments(EventObjectTest, TestCase): BROKER_BACKEND="memory", ) def test_user_mentions_for_events_comments(self): - self.company, _ = Company.objects.get_or_create( - name="test company", address="IN", sub_domain="test", country="IN" - ) self.user_comment = User.objects.create( first_name="johnComment", username="johnDoeComment", email="johnDoeComment@example.com", role="ADMIN", - company=self.company, ) self.user_comment.set_password("password") self.user_comment.save() diff --git a/common/urls.py b/common/urls.py deleted file mode 100644 index 6e2c620..0000000 --- a/common/urls.py +++ /dev/null @@ -1,130 +0,0 @@ -from django.conf import settings -from django.conf.urls.static import static -from django.contrib.auth import views as auth_views -from django.urls import path - -from common.views import ( - ChangePasswordView, - CompanyLoginView, - CreateUserView, - DocumentDeleteView, - DocumentDetailView, - DocumentListView, - ForgotPasswordView, - HomeView, - # LoginView, - LogoutView, - PasswordResetView, - ProfileView, - RegistrationView, - UpdateUserView, - UserDeleteView, - UserDetailView, - UsersListView, - activate_user, - add_api_settings, - add_comment, - api_settings, - change_passsword_by_admin, - change_user_status, - check_sub_domain, - create_lead_from_site, - delete_api_settings, - document_create, - document_update, - download_attachment, - download_document, - edit_comment, - get_teams_and_users, - google_login, - landing_page, - remove_comment, - resend_activation_link, - update_api_settings, - view_api_settings, -) - -app_name = "common" - - -urlpatterns = [ - path("", landing_page, name="landing_page"), - path("dashboard/", HomeView.as_view(), name="dashboard"), - path("login/", CompanyLoginView.as_view(), name="login"), - # path('login/', LoginView.as_view(), name='login'), - path("register/", RegistrationView.as_view(), name="register"), - path("auth/domain/", check_sub_domain, name="check_domain"), - path("forgot-password/", ForgotPasswordView.as_view(), name="forgot_password"), - path("logout/", LogoutView.as_view(), name="logout"), - path("change-password/", ChangePasswordView.as_view(), name="change_password"), - path("profile/", ProfileView.as_view(), name="profile"), - # User views - path("users/list/", UsersListView.as_view(), name="users_list"), - path("users/create/", CreateUserView.as_view(), name="create_user"), - path("users//edit/", UpdateUserView.as_view(), name="edit_user"), - path("users//view/", UserDetailView.as_view(), name="view_user"), - path("users//delete/", UserDeleteView.as_view(), name="remove_user"), - path("password-reset/", PasswordResetView.as_view(), name="password_reset"), - path( - "password-reset/done/", - auth_views.PasswordResetDoneView.as_view(), - name="password_reset_done", - ), - path( - "reset///", - auth_views.PasswordResetConfirmView.as_view(), - name="password_reset_confirm", - ), - path( - "reset/done/", - auth_views.PasswordResetCompleteView.as_view(), - name="password_reset_complete", - ), - # Document - path("documents/", DocumentListView.as_view(), name="doc_list"), - path("documents/create/", document_create, name="create_doc"), - path("documents//edit/", document_update, name="edit_doc"), - path("documents//view/", DocumentDetailView.as_view(), name="view_doc"), - path("documents//delete/", DocumentDeleteView.as_view(), name="remove_doc"), - # download - path("documents//download/", download_document, name="download_document"), - # download_attachment - path( - "attachments//download/", - download_attachment, - name="download_attachment", - ), - path("user/status//", change_user_status, name="change_user_status"), - path("comment/add/", add_comment, name="add_comment"), - path("comment//edit/", edit_comment, name="edit_comment"), - path("comment/remove/", remove_comment, name="remove_comment"), - # settings - path("api/settings/", api_settings, name="api_settings"), - path("api/settings/add/", add_api_settings, name="add_api_settings"), - path("api/settings//", view_api_settings, name="view_api_settings"), - path( - "api/settings//update/", update_api_settings, name="update_api_settings" - ), - path( - "api/settings//delete/", delete_api_settings, name="delete_api_settings" - ), - path( - "change-password-by-admin/", - change_passsword_by_admin, - name="change_passsword_by_admin", - ), - path("google/login/", google_login, name="google_login"), - path("create-lead-from-site/", create_lead_from_site, name="create_lead_from_site"), - # user activate link - path( - "activate-user////", - activate_user, - name="activate_user", - ), - path( - "resend_activation_link//", - resend_activation_link, - name="resend_activation_link", - ), - path("get_teams_and_users/", get_teams_and_users, name="get_teams_and_users"), -] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/common/utils.py b/common/utils.py index 4288dcb..cd59ff5 100644 --- a/common/utils.py +++ b/common/utils.py @@ -18,7 +18,6 @@ def jwt_payload_handler(user): "id": user.pk, # 'name': user.name, "email": user.email, - "company": user.company.id, "role": user.role, "has_sales_access": user.has_sales_access, "has_marketing_access": user.has_marketing_access, diff --git a/common/views.py b/common/views.py deleted file mode 100644 index 6768236..0000000 --- a/common/views.py +++ /dev/null @@ -1,1472 +0,0 @@ -import datetime -import json -import os - -import boto3 -import botocore -import phonenumbers -import requests -from django.conf import settings -from django.contrib import messages -from django.contrib.auth import authenticate, login, logout -from django.contrib.auth.decorators import login_required -from django.contrib.auth.hashers import check_password -from django.contrib.auth.mixins import AccessMixin, LoginRequiredMixin -from django.contrib.auth.views import PasswordResetView -from django.contrib.sites.shortcuts import get_current_site -from django.core.cache import cache -from django.core.exceptions import PermissionDenied -from django.core.mail import EmailMessage -from django.db.models import Q -from django.http import Http404, HttpResponse, HttpResponseRedirect, JsonResponse -from django.shortcuts import get_object_or_404, redirect, render -from django.template.loader import render_to_string -from django.urls import reverse, reverse_lazy -from django.utils import timezone -from django.utils.encoding import force_bytes, force_text -from django.utils.http import urlsafe_base64_decode, urlsafe_base64_encode -from django.views.generic import ( - CreateView, - DeleteView, - DetailView, - TemplateView, - UpdateView, - View, -) - -from accounts.models import Account, Tags -from cases.models import Case -from common.access_decorators_mixins import ( - MarketingAccessRequiredMixin, - SalesAccessRequiredMixin, - admin_login_required, - marketing_access_required, - sales_access_required, -) -from common.forms import ( - APISettingsForm, - ChangePasswordForm, - CompanyLoginForm, - DocumentForm, - LoginForm, - PasswordResetEmailForm, - RegistrationForm, - UserCommentForm, - UserForm, -) -from common.models import ( - APISettings, - Attachments, - Comment, - Company, - Document, - Google, - Profile, - User, -) -from common.tasks import ( - resend_activation_link_to_user, - send_email_to_new_user, - send_email_user_delete, - send_email_user_status, -) -from common.token_generator import account_activation_token -from common.utils import COUNTRIES, ROLES -from contacts.models import Contact -from leads.models import Lead -from marketing.models import BlockedDomain, BlockedEmail, ContactEmailCampaign -from opportunity.models import Opportunity -from teams.models import Teams - - -def handler404(request, exception): - return render(request, "404.html", status=404) - - -def handler500(request): - return render(request, "500.html", status=500) - - -def landing_page(request): - if request.user.is_authenticated: - return redirect("common:dashboard") - return render(request, "landing_page.html", status=200) - - -def check_sub_domain(request): - if request.method == "GET": - # try: - # if request.company: - # return redirect("common:login") - # except: - return render(request, "check_subdomain.html", {}) - if request.method == "POST": - sub_domain = request.POST.get("sub_domain", "") - if sub_domain == "": - return render( - request, - "check_subdomain.html", - {"error": "Please mention a sub_domain"}, - ) - company = Company.objects.filter(sub_domain=sub_domain).first() - if company: - abs_url = ( - request.scheme - + "://" - + company.sub_domain - + "." - + settings.DOMAIN_NAME - + reverse("common:login") - ) - # request.session["company"] = company.id - return HttpResponseRedirect(abs_url) - else: - return render( - request, "check_subdomain.html", {"error": "Company does not exist"} - ) - - -@login_required -def get_teams_and_users(request): - data = {} - teams = Teams.objects.all() - teams_data = [ - {"team": team.id, "users": [user.id for user in team.users.all()]} - for team in teams - ] - users = User.objects.all().values_list("id", flat=True) - data["teams"] = teams_data - data["users"] = list(users) - return JsonResponse(data) - - -class AdminRequiredMixin(AccessMixin): - def dispatch(self, request, *args, **kwargs): - if not request.user.is_authenticated: - return self.handle_no_permission() - self.raise_exception = True - if not request.user.role == "ADMIN": - if not request.user.is_superuser: - return self.handle_no_permission() - return super(AdminRequiredMixin, self).dispatch(request, *args, **kwargs) - - -class HomeView(SalesAccessRequiredMixin, LoginRequiredMixin, TemplateView): - template_name = "sales/index.html" - - def get_context_data(self, **kwargs): - context = super(HomeView, self).get_context_data(**kwargs) - accounts = Account.objects.filter(status="open", company=self.request.company) - contacts = Contact.objects.filter(company=self.request.company) - leads = Lead.objects.filter(company=self.request.company).exclude( - Q(status="converted") | Q(status="closed") - ) - opportunities = Opportunity.objects.filter(company=self.request.company) - if self.request.user.role == "ADMIN" or self.request.user.is_superuser: - pass - else: - accounts = accounts.filter( - Q(assigned_to__id__in=[self.request.user.id]) - | Q(created_by=self.request.user.id) - ) - contacts = contacts.filter( - Q(assigned_to__id__in=[self.request.user.id]) - | Q(created_by=self.request.user.id) - ) - leads = leads.filter( - Q(assigned_to__id__in=[self.request.user.id]) - | Q(created_by=self.request.user.id) - ).exclude(status="closed") - opportunities = opportunities.filter( - Q(assigned_to__id__in=[self.request.user.id]) - | Q(created_by=self.request.user.id) - ) - - context["accounts"] = accounts - context["contacts_count"] = contacts.count() - context["leads_count"] = leads - context["opportunities"] = opportunities - return context - - -class ChangePasswordView(LoginRequiredMixin, TemplateView): - template_name = "change_password.html" - - def get_context_data(self, **kwargs): - context = super(ChangePasswordView, self).get_context_data(**kwargs) - context["change_password_form"] = ChangePasswordForm() - return context - - def post(self, request, *args, **kwargs): - error, errors = "", "" - form = ChangePasswordForm(request.POST, user=request.user) - if form.is_valid(): - user = request.user - # if not check_password(request.POST.get('CurrentPassword'), - # user.password): - # error = "Invalid old password" - # else: - user.set_password(request.POST.get("Newpassword")) - user.is_active = True - user.save() - return redirect("common:dashboard") - else: - errors = form.errors - return render( - request, - "change_password.html", - {"error": error, "errors": errors, "change_password_form": form}, - ) - - -class ProfileView(LoginRequiredMixin, TemplateView): - template_name = "profile.html" - - def get_context_data(self, **kwargs): - - context = super(ProfileView, self).get_context_data(**kwargs) - context["user_obj"] = self.request.user - return context - - -# class LoginView(TemplateView): -# template_name = "login.html" - -# def get_context_data(self, **kwargs): -# context = super(LoginView, self).get_context_data(**kwargs) -# context["ENABLE_GOOGLE_LOGIN"] = settings.ENABLE_GOOGLE_LOGIN -# context["GP_CLIENT_SECRET"] = settings.GP_CLIENT_SECRET -# context["GP_CLIENT_ID"] = settings.GP_CLIENT_ID -# return context - -# def dispatch(self, request, *args, **kwargs): -# if request.user.is_authenticated: -# return redirect("common:dashboard") -# return super(LoginView, self).dispatch(request, *args, **kwargs) - -# def post(self, request, *args, **kwargs): -# form = LoginForm(request.POST, request=request) -# if form.is_valid(): - -# user = User.objects.filter(email=request.POST.get("email")).first() -# # user = authenticate(username=request.POST.get('email'), password=request.POST.get('password')) -# if user is not None: -# if user.is_active: -# user = authenticate( -# username=request.POST.get("email"), -# password=request.POST.get("password"), -# ) -# if user is not None: -# login(request, user) -# if user.has_sales_access: -# return redirect("common:dashboard") -# elif user.has_marketing_access: -# return redirect("marketing:dashboard") -# else: -# return redirect("common:dashboard") -# return render( -# request, -# "login.html", -# { -# "ENABLE_GOOGLE_LOGIN": settings.ENABLE_GOOGLE_LOGIN, -# "GP_CLIENT_SECRET": settings.GP_CLIENT_SECRET, -# "GP_CLIENT_ID": settings.GP_CLIENT_ID, -# "error": True, -# "message": "Your username and password didn't match. \ -# Please try again.", -# }, -# ) -# return render( -# request, -# "login.html", -# { -# "ENABLE_GOOGLE_LOGIN": settings.ENABLE_GOOGLE_LOGIN, -# "GP_CLIENT_SECRET": settings.GP_CLIENT_SECRET, -# "GP_CLIENT_ID": settings.GP_CLIENT_ID, -# "error": True, -# "message": "Your Account is inactive. Please Contact Administrator", -# }, -# ) -# return render( -# request, -# "login.html", -# { -# "ENABLE_GOOGLE_LOGIN": settings.ENABLE_GOOGLE_LOGIN, -# "GP_CLIENT_SECRET": settings.GP_CLIENT_SECRET, -# "GP_CLIENT_ID": settings.GP_CLIENT_ID, -# "error": True, -# "message": "Your Account is not Found. Please Contact Administrator", -# }, -# ) - -# return render( -# request, -# "login.html", -# { -# "ENABLE_GOOGLE_LOGIN": settings.ENABLE_GOOGLE_LOGIN, -# "GP_CLIENT_SECRET": settings.GP_CLIENT_SECRET, -# "GP_CLIENT_ID": settings.GP_CLIENT_ID, -# # "error": True, -# # "message": "Your username and password didn't match. Please try again." -# "form": form, -# }, -# ) - - -class ForgotPasswordView(TemplateView): - template_name = "forgot_password.html" - - -class LogoutView(LoginRequiredMixin, View): - def get(self, request, *args, **kwargs): - logout(request) - request.session.flush() - request.company = None - url = request.scheme + "://" + settings.DOMAIN_NAME + "/" - return HttpResponseRedirect(url) - # return redirect("common:login") - - -class UsersListView(AdminRequiredMixin, TemplateView): - model = User - context_object_name = "users" - template_name = "list.html" - - def get_queryset(self): - queryset = self.model.objects.filter(company=self.request.company) - - request_post = self.request.POST - if request_post: - if request_post.get("username"): - queryset = queryset.filter( - username__icontains=request_post.get("username") - ) - if request_post.get("email"): - queryset = queryset.filter(email__icontains=request_post.get("email")) - if request_post.get("role"): - queryset = queryset.filter(role=request_post.get("role")) - if request_post.get("status"): - queryset = queryset.filter(is_active=request_post.get("status")) - - return queryset.order_by("username") - - def get_context_data(self, **kwargs): - context = super(UsersListView, self).get_context_data(**kwargs) - active_users = self.get_queryset().filter(is_active=True) - inactive_users = self.get_queryset().filter(is_active=False) - context["active_users"] = active_users - context["inactive_users"] = inactive_users - context["per_page"] = self.request.POST.get("per_page") - context["admin_email"] = settings.ADMIN_EMAIL - context["roles"] = ROLES - context["status"] = [("True", "Active"), ("False", "In Active")] - return context - - def post(self, request, *args, **kwargs): - context = self.get_context_data(**kwargs) - return self.render_to_response(context) - - -class RegistrationView(CreateView): - model = Company - form_class = RegistrationForm - template_name = "company_register.html" - - def form_valid(self, form): - user = form.save(commit=False) - company = Company.objects.create(sub_domain=form.cleaned_data["sub_domain"]) - company.save() - user.company = company - user.role = "ADMIN" - user.is_superuser = False - user.has_marketing_access = True - user.has_sales_access = True - user.is_admin = True - user.set_password(form.cleaned_data["password"]) - user.save() - return redirect("common:dashboard") - # return super(RegistrationView, self).form_valid(form) - - def get_context_data(self, **kwargs): - context = super(RegistrationView, self).get_context_data(**kwargs) - return context - - -class CompanyLoginView(CreateView): - # model = User - form_class = CompanyLoginForm - template_name = "company_login.html" - - def post(self, request, *args, **kwargs): - # add company to request and header - host_name = request.META.get("HTTP_HOST") - subdomain = host_name.split(".")[0] - company = Company.objects.filter(sub_domain=subdomain).first() - if company: - request.company = company - request.session["company"] = company.id - else: - return render( - request, - "check_subdomain.html", - {"error": "Please mention a sub_domain"}, - ) - form = CompanyLoginForm(request.POST, request=request) - if form.is_valid(): - email = form.cleaned_data.get("email", "") - password = form.cleaned_data.get("password", "") - # company = get_object_or_404(Company, pk=form.data.get("company", "")) - if request.company: - user = User.objects.filter(email=email, company=request.company).first() - if user is not None: - if user.is_active: - user = authenticate( - email=email, password=password, company=request.company - ) - if user is not None: - login(request, user) - request.session["company"] = ( - user.company.id if user.company else None - ) - if user.has_sales_access: - return redirect(reverse("common:dashboard")) - elif user.has_marketing_access: - return redirect("marketing:dashboard") - else: - return redirect("common:dashboard") - return render( - request, - "company_login.html", - { - "form": form, - "error": True, - "message": "Your username and password didn't match. \ - Please try again.", - }, - ) - return render( - request, - "company_login.html", - { - "form": form, - "error": True, - "message": "Your Account is inactive. Please Contact Administrator", - }, - ) - return render( - request, - "company_login.html", - { - "form": form, - "error": True, - "message": "Your Account is not Found. Please Contact Administrator", - }, - ) - return render( - request, - "company_login.html", - { - "form": form, - "error": True, - "message": "Company with this sub domain does not exist", - }, - ) - return render(request, "company_login.html", {"form": form, "error": False}) - - def get_context_data(self, **kwargs): - context = super(CompanyLoginView, self).get_context_data(**kwargs) - return context - - -class CreateUserView(AdminRequiredMixin, CreateView): - model = User - form_class = UserForm - template_name = "create.html" - # success_url = '/users/list/' - - def form_valid(self, form): - user = form.save(commit=False) - if form.cleaned_data.get("password"): - user.set_password(form.cleaned_data.get("password")) - user.company = self.request.company - user.save() - - if self.request.POST.getlist("teams"): - for team in self.request.POST.getlist("teams"): - Teams.objects.filter(id=team).first().users.add(user) - - current_site = self.request.get_host() - protocol = self.request.scheme - send_email_to_new_user.delay( - user.email, self.request.user.email, domain=current_site, protocol=protocol - ) - # mail_subject = 'Created account in CRM' - # message = render_to_string('new_user.html', { - # 'user': user, - # 'created_by': self.request.user - - # }) - # email = EmailMessage(mail_subject, message, to=[user.email]) - # email.content_subtype = "html" - # email.send() - - if self.request.is_ajax(): - data = {"success_url": reverse_lazy("common:users_list"), "error": False} - return JsonResponse(data) - return super(CreateUserView, self).form_valid(form) - - def form_invalid(self, form): - response = super(CreateUserView, self).form_invalid(form) - if self.request.is_ajax(): - return JsonResponse({"error": True, "errors": form.errors}) - return response - - def get_form_kwargs(self): - kwargs = super(CreateUserView, self).get_form_kwargs() - kwargs.update({"request_user": self.request.user}) - return kwargs - - def get_context_data(self, **kwargs): - context = super(CreateUserView, self).get_context_data(**kwargs) - context["user_form"] = context["form"] - context["teams"] = Teams.objects.filter(company=self.request.company) - if "errors" in kwargs: - context["errors"] = kwargs["errors"] - return context - - -class UserDetailView(AdminRequiredMixin, DetailView): - model = User - context_object_name = "users" - template_name = "user_detail.html" - - def dispatch(self, request, *args, **kwargs): - user = self.get_object() - if user.company != request.company: - raise PermissionDenied - return super(UserDetailView, self).dispatch(request, *args, **kwargs) - - def get_context_data(self, **kwargs): - context = super(UserDetailView, self).get_context_data(**kwargs) - user_obj = self.object - users_data = [] - for each in User.objects.all(): - assigned_dict = {} - assigned_dict["id"] = each.id - assigned_dict["name"] = each.username - users_data.append(assigned_dict) - context.update( - { - "user_obj": user_obj, - "opportunity_list": Opportunity.objects.filter(assigned_to=user_obj.id), - "contacts": Contact.objects.filter(assigned_to=user_obj.id), - "cases": Case.objects.filter(assigned_to=user_obj.id), - # "accounts": Account.objects.filter(assigned_to=user_obj.id), - "assigned_data": json.dumps(users_data), - "comments": user_obj.user_comments.all(), - } - ) - return context - - -class UpdateUserView(LoginRequiredMixin, UpdateView): - model = User - form_class = UserForm - template_name = "create.html" - - def dispatch(self, request, *args, **kwargs): - user = self.get_object() - if user.company != request.company: - raise PermissionDenied - return super(UpdateUserView, self).dispatch(request, *args, **kwargs) - - def form_valid(self, form): - user = form.save(commit=False) - if self.request.is_ajax(): - if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: - if self.request.user.id != self.object.id: - data = {"error_403": True, "error": True} - return JsonResponse(data) - if user.role == "USER": - user.is_superuser = False - user.save() - - if self.request.POST.getlist("teams"): - user_teams = user.user_teams.all() - # this is for removing the user from previous team - for user_team in user_teams: - user_team.users.remove(user) - # this is for assigning the user to new team - for team in self.request.POST.getlist("teams"): - team_obj = Teams.objects.filter(id=team).first() - team_obj.users.add(user) - - if self.request.user.role == "ADMIN" and self.request.user.is_superuser: - if self.request.is_ajax(): - data = { - "success_url": reverse_lazy("common:users_list"), - "error": False, - } - if self.request.user.id == user.id: - data = { - "success_url": reverse_lazy("common:profile"), - "error": False, - } - return JsonResponse(data) - return JsonResponse(data) - if self.request.is_ajax(): - data = {"success_url": reverse_lazy("common:profile"), "error": False} - return JsonResponse(data) - return super(UpdateUserView, self).form_valid(form) - - def form_invalid(self, form): - response = super(UpdateUserView, self).form_invalid(form) - if self.request.is_ajax(): - return JsonResponse({"error": True, "errors": form.errors}) - return response - - def get_form_kwargs(self): - kwargs = super(UpdateUserView, self).get_form_kwargs() - kwargs.update({"request_user": self.request.user}) - return kwargs - - def get_context_data(self, **kwargs): - context = super(UpdateUserView, self).get_context_data(**kwargs) - context["user_obj"] = self.object - user_profile_name = str(context["user_obj"].profile_pic).split("/") - user_profile_name = user_profile_name[-1] - context["user_profile_name"] = user_profile_name - context["user_form"] = context["form"] - context["teams"] = Teams.objects.filter(company=self.request.company) - if "errors" in kwargs: - context["errors"] = kwargs["errors"] - return context - - -class UserDeleteView(AdminRequiredMixin, DeleteView): - model = User - - def dispatch(self, request, *args, **kwargs): - user = self.get_object() - if user.company != request.company: - raise PermissionDenied - return super(UserDeleteView, self).dispatch(request, *args, **kwargs) - - def get(self, request, *args, **kwargs): - self.object = self.get_object() - current_site = request.get_host() - deleted_by = self.request.user.email - send_email_user_delete.delay( - self.object.email, - deleted_by=deleted_by, - domain=current_site, - protocol=request.scheme, - ) - self.object.delete() - lead_users = ( - User.objects.filter(is_active=True).order_by("email").values("id", "email") - ) - cache.set("lead_form_users", lead_users, 60 * 60) - return redirect("common:users_list") - - -class PasswordResetView(PasswordResetView): - template_name = "registration/password_reset_form.html" - form_class = PasswordResetEmailForm - email_template_name = "registration/password_reset_email.html" - html_email_template_name = "registration/password_reset_email.html" - from_email = settings.PASSWORD_RESET_MAIL_FROM_USER - - -@login_required -@sales_access_required -def document_create(request): - template_name = "doc_create.html" - users = [] - if request.user.role == "ADMIN" or request.user.is_superuser: - users = User.objects.filter(is_active=True, company=request.company).order_by( - "email" - ) - else: - users = User.objects.filter(role="ADMIN", company=request.company).order_by( - "email" - ) - form = DocumentForm(users=users, request_obj=request) - if request.POST: - form = DocumentForm( - request.POST, request.FILES, users=users, request_obj=request - ) - if form.is_valid(): - doc = form.save(commit=False) - doc.created_by = request.user - doc.company = request.company - doc.save() - if request.POST.getlist("shared_to"): - doc.shared_to.add(*request.POST.getlist("shared_to")) - if request.POST.getlist("teams", []): - user_ids = Teams.objects.filter( - id__in=request.POST.getlist("teams") - ).values_list("users", flat=True) - assinged_to_users_ids = doc.shared_to.all().values_list("id", flat=True) - for user_id in user_ids: - if user_id not in assinged_to_users_ids: - doc.shared_to.add(user_id) - - if request.POST.getlist("teams", []): - doc.teams.add(*request.POST.getlist("teams")) - - data = {"success_url": reverse_lazy("common:doc_list"), "error": False} - return JsonResponse(data) - return JsonResponse({"error": True, "errors": form.errors}) - context = {} - context["doc_form"] = form - context["users"] = users - context["teams"] = Teams.objects.filter(company=request.company) - context["sharedto_list"] = [ - int(i) for i in request.POST.getlist("assigned_to", []) if i - ] - context["errors"] = form.errors - return render(request, template_name, context) - - -class DocumentListView(SalesAccessRequiredMixin, LoginRequiredMixin, TemplateView): - model = Document - context_object_name = "documents" - template_name = "doc_list_1.html" - - def get_queryset(self): - queryset = self.model.objects.all() - if self.request.user.is_superuser or self.request.user.role == "ADMIN": - queryset = queryset - else: - if self.request.user.documents(): - doc_ids = self.request.user.documents().values_list("id", flat=True) - shared_ids = queryset.filter( - Q(status="active") & Q(shared_to__id__in=[self.request.user.id]) - ).values_list("id", flat=True) - queryset = queryset.filter(Q(id__in=doc_ids) | Q(id__in=shared_ids)) - else: - queryset = queryset.filter( - Q(status="active") & Q(shared_to__id__in=[self.request.user.id]) - ) - - request_post = self.request.POST - if request_post: - if request_post.get("doc_name"): - queryset = queryset.filter( - title__icontains=request_post.get("doc_name") - ) - if request_post.get("status"): - queryset = queryset.filter(status=request_post.get("status")) - - if request_post.getlist("shared_to"): - queryset = queryset.filter( - shared_to__id__in=request_post.getlist("shared_to") - ) - return queryset.filter(company=self.request.company) - - def get_context_data(self, **kwargs): - context = super(DocumentListView, self).get_context_data(**kwargs) - context["users"] = User.objects.filter( - is_active=True, company=self.request.company - ).order_by("username") - context["documents"] = self.get_queryset() - context["status_choices"] = Document.DOCUMENT_STATUS_CHOICE - context["sharedto_list"] = [ - int(i) for i in self.request.POST.getlist("shared_to", []) if i - ] - context["per_page"] = self.request.POST.get("per_page") - - search = False - if ( - self.request.POST.get("doc_name") - or self.request.POST.get("status") - or self.request.POST.get("shared_to") - ): - search = True - - context["search"] = search - return context - - def post(self, request, *args, **kwargs): - context = self.get_context_data(**kwargs) - return self.render_to_response(context) - - -class DocumentDeleteView(LoginRequiredMixin, DeleteView): - model = Document - - def get(self, request, *args, **kwargs): - if not request.user.role == "ADMIN": - if not request.user == Document.objects.get(id=kwargs["pk"]).created_by: - raise PermissionDenied - self.object = self.get_object() - if self.object.company != request.company: - raise PermissionDenied - self.object.delete() - return redirect("common:doc_list") - - -@login_required -@sales_access_required -def document_update(request, pk): - template_name = "doc_create.html" - users = [] - if request.user.role == "ADMIN" or request.user.is_superuser: - users = User.objects.filter(is_active=True).order_by("email") - else: - users = User.objects.filter(role="ADMIN").order_by("email") - document = Document.objects.filter(id=pk).first() - - if document.company != request.company: - raise PermissionDenied - - form = DocumentForm(users=users, instance=document, request_obj=request) - - if request.POST: - form = DocumentForm( - request.POST, - request.FILES, - instance=document, - users=users, - request_obj=request, - ) - if form.is_valid(): - doc = form.save(commit=False) - doc.save() - - doc.shared_to.clear() - if request.POST.getlist("shared_to"): - doc.shared_to.add(*request.POST.getlist("shared_to")) - - if request.POST.getlist("teams", []): - user_ids = Teams.objects.filter( - id__in=request.POST.getlist("teams") - ).values_list("users", flat=True) - assinged_to_users_ids = doc.shared_to.all().values_list("id", flat=True) - for user_id in user_ids: - if user_id not in assinged_to_users_ids: - doc.shared_to.add(user_id) - - if request.POST.getlist("teams", []): - doc.teams.clear() - doc.teams.add(*request.POST.getlist("teams")) - else: - doc.teams.clear() - - data = {"success_url": reverse_lazy("common:doc_list"), "error": False} - return JsonResponse(data) - return JsonResponse({"error": True, "errors": form.errors}) - context = {} - context["doc_obj"] = document - context["doc_form"] = form - context["doc_file_name"] = context["doc_obj"].document_file.name.split("/")[-1] - context["users"] = users.filter(company=request.company) - context["teams"] = Teams.objects.filter(company=request.company) - context["sharedto_list"] = [ - int(i) for i in request.POST.getlist("shared_to", []) if i - ] - context["errors"] = form.errors - return render(request, template_name, context) - - -class DocumentDetailView(SalesAccessRequiredMixin, LoginRequiredMixin, DetailView): - model = Document - template_name = "doc_detail.html" - - def dispatch(self, request, *args, **kwargs): - if self.get_object().company != request.company: - raise PermissionDenied - - if not request.user.role == "ADMIN": - if not request.user == Document.objects.get(id=kwargs["pk"]).created_by: - raise PermissionDenied - - return super(DocumentDetailView, self).dispatch(request, *args, **kwargs) - - def get_context_data(self, **kwargs): - context = super(DocumentDetailView, self).get_context_data(**kwargs) - # documents = Document.objects.all() - context.update( - { - "file_type_code": self.object.file_type()[1], - "doc_obj": self.object, - } - ) - return context - - -def download_document(request, pk): - # doc_obj = Document.objects.filter(id=pk).last() - doc_obj = Document.objects.get(id=pk) - if doc_obj: - if not request.user.role == "ADMIN": - if ( - not request.user == doc_obj.created_by - and request.user not in doc_obj.shared_to.all() - ): - raise PermissionDenied - if settings.STORAGE_TYPE == "normal": - path = doc_obj.document_file.path - file_path = os.path.join(settings.MEDIA_ROOT, path) - if os.path.exists(file_path): - with open(file_path, "rb") as fh: - response = HttpResponse( - fh.read(), content_type="application/vnd.ms-excel" - ) - response[ - "Content-Disposition" - ] = "inline; filename=" + os.path.basename(file_path) - return response - else: - file_path = doc_obj.document_file - file_name = doc_obj.title - BUCKET_NAME = "django-crm-demo" - KEY = str(file_path) - s3 = boto3.resource("s3") - try: - s3.Bucket(BUCKET_NAME).download_file(KEY, file_name) - with open(file_name, "rb") as fh: - response = HttpResponse( - fh.read(), content_type="application/vnd.ms-excel" - ) - response[ - "Content-Disposition" - ] = "inline; filename=" + os.path.basename(file_name) - os.remove(file_name) - return response - except botocore.exceptions.ClientError as e: - if e.response["Error"]["Code"] == "404": - print("The object does not exist.") - else: - raise - - return path - raise Http404 - - -def download_attachment(request, pk): # pragma: no cover - attachment_obj = Attachments.objects.filter(id=pk).last() - if attachment_obj: - if settings.STORAGE_TYPE == "normal": - path = attachment_obj.attachment.path - file_path = os.path.join(settings.MEDIA_ROOT, path) - if os.path.exists(file_path): - with open(file_path, "rb") as fh: - response = HttpResponse( - fh.read(), content_type="application/vnd.ms-excel" - ) - response[ - "Content-Disposition" - ] = "inline; filename=" + os.path.basename(file_path) - return response - else: - file_path = attachment_obj.attachment - file_name = attachment_obj.file_name - BUCKET_NAME = "django-crm-demo" - KEY = str(file_path) - s3 = boto3.resource("s3") - try: - s3.Bucket(BUCKET_NAME).download_file(KEY, file_name) - with open(file_name, "rb") as fh: - response = HttpResponse( - fh.read(), content_type="application/vnd.ms-excel" - ) - response[ - "Content-Disposition" - ] = "inline; filename=" + os.path.basename(file_name) - os.remove(file_name) - return response - except botocore.exceptions.ClientError as e: - if e.response["Error"]["Code"] == "404": - print("The object does not exist.") - else: - raise - raise Http404 - - -def change_user_status(request, pk): - user = get_object_or_404(User, pk=pk) - if user.is_active: - user.is_active = False - else: - user.is_active = True - user.save() - current_site = request.get_host() - status_changed_user = request.user.email - send_email_user_status.delay( - pk, - status_changed_user=status_changed_user, - domain=current_site, - protocol=request.scheme, - ) - return HttpResponseRedirect("/users/list/") - - -def add_comment(request): - if request.method == "POST": - user = get_object_or_404(User, id=request.POST.get("userid")) - form = UserCommentForm(request.POST) - if form.is_valid(): - comment = form.save(commit=False) - comment.commented_by = request.user - comment.user = user - comment.save() - return JsonResponse( - { - "comment_id": comment.id, - "comment": comment.comment, - "commented_on": comment.commented_on, - "commented_by": comment.commented_by.email, - } - ) - return JsonResponse({"error": form.errors}) - - -def edit_comment(request, pk): - if request.method == "POST": - comment_obj = get_object_or_404(Comment, id=pk) - if request.user == comment_obj.commented_by: - form = UserCommentForm(request.POST, instance=comment_obj) - if form.is_valid(): - comment_obj.comment = form.cleaned_data.get("comment") - comment_obj.save(update_fields=["comment"]) - return JsonResponse( - { - "comment_id": comment_obj.id, - "comment": comment_obj.comment, - } - ) - return JsonResponse({"error": form["comment"].errors}) - data = {"error": "You don't have permission to edit this comment."} - return JsonResponse(data) - - -def remove_comment(request): - if request.method == "POST": - comment_obj = get_object_or_404(Comment, id=request.POST.get("comment_id")) - if request.user == comment_obj.commented_by: - comment_obj.delete() - data = {"cid": request.POST.get("comment_id")} - return JsonResponse(data) - data = {"error": "You don't have permission to delete this comment."} - return JsonResponse(data) - - -@login_required -@admin_login_required -def api_settings(request): - # api_settings = APISettings.objects.all() - blocked_domains = BlockedDomain.objects.all() - blocked_emails = BlockedEmail.objects.all() - contacts = ContactEmailCampaign.objects.all() - created_by_users = User.objects.filter(role="ADMIN") - assigned_users = User.objects.all() - - context = { - # 'settings': api_settings, - "contacts": contacts, - "created_by_users": created_by_users, - "assigned_users": assigned_users, - "blocked_emails": blocked_emails, - "blocked_domains": blocked_domains, - } - - if request.method == "POST": - - # settings = api_settings - # if request.POST.get('api_settings', None): - # if request.POST.get('title', None): - # settings = settings.filter(title__icontains=request.POST.get('title', None)) - # if request.POST.get('created_by', None): - # settings = settings.filter(created_by_id=request.POST.get('created_by', None)) - # if request.POST.get('assigned_to', None): - # settings = settings.filter(lead_assigned_to__id__in=request.POST.getlist('assigned_to', None)) - - # context['settings']= settings.distinct() - - if request.POST.get("filter_contacts", None): - contacts_filter = contacts - if request.POST.get("contact_name", None): - contacts_filter = contacts_filter.filter( - name__icontains=request.POST.get("contact_name", None) - ) - if request.POST.get("contact_created_by", None): - contacts_filter = contacts_filter.filter( - created_by_id=request.POST.get("contact_created_by", None) - ) - if request.POST.get("contact_email", None): - contacts_filter = contacts_filter.filter( - email__icontains=request.POST.get("contact_email", None) - ) - - context["contacts"] = contacts_filter.distinct() - - if request.POST.get("filter_blocked_domains", None): - if request.POST.get("domain", ""): - blocked_domains = blocked_domains.filter( - domain__icontains=request.POST.get("domain", "") - ) - if request.POST.get("created_by", ""): - blocked_domains = blocked_domains.filter( - created_by_id=request.POST.get("created_by", "") - ) - - context["blocked_domains"] = blocked_domains - - if request.POST.get("filter_blocked_emails", None): - if request.POST.get("email", ""): - blocked_emails = blocked_emails.filter( - email__icontains=request.POST.get("email", "") - ) - if request.POST.get("created_by", ""): - blocked_emails = blocked_emails.filter( - created_by_id=request.POST.get("created_by", "") - ) - - context["blocked_emails"] = blocked_emails - - return render(request, "settings/list.html", context) - - -def add_api_settings(request): - users = User.objects.filter(is_active=True).order_by("email") - form = APISettingsForm(assign_to=users) - assign_to_list = [] - if request.POST: - form = APISettingsForm(request.POST, assign_to=users) - assign_to_list = [ - int(i) for i in request.POST.getlist("lead_assigned_to", []) if i - ] - if form.is_valid(): - settings_obj = form.save(commit=False) - settings_obj.created_by = request.user - settings_obj.save() - if request.POST.get("tags", ""): - tags = request.POST.get("tags") - splitted_tags = tags.split(",") - for t in splitted_tags: - tag = Tags.objects.filter(name=t) - if tag: - tag = tag[0] - else: - tag = Tags.objects.create(name=t) - settings_obj.tags.add(tag) - if assign_to_list: - settings_obj.lead_assigned_to.add(*assign_to_list) - success_url = reverse_lazy("common:api_settings") - if request.POST.get("savenewform"): - success_url = reverse_lazy("common:add_api_settings") - data = {"success_url": success_url, "error": False} - return JsonResponse(data) - return JsonResponse({"error": True, "errors": form.errors}) - data = { - "form": form, - "setting": api_settings, - "users": users, - "assign_to_list": assign_to_list, - } - return render(request, "settings/create.html", data) - - -def view_api_settings(request, pk): - api_settings = APISettings.objects.filter(pk=pk).first() - data = {"setting": api_settings} - return render(request, "settings/view.html", data) - - -def update_api_settings(request, pk): - api_settings = APISettings.objects.filter(pk=pk).first() - users = User.objects.filter(is_active=True).order_by("email") - form = APISettingsForm(instance=api_settings, assign_to=users) - assign_to_list = [] - if request.POST: - form = APISettingsForm(request.POST, instance=api_settings, assign_to=users) - assign_to_list = [ - int(i) for i in request.POST.getlist("lead_assigned_to", []) if i - ] - if form.is_valid(): - settings_obj = form.save(commit=False) - settings_obj.save() - if request.POST.get("tags", ""): - settings_obj.tags.clear() - tags = request.POST.get("tags") - splitted_tags = tags.split(",") - for t in splitted_tags: - tag = Tags.objects.filter(name=t) - if tag: - tag = tag[0] - else: - tag = Tags.objects.create(name=t) - settings_obj.tags.add(tag) - if assign_to_list: - settings_obj.lead_assigned_to.clear() - settings_obj.lead_assigned_to.add(*assign_to_list) - success_url = reverse_lazy("common:api_settings") - if request.POST.get("savenewform"): - success_url = reverse_lazy("common:add_api_settings") - data = {"success_url": success_url, "error": False} - return JsonResponse(data) - return JsonResponse({"error": True, "errors": form.errors}) - data = { - "form": form, - "setting": api_settings, - "users": users, - "assign_to_list": assign_to_list, - "assigned_to_list": json.dumps( - [setting.id for setting in api_settings.lead_assigned_to.all() if setting] - ), - } - return render(request, "settings/update.html", data) - - -def delete_api_settings(request, pk): - api_settings = APISettings.objects.filter(pk=pk).first() - if api_settings: - api_settings.delete() - data = {"error": False, "response": "Successfully Deleted!"} - else: - data = {"error": True, "response": "Object Not Found!"} - # return JsonResponse(data) - return redirect("common:api_settings") - - -def change_passsword_by_admin(request): - if request.user.role == "ADMIN" or request.user.is_superuser: - if request.method == "POST": - user = get_object_or_404(User, id=request.POST.get("useer_id")) - user.set_password(request.POST.get("new_passwoord")) - user.save() - mail_subject = "Crm Account Password Changed" - message = ( - "

      hello " - + user.username - + "


      Your account password has been changed !\ -

      " - + "

      New Password : " - + request.POST.get("new_passwoord") - + "

      " - ) - email = EmailMessage(mail_subject, message, to=[user.email]) - email.content_subtype = "html" - email.send() - return HttpResponseRedirect("/users/list/") - raise PermissionDenied - - -def google_login(request): # pragma: no cover - if "code" in request.GET: - params = { - "grant_type": "authorization_code", - "code": request.GET.get("code"), - "redirect_uri": "http://" - + request.META["HTTP_HOST"] - + reverse("common:google_login"), - "client_id": settings.GP_CLIENT_ID, - "client_secret": settings.GP_CLIENT_SECRET, - } - - info = requests.post("https://accounts.google.com/o/oauth2/token", data=params) - info = info.json() - url = "https://www.googleapis.com/oauth2/v1/userinfo" - params = {"access_token": info["access_token"]} - kw = dict(params=params, headers={}, timeout=60) - response = requests.request("GET", url, **kw) - user_document = response.json() - - link = "https://plus.google.com/" + user_document["id"] - dob = user_document["birthday"] if "birthday" in user_document.keys() else "" - gender = user_document["gender"] if "gender" in user_document.keys() else "" - link = user_document["link"] if "link" in user_document.keys() else link - - verified_email = ( - user_document["verified_email"] - if "verified_email" in user_document.keys() - else "" - ) - name = user_document["name"] if "name" in user_document.keys() else "name" - first_name = ( - user_document["given_name"] - if "given_name" in user_document.keys() - else "first_name" - ) - last_name = ( - user_document["family_name"] - if "family_name" in user_document.keys() - else "last_name" - ) - email = ( - user_document["email"] - if "email" in user_document.keys() - else "email@dummy.com" - ) - - user = User.objects.filter(email=user_document["email"]) - - if user: - user = user[0] - user.first_name = first_name - user.last_name = last_name - else: - user = User.objects.create( - username=email, - email=email, - first_name=first_name, - last_name=last_name, - role="USER", - has_sales_access=True, - has_marketing_access=True, - ) - - google, _ = Google.objects.get_or_create(user=user) - google.user = user - google.google_url = link - google.verified_email = verified_email - google.google_id = user_document["id"] - google.family_name = last_name - google.name = name - google.given_name = first_name - google.dob = dob - google.email = email - google.gender = gender - google.save() - - user.last_login = datetime.datetime.now() - user.save() - - login(request, user) - - if request.GET.get("state") != "1235dfghjkf123": - return HttpResponseRedirect(request.GET.get("state")) - if user.has_sales_access: - return redirect("common:dashboard") - elif user.has_marketing_access: - return redirect("marketing:dashboard") - else: - return redirect("common:dashboard") - if request.GET.get("next"): - next_url = request.GET.get("next") - else: - next_url = "1235dfghjkf123" - rty = ( - "https://accounts.google.com/o/oauth2/auth?client_id=" - + settings.GP_CLIENT_ID - + "&response_type=code" - ) - rty += ( - "&scope=https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email&redirect_uri=" - + "http://" - + request.META["HTTP_HOST"] - + reverse("common:google_login") - + "&state=" - + next_url - ) - return HttpResponseRedirect(rty) - - -def create_lead_from_site(request): # pragma: no cover - allowed_domains = [ - "micropyramid.com", - "test.microsite.com:8000", - ] - # add origin_domain = request.get_host() in the post body - if ( - request.get_host() - in [ - "sales.micropyramid.com", - ] - and request.POST.get("origin_domain") in allowed_domains - ): - if request.method == "POST": - if request.POST.get("full_name", None): - try: - description = ( - request.POST.get("enquiry_type") - + "\n" - + request.POST.get("message") - ) - except Exception as e: - print("e:::", e) - country = request.POST.get("country").title() - country_codes = list(COUNTRIES) - for count in country_codes: - if country == count[1]: - country = count[0] - break - phone = request.POST.get("phone") - phone_number = phonenumbers.parse(phone, country) - lead = Lead.objects.create( - title=request.POST.get("full_name"), - email=request.POST.get("email"), - phone=phone_number, - description=description, - country=country, - created_from_site=True, - ) - lead.source = "micropyramid" - lead.save() - recipients = User.objects.filter(role="ADMIN").values_list( - "id", flat=True - ) - lead.assigned_to.add(*recipients) - from leads.tasks import send_email_to_assigned_user - - send_email_to_assigned_user( - recipients, - lead.id, - domain="sales.micropyramid.com", - source=request.POST.get("origin_domain"), - ) - return HttpResponse("Lead Created") - from django.http import HttpResponseBadRequest - - return HttpResponseBadRequest("Bad Request") - - -def activate_user(request, uidb64, token, activation_key): # pragma: no cover - profile = get_object_or_404(Profile, activation_key=activation_key) - if profile.user: - if timezone.now() > profile.key_expires: - resend_url = reverse( - "common:resend_activation_link", args=(profile.user.id,) - ) - link_content = ( - 'Click Here to resend the activation link.'.format( - resend_url - ) - ) - message_content = "Your activation link has expired, {}".format( - link_content - ) - messages.info(request, message_content) - return render(request, "login.html") - else: - try: - uid = force_text(urlsafe_base64_decode(uidb64)) - user = User.objects.get(pk=uid) - except (TypeError, ValueError, OverflowError, User.DoesNotExist): - user = None - if user is not None and account_activation_token.check_token(user, token): - user.is_active = True - user.save() - login(request, user) - if user.has_sales_access: - return redirect("common:dashboard") - elif user.has_marketing_access: - return redirect("marketing:dashboard") - else: - return redirect("common:dashboard") - # return HttpResponse('Thank you for your email confirmation. Now you can login your account.') - else: - return HttpResponse("Activation link is invalid!") - - -def resend_activation_link(request, userId): # pragma: no cover - user = get_object_or_404(User, pk=userId) - kwargs = { - "user_email": user.email, - "domain": request.get_host(), - "protocol": request.scheme, - } - resend_activation_link_to_user.delay(**kwargs) - return redirect("common:dashboard") diff --git a/contacts/api_urls.py b/contacts/api_urls.py index 619943e..c10c533 100644 --- a/contacts/api_urls.py +++ b/contacts/api_urls.py @@ -5,5 +5,7 @@ urlpatterns = [ path("", api_views.ContactsListView.as_view()), - path("/", api_views.ContactDetailView.as_view(), name="view_contact"), + path("/", api_views.ContactDetailView.as_view()), + path("comment//", api_views.ContactCommentView.as_view()), + path("attachment//", api_views.ContactAttachmentView.as_view()), ] diff --git a/contacts/api_views.py b/contacts/api_views.py index ffbeb9e..98d2639 100644 --- a/contacts/api_views.py +++ b/contacts/api_views.py @@ -1,5 +1,5 @@ from rest_framework import status -from common.models import User, Attachments +from common.models import User, Attachments, Comment from contacts.models import Contact from teams.models import Teams from django.db.models import Q @@ -7,6 +7,7 @@ from drf_yasg.utils import swagger_auto_schema from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response +from rest_framework.pagination import LimitOffsetPagination from common.custom_auth import JSONWebTokenAuthentication from contacts import swagger_params from contacts.serializer import * @@ -23,9 +24,10 @@ from django.contrib.sites.shortcuts import get_current_site from contacts.tasks import send_email_to_assigned_user import json +from crm import settings -class ContactsListView(APIView): +class ContactsListView(APIView, LimitOffsetPagination): authentication_classes = (JSONWebTokenAuthentication,) permission_classes = (IsAuthenticated,) model = Contact @@ -36,9 +38,7 @@ def get_context_data(self, **kwargs): if len(self.request.data) == 0 else self.request.data ) - queryset = self.model.objects.filter(company=self.request.company).order_by( - "-created_on" - ) + queryset = self.model.objects.all().order_by("-created_on") if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: queryset = queryset.filter( Q(assigned_to__in=[self.request.user]) | Q(created_by=self.request.user) @@ -74,21 +74,29 @@ def get_context_data(self, **kwargs): ): search = True context["search"] = search - context["contact_obj_list"] = ContactSerializer(queryset, many=True).data + + results_contact = self.paginate_queryset( + queryset.distinct(), self.request, view=self + ) + contacts = ContactSerializer(results_contact, many=True).data + context["per_page"] = 10 + context.update( + { + "contacts_count": self.count, + "next": self.get_next_link(), + "previous": self.get_previous_link(), + "page_number": int(self.offset / 10) + 1, + } + ) + context["contact_obj_list"] = contacts context["users"] = UserSerializer( - User.objects.filter(is_active=True, company=self.request.company).order_by( - "email" - ), + User.objects.filter(is_active=True).order_by("email"), many=True, ).data context["countries"] = COUNTRIES - context["teams"] = TeamsSerializer( - Teams.objects.filter(company=self.request.company), many=True - ).data + context["teams"] = TeamsSerializer(Teams.objects.all(), many=True).data context["per_page"] = params.get("per_page") - context["assignedto_list"] = UserSerializer( - User.objects.filter(company=self.request.company), many=True - ).data + context["assignedto_list"] = UserSerializer(User.objects.all(), many=True).data return context @swagger_auto_schema( @@ -114,46 +122,53 @@ def post(self, request, *args, **kwargs): if not address_serializer.is_valid(): data["address_errors"] = (address_serializer.errors,) if data: - return Response({"error": True, "errors": data}) + return Response( + {"error": True, "errors": data}, + status=status.HTTP_400_BAD_REQUEST, + ) # if contact_serializer.is_valid() and address_serializer.is_valid(): address_obj = address_serializer.save() contact_obj = contact_serializer.save() contact_obj.address = address_obj contact_obj.created_by = self.request.user - contact_obj.company = self.request.company contact_obj.save() if self.request.user.role == "ADMIN": if params.get("teams"): teams = json.loads(params.get("teams")) for team in teams: - teams_ids = Teams.objects.filter(id=team, company=request.company) + teams_ids = Teams.objects.filter(id=team) if teams_ids: contact_obj.teams.add(team) else: contact_obj.delete() data["team"] = "Please enter valid Team" - return Response({"error": True, "errors": data}) + return Response( + {"error": True, "errors": data}, + status=status.HTTP_400_BAD_REQUEST, + ) assinged_to_users_ids = json.loads(params.get("assigned_to")) for user_id in assinged_to_users_ids: - user = User.objects.filter(id=user_id, company=request.company) + user = User.objects.filter(id=user_id) if user: contact_obj.assigned_to.add(user_id) else: contact_obj.delete() data["assigned_to"] = "Please enter valid user" - return Response({"error": True, "errors": data}) + return Response( + {"error": True, "errors": data}, + status=status.HTTP_400_BAD_REQUEST, + ) assigned_to_list = list( contact_obj.assigned_to.all().values_list("id", flat=True) ) - current_site = get_current_site(self.request) recipients = assigned_to_list send_email_to_assigned_user.delay( recipients, contact_obj.id, - domain=current_site.domain, + domain=settings.Domain, protocol=self.request.scheme, ) @@ -164,7 +179,10 @@ def post(self, request, *args, **kwargs): attachment.contact = contact_obj attachment.attachment = request.FILES.get("contact_attachment") attachment.save() - return Response({"error": False, "message": "Contact created Successfuly"}) + return Response( + {"error": False, "message": "Contact created Successfuly"}, + status=status.HTTP_200_OK, + ) class ContactDetailView(APIView): @@ -182,10 +200,6 @@ def put(self, request, pk, format=None): params = request.query_params if len(request.data) == 0 else request.data contact_obj = self.get_object(pk=pk) address_obj = contact_obj.address - if contact_obj.company != request.company: - return Response( - {"error": True, "errors": "User company doesnot match with header...."} - ) contact_serializer = CreateContactSerializer( data=params, instance=contact_obj, request_obj=request, contact=True @@ -198,7 +212,10 @@ def put(self, request, pk, format=None): data["address_errors"] = (address_serializer.errors,) if data: data["error"] = True - return Response(data) + return Response( + data, + status=status.HTTP_400_BAD_REQUEST, + ) if contact_serializer.is_valid(): if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: @@ -211,7 +228,7 @@ def put(self, request, pk, format=None): "error": True, "errors": "You do not have Permission to perform this action", }, - status=status.HTTP_401_UNAUTHORIZED, + status=status.HTTP_403_FORBIDDEN, ) address_obj = address_serializer.save() contact_obj = contact_serializer.save() @@ -223,31 +240,34 @@ def put(self, request, pk, format=None): if params.get("teams"): teams = json.loads(params.get("teams")) for team in teams: - teams_ids = Teams.objects.filter( - id=team, company=request.company - ) + teams_ids = Teams.objects.filter(id=team) if teams_ids: contact_obj.teams.add(team) else: data["team"] = "Please enter valid Team" - return Response({"error": True, "errors": data}) + return Response( + {"error": True, "errors": data}, + status=status.HTTP_400_BAD_REQUEST, + ) contact_obj.assigned_to.clear() if params.get("assigned_to"): assinged_to_users_ids = json.loads(params.get("assigned_to")) for user_id in assinged_to_users_ids: - user = User.objects.filter(id=user_id, company=request.company) + user = User.objects.filter(id=user_id) if user: contact_obj.assigned_to.add(user_id) else: data["assigned_to"] = "Please enter valid user" - return Response({"error": True, "errors": data}) + return Response( + {"error": True, "errors": data}, + status=status.HTTP_400_BAD_REQUEST, + ) previous_assigned_to_users = list( contact_obj.assigned_to.all().values_list("id", flat=True) ) - current_site = get_current_site(request) assigned_to_list = list( contact_obj.assigned_to.all().values_list("id", flat=True) ) @@ -255,7 +275,7 @@ def put(self, request, pk, format=None): send_email_to_assigned_user.delay( recipients, contact_obj.id, - domain=current_site.domain, + domain=settings.Domain, protocol=request.scheme, ) if request.FILES.get("contact_attachment"): @@ -265,10 +285,13 @@ def put(self, request, pk, format=None): attachment.contact = contact_obj attachment.attachment = request.FILES.get("contact_attachment") attachment.save() - return Response({"error": False, "message": "Contact Updated Successfully"}) + return Response( + {"error": False, "message": "Contact Updated Successfully"}, + status=status.HTTP_200_OK, + ) @swagger_auto_schema( - tags=["contacts"], manual_parameters=swagger_params.contact_detail_get_params + tags=["contacts"], ) def get(self, request, pk, format=None): context = {} @@ -293,7 +316,8 @@ def get(self, request, pk, format=None): { "error": True, "errors": "You do not have Permission to perform this action", - } + }, + status=status.HTTP_403_FORBIDDEN, ) assigned_data = [] for each in contact_obj.assigned_to.all(): @@ -303,11 +327,7 @@ def get(self, request, pk, format=None): assigned_data.append(assigned_dict) if self.request.user.is_superuser or self.request.user.role == "ADMIN": - users_mention = list( - User.objects.filter( - is_active=True, company=self.request.company - ).values("username") - ) + users_mention = list(User.objects.filter(is_active=True).values("username")) elif self.request.user != contact_obj.created_by: users_mention = [{"username": contact_obj.created_by.username}] else: @@ -318,15 +338,11 @@ def get(self, request, pk, format=None): context["address_obj"] = BillingAddressSerializer(contact_obj.address).data context["users"] = UserSerializer( - User.objects.filter(is_active=True, company=self.request.company).order_by( - "email" - ), + User.objects.filter(is_active=True).order_by("email"), many=True, ).data context["countries"] = COUNTRIES - context["teams"] = TeamsSerializer( - Teams.objects.filter(company=request.company), many=True - ).data + context["teams"] = TeamsSerializer(Teams.objects.all(), many=True).data context.update( { "comments": CommentSerializer( @@ -345,7 +361,7 @@ def get(self, request, pk, format=None): return Response(context) @swagger_auto_schema( - tags=["contacts"], manual_parameters=swagger_params.contact_delete_get_params + tags=["contacts"], ) def delete(self, request, pk, format=None): self.object = self.get_object(pk) @@ -353,12 +369,164 @@ def delete(self, request, pk, format=None): self.request.user.role != "ADMIN" and not self.request.user.is_superuser and self.request.user != self.object.created_by - ) or self.object.company != self.request.company: + ): return Response( - {"error": True, "errors": "User company doesnot match with header...."} + { + "error": True, + "errors": "You don't have permission to perform this action.", + }, + status=status.HTTP_403_FORBIDDEN, ) else: if self.object.address_id: self.object.address.delete() self.object.delete() - return Response({"error": False, "message": "Contact Deleted Successfully."}) + return Response( + {"error": False, "message": "Contact Deleted Successfully."}, + status=status.HTTP_200_OK, + ) + + @swagger_auto_schema( + tags=["contacts"], manual_parameters=swagger_params.contact_detail_get_params + ) + def post(self, request, pk, **kwargs): + params = ( + self.request.query_params + if len(self.request.data) == 0 + else self.request.data + ) + context = {} + self.contact_obj = Contact.objects.get(pk=pk) + if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: + if not ( + (self.request.user == self.contact_obj.created_by) + or (self.request.user in self.contact_obj.assigned_to.all()) + ): + return Response( + { + "error": True, + "errors": "You do not have Permission to perform this action", + }, + status=status.HTTP_403_FORBIDDEN, + ) + comment_serializer = CommentSerializer(data=params) + if comment_serializer.is_valid(): + if params.get("comment"): + comment_serializer.save( + contact_id=self.contact_obj.id, + commented_by_id=self.request.user.id, + ) + + if self.request.FILES.get("contact_attachment"): + attachment = Attachments() + attachment.created_by = self.request.user + attachment.file_name = self.request.FILES.get("contact_attachment").name + attachment.contact = self.contact_obj + attachment.attachment = self.request.FILES.get("contact_attachment") + attachment.save() + + comments = Comment.objects.filter(contact__id=self.contact_obj.id).order_by( + "-id" + ) + attachments = Attachments.objects.filter( + contact__id=self.contact_obj.id + ).order_by("-id") + context.update( + { + "contact_obj": ContactSerializer(self.contact_obj).data, + "attachments": AttachmentsSerializer(attachments, many=True).data, + "comments": CommentSerializer(comments, many=True).data, + } + ) + return Response(context) + + +class ContactCommentView(APIView): + model = Comment + authentication_classes = (JSONWebTokenAuthentication,) + permission_classes = (IsAuthenticated,) + + def get_object(self, pk): + return self.model.objects.get(pk=pk) + + @swagger_auto_schema( + tags=["contacts"], manual_parameters=swagger_params.contact_comment_edit_params + ) + def put(self, request, pk, format=None): + params = request.query_params if len(request.data) == 0 else request.data + obj = self.get_object(pk) + if ( + request.user.role == "ADMIN" + or request.user.is_superuser + or request.user == obj.commented_by + ): + serializer = CommentSerializer(obj, data=params) + if params.get("comment"): + if serializer.is_valid(): + serializer.save() + return Response( + {"error": False, "message": "Comment Submitted"}, + status=status.HTTP_200_OK, + ) + return Response( + {"error": True, "errors": serializer.errors}, + status=status.HTTP_400_BAD_REQUEST, + ) + else: + return Response( + { + "error": True, + "errors": "You don't have permission to edit this Comment", + }, + status=status.HTTP_403_FORBIDDEN, + ) + + @swagger_auto_schema(tags=["contacts"]) + def delete(self, request, pk, format=None): + self.object = self.get_object(pk) + if ( + request.user.role == "ADMIN" + or request.user.is_superuser + or request.user == self.object.commented_by + ): + self.object.delete() + return Response( + {"error": False, "message": "Comment Deleted Successfully"}, + status=status.HTTP_200_OK, + ) + else: + return Response( + { + "error": True, + "errors": "You don't have permission to perform this action", + }, + status=status.HTTP_403_FORBIDDEN, + ) + + +class ContactAttachmentView(APIView): + model = Attachments + authentication_classes = (JSONWebTokenAuthentication,) + permission_classes = (IsAuthenticated,) + + @swagger_auto_schema(tags=["contacts"]) + def delete(self, request, pk, format=None): + self.object = self.model.objects.get(pk=pk) + if ( + request.user.role == "ADMIN" + or request.user.is_superuser + or request.user == self.object.created_by + ): + self.object.delete() + return Response( + {"error": False, "message": "Attachment Deleted Successfully"}, + status=status.HTTP_200_OK, + ) + else: + return Response( + { + "error": True, + "errors": "You don't have permission to delete this Attachment", + }, + status=status.HTTP_403_FORBIDDEN, + ) diff --git a/contacts/forms.py b/contacts/forms.py deleted file mode 100644 index d95ce7f..0000000 --- a/contacts/forms.py +++ /dev/null @@ -1,58 +0,0 @@ -from django import forms -from contacts.models import Contact -from common.models import Comment, Attachments -from teams.models import Teams - - -class ContactForm(forms.ModelForm): - teams_queryset = [] - teams = forms.MultipleChoiceField(choices=teams_queryset) - - def __init__(self, *args, **kwargs): - assigned_users = kwargs.pop("assigned_to", []) - super(ContactForm, self).__init__(*args, **kwargs) - for field in self.fields.values(): - field.widget.attrs = {"class": "form-control"} - self.fields["description"].widget.attrs.update({"rows": "6"}) - if assigned_users: - self.fields["assigned_to"].queryset = assigned_users - self.fields["assigned_to"].required = False - - for key, value in self.fields.items(): - if key == "phone": - pass - else: - value.widget.attrs["placeholder"] = value.label - self.fields["teams"].choices = [ - (team.get("id"), team.get("name")) - for team in Teams.objects.all().values("id", "name") - ] - self.fields["teams"].required = False - - class Meta: - model = Contact - fields = ( - "assigned_to", - "first_name", - "last_name", - "email", - "phone", - "address", - "description", - ) - - -class ContactCommentForm(forms.ModelForm): - comment = forms.CharField(max_length=255, required=True) - - class Meta: - model = Comment - fields = ("comment", "contact", "commented_by") - - -class ContactAttachmentForm(forms.ModelForm): - attachment = forms.FileField(max_length=1001, required=True) - - class Meta: - model = Attachments - fields = ("attachment", "contact") diff --git a/contacts/migrations/0006_remove_contact_company.py b/contacts/migrations/0006_remove_contact_company.py new file mode 100644 index 0000000..ad965df --- /dev/null +++ b/contacts/migrations/0006_remove_contact_company.py @@ -0,0 +1,17 @@ +# Generated by Django 3.1.7 on 2021-03-23 14:25 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("contacts", "0005_contact_company"), + ] + + operations = [ + migrations.RemoveField( + model_name="contact", + name="company", + ), + ] diff --git a/contacts/models.py b/contacts/models.py index b2da3ed..4192c4d 100644 --- a/contacts/models.py +++ b/contacts/models.py @@ -2,7 +2,7 @@ from django.db import models from django.utils.translation import ugettext_lazy as _ -from common.models import Address, User, Company +from common.models import Address, User from phonenumber_field.modelfields import PhoneNumberField from teams.models import Teams @@ -28,10 +28,6 @@ class Contact(models.Model): is_active = models.BooleanField(default=False) teams = models.ManyToManyField(Teams, related_name="contact_teams") - company = models.ForeignKey( - Company, on_delete=models.SET_NULL, null=True, blank=True - ) - def __str__(self): return self.first_name diff --git a/contacts/serializer.py b/contacts/serializer.py index ae40c64..be8a084 100644 --- a/contacts/serializer.py +++ b/contacts/serializer.py @@ -2,7 +2,6 @@ from contacts.models import Contact from common.serializer import ( UserSerializer, - CompanySerializer, BillingAddressSerializer, AttachmentsSerializer, ) @@ -11,7 +10,6 @@ class ContactSerializer(serializers.ModelSerializer): created_by = UserSerializer() - company = CompanySerializer() teams = TeamsSerializer(read_only=True, many=True) assigned_to = UserSerializer(read_only=True, many=True) address = BillingAddressSerializer(read_only=True) @@ -36,7 +34,6 @@ class Meta: "created_on", "is_active", "teams", - "company", "created_on_arrow", "get_team_users", "get_team_and_assigned_users", @@ -50,14 +47,10 @@ def __init__(self, *args, **kwargs): request_obj = kwargs.pop("request_obj", None) super(CreateContactSerializer, self).__init__(*args, **kwargs) - self.company = request_obj.company - def validate_first_name(self, first_name): if self.instance: if ( - Contact.objects.filter( - first_name__iexact=first_name, company=self.company - ) + Contact.objects.filter(first_name__iexact=first_name) .exclude(id=self.instance.id) .exists() ): @@ -66,9 +59,7 @@ def validate_first_name(self, first_name): ) else: - if Contact.objects.filter( - first_name__iexact=first_name, company=self.company - ).exists(): + if Contact.objects.filter(first_name__iexact=first_name).exists(): raise serializers.ValidationError( "Contact already exists with this name" ) diff --git a/contacts/swagger_params.py b/contacts/swagger_params.py index 8991e5d..661b39c 100644 --- a/contacts/swagger_params.py +++ b/contacts/swagger_params.py @@ -1,23 +1,12 @@ from drf_yasg import openapi -company_params_in_header = openapi.Parameter( - "company", openapi.IN_HEADER, required=True, type=openapi.TYPE_STRING -) - - contact_list_get_params = [ - company_params_in_header, openapi.Parameter("name", openapi.IN_QUERY, type=openapi.TYPE_STRING), openapi.Parameter("city", openapi.IN_QUERY, type=openapi.TYPE_STRING), openapi.Parameter("assigned_to", openapi.IN_QUERY, type=openapi.TYPE_STRING), ] -contact_detail_get_params = [company_params_in_header] - -contact_delete_get_params = [company_params_in_header] - contact_create_post_params = [ - company_params_in_header, openapi.Parameter( "first_name", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING ), @@ -41,3 +30,16 @@ openapi.Parameter("description", openapi.IN_QUERY, type=openapi.TYPE_STRING), openapi.Parameter("contact_attachment", openapi.IN_QUERY, type=openapi.TYPE_FILE), ] + +contact_detail_get_params = [ + openapi.Parameter( + "contact_attachment", + openapi.IN_QUERY, + type=openapi.TYPE_FILE, + ), + openapi.Parameter("comment", openapi.IN_QUERY, type=openapi.TYPE_STRING), +] + +contact_comment_edit_params = [ + openapi.Parameter("comment", openapi.IN_QUERY, type=openapi.TYPE_STRING), +] diff --git a/contacts/tasks.py b/contacts/tasks.py index f82cf97..3dd3a15 100644 --- a/contacts/tasks.py +++ b/contacts/tasks.py @@ -5,7 +5,6 @@ from common.models import User from contacts.models import Contact -from marketing.models import BlockedDomain, BlockedEmail app = Celery("redis://") @@ -16,32 +15,22 @@ def send_email_to_assigned_user( ): """ Send Mail To Users When they are assigned to a contact """ contact = Contact.objects.get(id=contact_id) - blocked_domains = BlockedDomain.objects.values_list("domain", flat=True) - blocked_emails = BlockedEmail.objects.values_list("email", flat=True) created_by = contact.created_by for user in recipients: recipients_list = [] user = User.objects.filter(id=user, is_active=True).first() if user: - if (user.email not in blocked_emails) and ( - user.email.split("@")[-1] not in blocked_domains - ): - recipients_list.append(user.email) - context = {} - context["url"] = ( - protocol - + "://" - + domain - + reverse("contacts:view_contact", args=(contact.id,)) - ) - context["user"] = user - context["contact"] = contact - context["created_by"] = created_by - subject = "Assigned a contact for you." - html_content = render_to_string( - "assigned_to/contact_assigned.html", context=context - ) + recipients_list.append(user.email) + context = {} + context["url"] = protocol + "://" + domain + context["user"] = user + context["contact"] = contact + context["created_by"] = created_by + subject = "Assigned a contact for you." + html_content = render_to_string( + "assigned_to/contact_assigned.html", context=context + ) - msg = EmailMessage(subject, html_content, to=recipients_list) - msg.content_subtype = "html" - msg.send() + msg = EmailMessage(subject, html_content, to=recipients_list) + msg.content_subtype = "html" + msg.send() diff --git a/contacts/templates/contacts.html b/contacts/templates/contacts.html deleted file mode 100644 index b11d67f..0000000 --- a/contacts/templates/contacts.html +++ /dev/null @@ -1,308 +0,0 @@ -{% extends 'sales/base.html' %} -{% load static %} -{% load paginate %} -{% load thumbnail %} -{% block extralinks %} - -{% endblock %} -{% block content %} - -
      - - -
      -
      -
      -
      -
      -
      -
      Filters
      -
      -
      -
      - - -
      -
      -
      -
      - - -
      -
      -
      -
      - - -
      -
      -
      -
      - - Clear -
      -
      -
      -
      -
      -
      -
      -
      -
      - - -
      -
      -
      -
      -
      - - Contacts - {% if show_pageitems %} {% show_pageitems %}{% else %} - {{contact_obj_list|length}}{% endif %} - - - - - -
      -
      - - - {% if contact_obj_list|length > 0 %} - - - - - - - - - - {% endif %} - - - {% if per_page %} - {% paginate per_page contact_obj_list %} - {% else%} - {% paginate 10 contact_obj_list %} - {% endif %} - {% for contact in contact_obj_list %} - - - - - - - - - - {% endfor%} - -
      S.noNameAssigned ToCityStateCreated OnActions
      {{ forloop.counter }}{{contact.first_name}} - {{contact.last_name}} - {% with contact_users=contact.get_team_and_assigned_users %} - {% for user in contact_users %} - {% if user.profile_pic %} - {% thumbnail user.profile_pic "40x40" crop="center" as im %} - - - - {% endthumbnail %} - {% else %} - - - - {% endif %} - {% empty %} - None - {% endfor %} - {% endwith %} - - {% if contact.address.city %} - {{contact.address.city}} - {% else %} - Not Specified - {% endif %} - - {% if contact.address.state %} - {{contact.address.state}} - {% else %} - Not Specified - {% endif %} - {{contact.created_on_arrow}} - - - {% if request.user == contact.created_by or request.user.role == "ADMIN" or request.user.is_superuser %} - - {% endif %} -
      -
      - {%ifequal contact_obj_list|length 0 %} -
      No Contact Records Found
      - {%endifequal%} -
      - {% show_pages %} -
      -
      -
      -
      -
      -
      - -
      - - - -{% for contact_record in contact_obj_list %} - - - -{% endfor %} - - - -{%endblock%} -{% block js_block %} - -{% endblock js_block %} diff --git a/contacts/templates/contacts_list.html b/contacts/templates/contacts_list.html deleted file mode 100644 index c8c878f..0000000 --- a/contacts/templates/contacts_list.html +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - {% ifequal contacts|length 0 %} - - - - {% endifequal %} - {% for contact in contacts %} - - - - - {% endfor %} - -
      - - Name - - - - - Email - -
      - NO CONTACTS FOUND!! -
      - - {{ contact.name }} - - - {{ contact.email }} -
      \ No newline at end of file diff --git a/contacts/templates/create_contact.html b/contacts/templates/create_contact.html deleted file mode 100644 index adf11bd..0000000 --- a/contacts/templates/create_contact.html +++ /dev/null @@ -1,442 +0,0 @@ -{% extends 'sales/base.html' %} -{% load static %} -{% block breadcrumb %} - - -{% endblock %} -{% block content %} -
      -
      -
      -
      -
      -
      - {% if contact_obj %}EDIT{% else %}CREATE{% endif %} CONTACT -
      -
      -
      -
      -
      -
      -
      - - {{ contact_form.first_name }} - {{ contact_form.first_name.errors }} -
      -
      - - {{ contact_form.last_name }} - {{ contact_form.last_name.errors }} -
      -
      -
      -
      -
      -
      - - {{ contact_form.phone }} - {{ contact_form.phone.errors }} -
      -
      -
      -
      - - {{ contact_form.email }} - {{ contact_form.email.errors }} -
      -
      - {% if request.user.is_superuser or request.user.role == 'ADMIN' %} -
      -
      - - - {{ contact_form.teams.errors }} -
      -
      - -
      -
      - - -
      -
      - - {% endif %} -
      -
      -
      -
      - - - {{ contact_form.assigned_to.errors }} -
      -
      -
      -
      - - {{ address_form.address_line }} - {{ address_form.address_line.errors }} -
      - {{ address_form.street }} - {{ address_form.street.errors }} -
      -
      - {{ address_form.city }} - {{ address_form.city.errors }} -
      -
      - {{ address_form.state }} - {{ address_form.state.errors }} -
      -
      - {{ address_form.postcode }} - {{ address_form.postcode.errors }} -
      -
      - {{ address_form.country }} - {{ address_form.country.errors }} -
      -
      -
      -
      -
      -
      -
      -
      - - {{ contact_form.description }} - {{ contact_form.description.errors }} -
      -
      -
      -
      - - - {% if contact_obj.contact_attachment.count %} - {% for attachment in contact_obj.contact_attachment.all %} -
      - {{ attachment.file_name }} - {% if not attachment.created_by.role == 'ADMIN' or attachment.created_by.role == request.user.role %} - X - {% endif %} -
      - {% endfor %} - {% endif %} - -
      -
      -
      - - -
      -
      - - {% if not contact_obj %} - - {% endif %} - Cancel -
      -
      -
      -
      -
      -
      -
      -
      -{% endblock %} -{% block js_block %} - - - - -{% endblock js_block %} \ No newline at end of file diff --git a/contacts/templates/view_contact.html b/contacts/templates/view_contact.html deleted file mode 100644 index 9dd2d97..0000000 --- a/contacts/templates/view_contact.html +++ /dev/null @@ -1,507 +0,0 @@ -{% extends 'sales/base.html' %} -{% load static %} -{% load thumbnail %} -{% block breadcrumb %} -{% block extralinks %} - - -{% endblock extralinks %} - -{% endblock %} -{% block content %} - -
      -
      -
      -
      - -
      - -
      -
      - Overview - - - -
      -
      - -
      -
      -
      -
      - -
      {{ contact_record.first_name }} - {{ contact_record.last_name }}
      -
      -
      -
      -
      - -
      {{ contact_record.phone }}
      -
      -
      - -
      -
      -
      -
      - -
      {{ contact_record.email }}
      -
      -
      -
      -
      -
      -
      - {% if contact_record.address.address_line or contact_record.address.street or contact_record.address.city or contact_record.address.state or contact_record.address.postcode or contact_record.address.country %} - -
      - {{contact_record.address.get_complete_address}} -
      - {% endif %} -
      -
      -
      -
      - {% if contact_record.description %} - -
      {{ contact_record.description }} -
      - {% endif %} -
      -
      -
      -
      -
      - Created by {{ contact_record.created_by }} created on - {{ contact_record.created_on_arrow }} -
      -
      -
      -
      - - -
      -
      -
      -
      Attachments
      -
      -
      -
      -
      -
      - -
      - -
      -
      -
      - -
      -
      - -
      -
        - {% for attachment in attachments %} -
      • - {% if request.user.is_superuser or request.user.role == 'ADMIN' or request.user == attachment.created_by %} -
        -
        - -
        -
        - {% endif %} - -
        - {% if attachment.attachment %} - {% if 'image' in attachment.file_type %} - {% thumbnail attachment.attachment "80x80" crop="center" as im %} - - {% endthumbnail %} - {% endif %} - {% endif %} -
         {{attachment.file_name}}  Download
        -
        - -
        -
        Uploaded by :{{ attachment.created_by }}
        -
        {{ attachment.created_on_arrow }}
        -
        -
      • - {% endfor %} -
      -
      -
      -
      - - - - -
      -
      -
      Comments
      -
      -
      -
      -
      -
      - -
      - -
      -
      -
      - -
      -
      - -
      -
        - {% for comment in comments %} -
      • - {% if request.user.is_superuser or request.user.role == 'ADMIN' or request.user == comment.commented_by %} -
        -
        - - -
        -
        - {% endif %} -
        -
        {{ comment.comment }}
        -
        -
        -
        {{ comment.commented_by }}
        -
        {{ comment.commented_on_arrow }}
        -
        -
      • - {% endfor %} -
      -
      -
      - -
      - -
      -
      -
      -
      -
      -
      -
      -
      -
      - Tasks - -
      -
      - - {% if tasks|length > 0 %} - - - - - - - - - - {% endif %} - - {% for task in tasks %} - - - - - - - - {% endfor %} - -
      S.NoTitleStatusPriorityActions
      {{ forloop.counter }}{{task.title}}{{task.status}}{{task.priority}} {% if task.probability %} % {% endif %} - View - Edit - Remove -
      -
      - {% ifequal tasks|length 0 %} -
      No tasks Records Found
      - {% endifequal %} -
      -
      -
      -
      -
      -
      -
      -
      - -
      - Processing File... -
      -
      -
      - - {% endblock%} - {% block js_block %} - - - - {% endblock js_block %} \ No newline at end of file diff --git a/contacts/tests.py b/contacts/tests.py deleted file mode 100644 index b5ea69b..0000000 --- a/contacts/tests.py +++ /dev/null @@ -1,670 +0,0 @@ -from django.core.files.uploadedfile import SimpleUploadedFile -from django.test import Client, TestCase -from django.urls import reverse -from django.utils.encoding import force_text - -from accounts.models import Account -from cases.models import Case -from common.models import Address, Attachments, Comment, User, Company -from contacts.forms import ContactAttachmentForm -from contacts.models import Contact -from teams.models import Teams - - -class ContactObjectsCreation(object): - def setUp(self): - self.client = Client() - self.company, _ = Company.objects.get_or_create( - name="test company", address="IN", sub_domain="test", country="IN" - ) - self.user = User.objects.create( - first_name="johnContact", - username="johnDoeContact", - email="johnContact@example.com", - role="ADMIN", - company=self.company, - ) - self.user.set_password("password") - self.user.save() - self.address = Address.objects.create( - street="street", - city="city name", - state="state name", - postcode=12345, - country="IN", - ) - - self.contact = Contact.objects.create( - first_name="contact", - email="contact@example.com", - phone="12345", - address=self.address, - description="contact", - created_by=self.user, - ) - self.contact.assigned_to.add(self.user) - self.case = Case.objects.create( - name="jane doe case", - case_type="Problem", - status="New", - priority="Low", - description="description for case", - created_by=self.user, - closed_on="2016-05-04", - ) - self.comment = Comment.objects.create( - comment="test comment", case=self.case, commented_by=self.user - ) - self.attachment = Attachments.objects.create( - attachment="image.png", case=self.case, created_by=self.user - ) - - self.user_contacts_mp = User.objects.create( - first_name="janeUser@example.com", - username="janeUserContact", - email="janeUser@example.com", - role="USER", - has_sales_access=True, - company=self.company, - ) - self.user_contacts_mp.set_password("password") - self.user_contacts_mp.save() - - self.client.login(username="johnContact@example.com", password="password") - - -class ContactObjectsCreation_Count(ContactObjectsCreation, TestCase): - def test_contact_object_creation(self): - c = Contact.objects.count() - con = Contact.objects.filter(id=self.contact.id) - # print(self.contact.first_name) - self.assertEqual(str(con.last()), self.contact.first_name) - self.assertEqual(c, 1) - - def test_address_object_creation(self): - c = Address.objects.count() - self.assertEqual(c, 1) - - -class ContactViewsTestCase(ContactObjectsCreation, TestCase): - def test_contacts_list_page(self): - response = self.client.get(reverse("contacts:list")) - self.assertEqual(response.status_code, 200) - if response.status_code == 200: - self.assertEqual( - response.context["contact_obj_list"][0].id, self.contact.id - ) - self.assertTrue(response.context["contact_obj_list"]) - - def test_contacts_list_html(self): - response = self.client.get(reverse("contacts:list")) - self.assertTemplateUsed(response, "contacts.html") - - def test_contacts_create(self): - upload_file = open("static/images/user.png", "rb") - response = self.client.post( - "/contacts/create/", - { - "first_name": "john contact", - "last_name": "doe", - "email": "johnDoeContact@example.com", - "phone": "+911234567892", - "address": self.address.id, - "description": "contact", - "created_by": self.user, - "assigned_to": str(self.user.id), - "contact_attachment": SimpleUploadedFile( - upload_file.name, upload_file.read() - ), - }, - ) - self.assertEqual(response.status_code, 302) - - def test_contact_create(self): - upload_file = open("static/images/user.png", "rb") - response = self.client.post( - "/contacts/create/", - { - "first_name": "janeDoe", - "last_name": "contact doe", - "email": "janeDoeContact@example.com", - "phone": "+911234567892", - "address": self.address.id, - "description": "contact", - "created_by": self.user, - "assigned_to": str(self.user.id), - "contact_attachment": SimpleUploadedFile( - upload_file.name, upload_file.read() - ), - }, - ) - self.assertEqual(response.status_code, 302) - - def test_update_contact(self): - upload_file = open("static/images/user.png", "rb") - url = "/contacts/" + str(self.contact.id) + "/edit/" - data = { - "first_name": "john Contact", - "last_name": "doe", - "email": "johnDoeContact@example.com", - "phone": "+911234561255", - "address": self.address.id, - "description": "contact", - "created_by": self.user, - "assigned_to": str(self.user.id), - "contact_attachment": SimpleUploadedFile( - upload_file.name, upload_file.read() - ), - } - response = self.client.post(url, data) - self.assertEqual(response.status_code, 302) - - def test_contacts_create_html(self): - response = self.client.post( - "/contacts/create/", - { - "name": "contact", - "email": "contact@example.com", - "phone": "12345", - "address": self.address, - "description": "contact", - }, - ) - self.assertTemplateUsed(response, "create_contact.html") - - def test_contacts_delete(self): - Contact.objects.filter(id=self.contact.id).delete() - response = self.client.get(reverse("contacts:list")) - self.assertEqual(response.status_code, 200) - - def test_contacts_delete_get(self): - response = self.client.get("/contacts/" + str(self.contact.id) + "/delete/") - self.assertEqual(response.status_code, 302) - - def test_contacts_delete_location_checking(self): - response = self.client.post("/contacts/" + str(self.contact.id) + "/delete/") - self.assertEqual(response["location"], "/contacts/") - - def test_contacts_edit(self): - response = self.client.post( - "/contacts/" + str(self.contact.id) + "/edit/", - { - "name": "contact name", - "email": "contact@example.com", - "phone": "12345", - "pk": self.contact.id, - "address": self.address.id, - }, - ) - self.assertEqual(response.status_code, 200) - - def test_contacts_edit_html(self): - response = self.client.post( - "/contacts/" + str(self.contact.id) + "/edit/", - { - "name": "contact Name", - "email": "contact@example.com", - "phone": "12345", - "pk": self.contact.id, - "address": self.address.id, - }, - ) - self.assertTemplateUsed(response, "create_contact.html") - - def test_contacts_view(self): - response = self.client.get("/contacts/" + str(self.contact.id) + "/view/") - self.assertEqual(response.status_code, 200) - self.assertEqual(response.context["contact_record"].id, self.contact.id) - - def test_contacts_view_html(self): - response = self.client.get("/contacts/" + str(self.contact.id) + "/view/") - self.assertTemplateUsed(response, "view_contact.html") - - def test_contacts_edit_post(self): - response = self.client.get("/contacts/" + str(self.contact.id) + "/edit/") - self.assertEqual(response.status_code, 200) - - -class ContactsListTestCase(ContactObjectsCreation, TestCase): - def test_contacts_list(self): - self.contacts = Contact.objects.all() - response = self.client.get(reverse("contacts:list")) - self.assertEqual(response.status_code, 200) - self.assertTemplateUsed(response, "contacts.html") - - def test_contacts_list_queryset(self): - data = { - "fist_name": "jane contact", - "city": "city name", - "phone": "12345", - "email": "contact@example.com", - "assigned_to": str(self.user.id), - } - response = self.client.post(reverse("contacts:list"), data) - - self.assertEqual(response.status_code, 200) - self.assertTemplateUsed(response, "contacts.html") - - def test_contacts_list_user_role(self): - self.client.login(username="janeUser@example.com", password="password") - self.contact = Contact.objects.create( - first_name="jane contact", - email="janecontact@example.com", - created_by=self.user_contacts_mp, - ) - response = self.client.get(reverse("contacts:list")) - self.assertEqual(response.status_code, 200) - self.contact.delete() - - response = self.client.post( - reverse("contacts:list"), - {"first_name": "john contact", "assigned_to": str(self.user.id)}, - ) - self.assertEqual(response.status_code, 200) - - -class CommentTestCase(ContactObjectsCreation, TestCase): - def test_comment_add(self): - response = self.client.post( - "/contacts/comment/add/", {"contactid": self.contact.id} - ) - self.assertEqual(response.status_code, 200) - - # def test_GetContactsView(self): - # response = self.client.get('/get/list/') - # # self.assertEqual(response.status_code, 200) - # self.assertIsNone(response.context['contacts']) - - def test_comment_edit(self): - response = self.client.post( - "/contacts/comment/edit/", {"commentid": self.comment.id} - ) - self.assertEqual(response.status_code, 200) - resp = self.client.post( - "/contacts/comment/edit/", - {"commentid": self.comment.id, "comment": "test comment"}, - ) - self.assertEqual(resp.status_code, 200) - - def test_comment_delete(self): - response = self.client.post( - "/contacts/comment/remove/", {"comment_id": self.comment.id} - ) - self.assertEqual(response.status_code, 200) - - def test_form_valid(self): - response = self.client.post( - "/contacts/comment/add/", - {"contactid": self.contact.id, "comment": "test comment"}, - ) - # print(response , "response") - self.assertEqual(response.status_code, 200) - - -class AttachmentTestCase(ContactObjectsCreation, TestCase): - def test_attachment_add(self): - response = self.client.post( - "/contacts/attachment/add/", {"contactid": self.contact.id} - ) - self.assertEqual(response.status_code, 200) - - def test_attachment_valid(self): - upload_file = open("static/images/user.png", "rb") - response = self.client.post( - "/contacts/attachment/add/", - { - "contactid": self.contact.id, - "attachment": SimpleUploadedFile(upload_file.name, upload_file.read()), - }, - ) - self.assertEqual(response.status_code, 200) - - def test_attachment_delete(self): - response = self.client.post( - "/contacts/attachment/remove/", {"attachment_id": self.attachment.id} - ) - self.assertEqual(response.status_code, 200) - - -class TestContactCreateContact(ContactObjectsCreation, TestCase): - def test_create_new_contact(self): - upload_file = open("static/images/user.png", "rb") - response = self.client.post( - "/contacts/create/", - { - "first_name": "john doe contact", - "last_name": "doe", - "email": "johnDContact@example.com", - "phone": "+911234561256", - "address": self.address.id, - "description": "contact", - "created_by": self.user, - "assigned_to": str(self.user.id), - "savenewform": True, - "address_line": "address line", - }, - ) - self.assertEqual(response.status_code, 302) - - def test_contact_detail_view_error(self): - self.client.login(username="janeUser@example.com", password="password") - self.contact = Contact.objects.create(created_by=self.user) - - def test_contact_update_view(self): - self.client.login(username="johnContact@example.com", password="password") - response = self.client.post( - reverse("contacts:edit_contact", args=(self.contact.id,)), - { - "first_name": "first name", - "last_name": "last name", - "phone": "232323", - "email": "email@email.com", - "assigned_to": str(self.user.id), - }, - ) - self.assertEqual(200, response.status_code) - - def test_contact_update_view_assigned_Users(self): - self.client.login(username="johnContact@example.com", password="password") - response = self.client.post( - reverse("contacts:edit_contact", args=(self.contact.id,)), - { - "first_name": "first name", - "last_name": "last name", - "phone": "232323", - "email": "email@email.com", - "assigned_to": str(self.user_contacts_mp.id), - }, - ) - self.assertEqual(200, response.status_code) - - response = self.client.post( - reverse("contacts:edit_contact", args=(self.contact.id,)), - { - "first_name": "first name", - "last_name": "last name", - "phone": "232323", - "email": "email@email.com", - }, - ) - self.assertEqual(200, response.status_code) - - def test_contact_update_view_error(self): - self.usermp1 = User.objects.create( - first_name="janeDoe@example.com", - username="janeDoe", - email="janeDoe@example.com", - role="USER", - is_active=True, - has_sales_access=True, - company=self.company, - ) - self.usermp1.set_password("password") - self.usermp1.save() - self.contact = Contact.objects.create( - first_name="jane doe contact", - email="contactJaneDoe@example.com", - created_by=self.user_contacts_mp, - ) - self.client.login(username="janeDoe@example.com", password="password") - response = self.client.get( - reverse("contacts:edit_contact", args=(self.contact.id,)), {} - ) - self.assertEqual(403, response.status_code) - - response = self.client.post( - reverse("contacts:remove_contact", args=(self.contact.id,)), - {"pk": self.contact.id}, - ) - self.assertEqual(403, response.status_code) - self.contact.delete() - - self.contact = Contact.objects.create(created_by=self.user) - response = self.client.post( - "/contacts/comment/add/", {"contactid": self.contact.id} - ) - self.assertJSONEqual( - force_text(response.content), - {"error": "You don't have permission to comment."}, - ) - - response = self.client.post( - "/contacts/comment/edit/", {"commentid": self.comment.id} - ) - self.assertJSONEqual( - force_text(response.content), - {"error": "You don't have permission to edit this comment."}, - ) - - response = self.client.post( - "/contacts/comment/remove/", {"comment_id": self.comment.id} - ) - self.assertJSONEqual( - force_text(response.content), - {"error": "You don't have permission to delete this comment."}, - ) - - response = self.client.post( - "/contacts/attachment/add/", {"contactid": self.contact.id} - ) - self.assertJSONEqual( - force_text(response.content), - {"error": "You don't have permission to add attachment."}, - ) - - self.attachment = Attachments.objects.create( - attachment="image.png", case=self.case, created_by=self.user - ) - response = self.client.post( - "/contacts/attachment/remove/", {"attachment_id": self.attachment.id} - ) - self.assertJSONEqual( - force_text(response.content), - {"error": "You don't have permission to delete this attachment."}, - ) - - -class TestContactViews(ContactObjectsCreation, TestCase): - def test_create_contact(self): - self.client.logout() - self.client.login(username="janeUser@example.com", password="password") - response = self.client.get(reverse("contacts:list"), {}) - self.assertEqual(200, response.status_code) - - self.client.logout() - self.client.login(username="johnContact@example.com", password="password") - self.account_by_user = Account.objects.create( - name="account edit", - email="johndoe@example.com", - phone="123456789", - billing_address_line="", - billing_street="street name", - billing_city="city name", - billing_state="state", - billing_postcode="1234", - billing_country="US", - website="www.example.como", - created_by=self.user, - status="open", - industry="SOFTWARE", - description="Testing", - ) - self.teams_contacts = Teams.objects.create(name="teams contacts") - self.teams_contacts.users.add(self.user) - data = { - "first_name": "first name", - "last_name": "last name", - "phone": "+91-123-456-7854", - "email": "example@user.com", - "teams": [ - self.teams_contacts.id, - ], - } - response = self.client.post( - reverse("contacts:add_contact") - + "?view_account={}&address_form=".format(self.account_by_user.id), - data, - ) - self.assertEqual(302, response.status_code) - - data = { - "first_name": "first name", - "last_name": "last name", - "phone": "+91-123-456-7858", - "email": "example@mail.com", - "teams": [ - self.teams_contacts.id, - ], - } - response = self.client.post( - reverse("contacts:add_contact") - + "?view_account={}".format(self.account_by_user.id), - data, - HTTP_X_REQUESTED_WITH="XMLHttpRequest", - ) - self.assertEqual(200, response.status_code) - - data = { - "first_name": "first name", - "last_name": "last name", - "phone": "+91-123-456-7854", - "email": "example@user", - "teams": [ - self.teams_contacts.id, - ], - } - response = self.client.post( - reverse("contacts:add_contact") - + "?view_account={}".format(self.account_by_user.id), - data, - HTTP_X_REQUESTED_WITH="XMLHttpRequest", - ) - self.assertEqual(200, response.status_code) - response = self.client.get(reverse("contacts:add_contact") + "?address_form=") - self.assertEqual(200, response.status_code) - - response = self.client.post( - reverse("contacts:edit_contact", args=(self.contact.id,)), - { - "first_name": "contact", - "last_name": "contact@example.com", - "phone": "+91-123-456-7856", - "email": "contact@example.com", - "teams": [ - self.teams_contacts.id, - ], - }, - ) - self.assertEqual(302, response.status_code) - - self.user_contacts_mp = User.objects.create( - first_name="joeUser@contact.com", - username="joeUser@contact.com", - email="joeUser@contact.com", - role="USER", - has_sales_access=True, - company=self.company, - ) - self.user_contacts_mp.set_password("password") - self.user_contacts_mp.save() - - self.client.logout() - self.client.login(username="joeUser@contact.com", password="password") - response = self.client.get( - reverse("contacts:view_contact", args=(self.contact.id,)) - ) - self.assertEqual(403, response.status_code) - - self.client.logout() - self.client.login(username="janeUser@example.com", password="password") - response = self.client.get( - reverse("contacts:view_contact", args=(self.contact.id,)) - ) - # self.assertEqual(403, response.status_code) - - self.client.logout() - self.client.login(username="johnContact@example.com", password="password") - self.teams_contacts.users.add(self.user) - data = { - "first_name": "contact", - "last_name": "contact", - "phone": "+91-123-456-7852", - "email": "contact@example.com", - "teams": [ - self.teams_contacts.id, - ], - } - response = self.client.post( - reverse("contacts:edit_contact", args=(self.contact.id,)) - + "?from_account={}".format(self.account_by_user.id), - data, - ) - self.assertEqual(302, response.status_code) - response = self.client.post( - reverse("contacts:edit_contact", args=(self.contact.id,)) - + "?from_account={}&address_form=".format(self.account_by_user.id), - data, - HTTP_X_REQUESTED_WITH="XMLHttpRequest", - ) - - self.assertEqual(200, response.status_code) - - data = { - "first_name": "contact", - "last_name": "contact", - "phone": "+91-123-456", - "email": "contact@example", - "teams": [ - self.teams_contacts.id, - ], - } - response = self.client.post( - reverse("contacts:edit_contact", args=(self.contact.id,)) - + "?from_account={}".format(self.account_by_user.id), - data, - HTTP_X_REQUESTED_WITH="XMLHttpRequest", - ) - self.assertEqual(200, response.status_code) - - response = self.client.post( - reverse("contacts:edit_contact", args=(self.contact.id,)) - + "?from_account={}".format(self.account_by_user.id), - data, - ) - self.assertEqual(200, response.status_code) - - self.client.logout() - self.client.login(username="johnContact@example.com", password="password") - self.contact_delete = Contact.objects.create( - first_name="contact", - email="contact_delete@example.com", - phone="12345", - address=self.address, - description="contact", - created_by=self.user, - ) - response = self.client.post( - reverse("contacts:remove_contact", args=(self.contact_delete.id,)), - {"pk": self.contact_delete.id}, - HTTP_X_REQUESTED_WITH="XMLHttpRequest", - ) - self.assertEqual(200, response.status_code) - - self.contact_edit = Contact.objects.create( - first_name="contact", - email="contact_edit@example.com", - phone="12345", - description="contact", - created_by=self.user_contacts_mp, - ) - - self.client.logout() - self.client.login(username="joeUser@contact.com", password="password") - response = self.client.get( - reverse("contacts:view_contact", args=(self.contact_edit.id,)), - {"pk": self.contact_edit.id}, - HTTP_X_REQUESTED_WITH="XMLHttpRequest", - ) - self.assertEqual(200, response.status_code) - response = self.client.get(reverse("contacts:add_contact")) - self.assertEqual(200, response.status_code) diff --git a/contacts/urls.py b/contacts/urls.py deleted file mode 100644 index a803e55..0000000 --- a/contacts/urls.py +++ /dev/null @@ -1,35 +0,0 @@ -from django.urls import path -from contacts.views import ( - ContactsListView, - CreateContactView, - ContactDetailView, - UpdateContactView, - RemoveContactView, - get_teams_and_users, - GetContactsView, - AddCommentView, - UpdateCommentView, - DeleteCommentView, - AddAttachmentsView, - DeleteAttachmentsView, -) - -app_name = "contacts" - - -urlpatterns = [ - path("", ContactsListView.as_view(), name="list"), - path("create/", CreateContactView.as_view(), name="add_contact"), - path("/view/", ContactDetailView.as_view(), name="view_contact"), - path("/edit/", UpdateContactView.as_view(), name="edit_contact"), - path("/delete/", RemoveContactView.as_view(), name="remove_contact"), - path("get/list/", GetContactsView.as_view(), name="get_contacts"), - path("comment/add/", AddCommentView.as_view(), name="add_comment"), - path("comment/edit/", UpdateCommentView.as_view(), name="edit_comment"), - path("comment/remove/", DeleteCommentView.as_view(), name="remove_comment"), - path("attachment/add/", AddAttachmentsView.as_view(), name="add_attachment"), - path( - "attachment/remove/", DeleteAttachmentsView.as_view(), name="remove_attachment" - ), - path("get_teams_and_users/", get_teams_and_users, name="get_teams_and_users"), -] diff --git a/contacts/views.py b/contacts/views.py deleted file mode 100644 index 6fedf17..0000000 --- a/contacts/views.py +++ /dev/null @@ -1,672 +0,0 @@ -import json -from django.contrib.auth.mixins import LoginRequiredMixin -from django.contrib.sites.shortcuts import get_current_site -from django.contrib.auth.decorators import login_required -from django.core.mail import EmailMessage -from django.http import JsonResponse -from django.shortcuts import get_object_or_404, redirect -from django.template.loader import render_to_string -from django.urls import reverse -from django.views.generic import CreateView, UpdateView, DetailView, TemplateView, View -from common.models import User, Comment, Attachments -from common.forms import BillingAddressForm -from common.utils import COUNTRIES -from contacts.models import Contact -from contacts.forms import ContactForm, ContactCommentForm, ContactAttachmentForm -from accounts.models import Account -from django.core.exceptions import PermissionDenied -from django.db.models import Q -from common.tasks import send_email_user_mentions -from contacts.tasks import send_email_to_assigned_user -from common.access_decorators_mixins import ( - sales_access_required, - marketing_access_required, - SalesAccessRequiredMixin, - MarketingAccessRequiredMixin, -) -from teams.models import Teams - - -@login_required -def get_teams_and_users(request): - data = {} - teams = Teams.objects.filter(company=request.company) - teams_data = [ - {"team": team.id, "users": [user.id for user in team.users.all()]} - for team in teams - ] - users = User.objects.filter(company=request.company).values_list("id", flat=True) - data["teams"] = teams_data - data["users"] = list(users) - return JsonResponse(data) - - -class ContactsListView(SalesAccessRequiredMixin, LoginRequiredMixin, TemplateView): - model = Contact - context_object_name = "contact_obj_list" - template_name = "contacts.html" - - def get_queryset(self): - queryset = self.model.objects.filter(company=self.request.company).order_by( - "-created_on" - ) - if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: - queryset = queryset.filter( - Q(assigned_to__in=[self.request.user]) | Q(created_by=self.request.user) - ) - - request_post = self.request.POST - if request_post: - if request_post.get("first_name"): - queryset = queryset.filter( - first_name__icontains=request_post.get("first_name") - ) - if request_post.get("city"): - queryset = queryset.filter( - address__city__icontains=request_post.get("city") - ) - if request_post.get("phone"): - queryset = queryset.filter(phone__icontains=request_post.get("phone")) - if request_post.get("email"): - queryset = queryset.filter(email__icontains=request_post.get("email")) - if request_post.getlist("assigned_to"): - queryset = queryset.filter( - assigned_to__id__in=request_post.getlist("assigned_to") - ) - return queryset.distinct() - - def get_context_data(self, **kwargs): - context = super(ContactsListView, self).get_context_data(**kwargs) - context["contact_obj_list"] = self.get_queryset() - context["per_page"] = self.request.POST.get("per_page") - context["users"] = User.objects.filter(is_active=True).order_by("username") - context["assignedto_list"] = [ - int(i) for i in self.request.POST.getlist("assigned_to", []) if i - ] - search = False - if ( - self.request.POST.get("first_name") - or self.request.POST.get("city") - or self.request.POST.get("phone") - or self.request.POST.get("email") - or self.request.POST.get("assigned_to") - ): - search = True - context["search"] = search - return context - - def post(self, request, *args, **kwargs): - context = self.get_context_data(**kwargs) - return self.render_to_response(context) - - -class CreateContactView(SalesAccessRequiredMixin, LoginRequiredMixin, CreateView): - model = Contact - form_class = ContactForm - template_name = "create_contact.html" - - def dispatch(self, request, *args, **kwargs): - if self.request.user.role == "ADMIN" or self.request.user.is_superuser: - self.users = User.objects.filter( - is_active=True, company=self.request.company - ).order_by("email") - else: - self.users = User.objects.filter( - role="ADMIN", company=self.request.company - ).order_by("email") - return super(CreateContactView, self).dispatch(request, *args, **kwargs) - - def get_form_kwargs(self): - kwargs = super(CreateContactView, self).get_form_kwargs() - if self.request.user.role == "ADMIN" or self.request.user.is_superuser: - self.users = User.objects.filter( - is_active=True, company=self.request.company - ).order_by("email") - kwargs.update({"assigned_to": self.users}) - return kwargs - - def post(self, request, *args, **kwargs): - self.object = None - form = self.get_form() - address_form = BillingAddressForm(request.POST) - if form.is_valid() and address_form.is_valid(): - address_obj = address_form.save() - contact_obj = form.save(commit=False) - contact_obj.address = address_obj - contact_obj.created_by = self.request.user - contact_obj.company = self.request.company - contact_obj.save() - if self.request.GET.get("view_account", None): - if Account.objects.filter( - id=int(self.request.GET.get("view_account")) - ).exists(): - Account.objects.get( - id=int(self.request.GET.get("view_account")) - ).contacts.add(contact_obj) - return self.form_valid(form) - - return self.form_invalid(form) - - def form_valid(self, form): - contact_obj = form.save(commit=False) - if self.request.POST.getlist("assigned_to", []): - contact_obj.assigned_to.add(*self.request.POST.getlist("assigned_to")) - # for assigned_to_user in assigned_to_list: - # user = get_object_or_404(User, pk=assigned_to_user) - # mail_subject = 'Assigned to contact.' - # message = render_to_string( - # 'assigned_to/contact_assigned.html', { - # 'user': user, - # 'domain': current_site.domain, - # 'protocol': self.request.scheme, - # 'contact': contact_obj - # }) - # email = EmailMessage(mail_subject, message, to=[user.email]) - # email.content_subtype = "html" - # email.send() - if self.request.POST.getlist("teams", []): - user_ids = Teams.objects.filter( - id__in=self.request.POST.getlist("teams") - ).values_list("users", flat=True) - assinged_to_users_ids = contact_obj.assigned_to.all().values_list( - "id", flat=True - ) - for user_id in user_ids: - if user_id not in assinged_to_users_ids: - contact_obj.assigned_to.add(user_id) - - if self.request.POST.getlist("teams", []): - contact_obj.teams.add(*self.request.POST.getlist("teams")) - - assigned_to_list = list( - contact_obj.assigned_to.all().values_list("id", flat=True) - ) - current_site = get_current_site(self.request) - recipients = assigned_to_list - send_email_to_assigned_user.delay( - recipients, - contact_obj.id, - domain=current_site.domain, - protocol=self.request.scheme, - ) - - if self.request.FILES.get("contact_attachment"): - attachment = Attachments() - attachment.created_by = self.request.user - attachment.file_name = self.request.FILES.get("contact_attachment").name - attachment.contact = contact_obj - attachment.attachment = self.request.FILES.get("contact_attachment") - attachment.save() - - if self.request.is_ajax(): - return JsonResponse({"error": False}) - if self.request.POST.get("savenewform"): - return redirect("contacts:add_contact") - - return redirect("contacts:list") - - def form_invalid(self, form): - address_form = BillingAddressForm(self.request.POST) - if self.request.is_ajax(): - return JsonResponse( - { - "error": True, - "contact_errors": form.errors, - "address_errors": address_form.errors, - } - ) - return self.render_to_response( - self.get_context_data(form=form, address_form=address_form) - ) - - def get_context_data(self, **kwargs): - context = super(CreateContactView, self).get_context_data(**kwargs) - context["contact_form"] = context["form"] - context["users"] = self.users - context["countries"] = COUNTRIES - context["assignedto_list"] = [ - int(i) for i in self.request.POST.getlist("assigned_to", []) if i - ] - if "address_form" in kwargs: - context["address_form"] = kwargs["address_form"] - else: - if self.request.POST: - context["address_form"] = BillingAddressForm(self.request.POST) - else: - context["address_form"] = BillingAddressForm() - context["teams"] = Teams.objects.filter(company=self.request.company) - return context - - -class ContactDetailView(SalesAccessRequiredMixin, LoginRequiredMixin, DetailView): - model = Contact - context_object_name = "contact_record" - template_name = "view_contact.html" - - def dispatch(self, request, *args, **kwargs): - contact = self.get_object() - if contact.company != request.company: - raise PermissionDenied - return super(ContactDetailView, self).dispatch(request, *args, **kwargs) - - def get_queryset(self): - queryset = super(ContactDetailView, self).get_queryset() - return queryset.select_related("address") - - def get_context_data(self, **kwargs): - context = super(ContactDetailView, self).get_context_data(**kwargs) - user_assgn_list = [ - assigned_to.id for assigned_to in context["object"].assigned_to.all() - ] - user_assigned_accounts = set( - self.request.user.account_assigned_users.values_list("id", flat=True) - ) - contact_accounts = set( - context["object"].account_contacts.values_list("id", flat=True) - ) - if user_assigned_accounts.intersection(contact_accounts): - user_assgn_list.append(self.request.user.id) - if self.request.user == context["object"].created_by: - user_assgn_list.append(self.request.user.id) - if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: - if self.request.user.id not in user_assgn_list: - raise PermissionDenied - assigned_data = [] - for each in context["contact_record"].assigned_to.all(): - assigned_dict = {} - assigned_dict["id"] = each.id - assigned_dict["name"] = each.email - assigned_data.append(assigned_dict) - - if self.request.user.is_superuser or self.request.user.role == "ADMIN": - users_mention = list( - User.objects.filter( - is_active=True, company=self.request.company - ).values("username") - ) - elif self.request.user != context["object"].created_by: - users_mention = [{"username": context["object"].created_by.username}] - else: - users_mention = list(context["object"].assigned_to.all().values("username")) - - context.update( - { - "comments": context["contact_record"].contact_comments.all(), - "attachments": context["contact_record"].contact_attachment.all(), - "assigned_data": json.dumps(assigned_data), - "tasks": context["object"].contacts_tasks.all(), - "users_mention": users_mention, - } - ) - return context - - -class UpdateContactView(SalesAccessRequiredMixin, LoginRequiredMixin, UpdateView): - model = Contact - form_class = ContactForm - template_name = "create_contact.html" - - def dispatch(self, request, *args, **kwargs): - contact = self.get_object() - if contact.company != request.company: - raise PermissionDenied - - if self.request.user.role == "ADMIN" or self.request.user.is_superuser: - self.users = User.objects.filter( - is_active=True, company=self.request.company - ).order_by("email") - else: - self.users = User.objects.filter( - role="ADMIN", company=self.request.company - ).order_by("email") - return super(UpdateContactView, self).dispatch(request, *args, **kwargs) - - def get_form_kwargs(self): - kwargs = super(UpdateContactView, self).get_form_kwargs() - if self.request.user.role == "ADMIN" or self.request.user.is_superuser: - self.users = User.objects.filter( - is_active=True, company=self.request.company - ).order_by("email") - kwargs.update({"assigned_to": self.users}) - return kwargs - - def post(self, request, *args, **kwargs): - self.object = self.get_object() - address_obj = self.object.address - form = self.get_form() - address_form = BillingAddressForm(request.POST, instance=address_obj) - if form.is_valid() and address_form.is_valid(): - addres_obj = address_form.save() - contact_obj = form.save(commit=False) - contact_obj.address = addres_obj - contact_obj.save() - return self.form_valid(form) - return self.form_invalid(form) - - def form_valid(self, form): - assigned_to_ids = ( - self.get_object().assigned_to.all().values_list("id", flat=True) - ) - - contact_obj = form.save(commit=False) - previous_assigned_to_users = list( - contact_obj.assigned_to.all().values_list("id", flat=True) - ) - all_members_list = [] - if self.request.POST.getlist("assigned_to", []): - current_site = get_current_site(self.request) - assigned_form_users = form.cleaned_data.get("assigned_to").values_list( - "id", flat=True - ) - all_members_list = list( - set(list(assigned_form_users)) - set(list(assigned_to_ids)) - ) - # if all_members_list: - # for assigned_to_user in all_members_list: - # user = get_object_or_404(User, pk=assigned_to_user) - # mail_subject = 'Assigned to contact.' - # message = render_to_string( - # 'assigned_to/contact_assigned.html', { - # 'user': user, - # 'domain': current_site.domain, - # 'protocol': self.request.scheme, - # 'contact': contact_obj - # }) - # email = EmailMessage( - # mail_subject, message, to=[user.email]) - # email.content_subtype = "html" - # email.send() - - contact_obj.assigned_to.clear() - contact_obj.assigned_to.add(*self.request.POST.getlist("assigned_to")) - else: - contact_obj.assigned_to.clear() - - if self.request.POST.getlist("teams", []): - user_ids = Teams.objects.filter( - id__in=self.request.POST.getlist("teams") - ).values_list("users", flat=True) - assinged_to_users_ids = contact_obj.assigned_to.all().values_list( - "id", flat=True - ) - for user_id in user_ids: - if user_id not in assinged_to_users_ids: - contact_obj.assigned_to.add(user_id) - - if self.request.POST.getlist("teams", []): - contact_obj.teams.clear() - contact_obj.teams.add(*self.request.POST.getlist("teams")) - else: - contact_obj.teams.clear() - - current_site = get_current_site(self.request) - assigned_to_list = list( - contact_obj.assigned_to.all().values_list("id", flat=True) - ) - recipients = list(set(assigned_to_list) - set(previous_assigned_to_users)) - send_email_to_assigned_user.delay( - recipients, - contact_obj.id, - domain=current_site.domain, - protocol=self.request.scheme, - ) - - if self.request.FILES.get("contact_attachment"): - attachment = Attachments() - attachment.created_by = self.request.user - attachment.file_name = self.request.FILES.get("contact_attachment").name - attachment.contact = contact_obj - attachment.attachment = self.request.FILES.get("contact_attachment") - attachment.save() - if self.request.POST.get("from_account"): - from_account = self.request.POST.get("from_account") - return redirect("accounts:view_account", pk=from_account) - if self.request.is_ajax(): - return JsonResponse({"error": False}) - return redirect("contacts:list") - - def form_invalid(self, form): - address_obj = self.object.address - address_form = BillingAddressForm(self.request.POST, instance=address_obj) - if self.request.is_ajax(): - return JsonResponse( - { - "error": True, - "contact_errors": form.errors, - "address_errors": address_form.errors, - } - ) - return self.render_to_response( - self.get_context_data(form=form, address_form=address_form) - ) - - def get_context_data(self, **kwargs): - context = super(UpdateContactView, self).get_context_data(**kwargs) - context["contact_obj"] = self.object - user_assgn_list = [ - assigned_to.id for assigned_to in context["contact_obj"].assigned_to.all() - ] - if self.request.user == context["contact_obj"].created_by: - user_assgn_list.append(self.request.user.id) - if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: - if self.request.user.id not in user_assgn_list: - raise PermissionDenied - context["address_obj"] = self.object.address - context["contact_form"] = context["form"] - context["users"] = self.users - context["countries"] = COUNTRIES - context["teams"] = Teams.objects.filter(company=self.request.company) - context["assignedto_list"] = [ - int(i) for i in self.request.POST.getlist("assigned_to", []) if i - ] - if "address_form" in kwargs: - context["address_form"] = kwargs["address_form"] - else: - if self.request.POST: - context["address_form"] = BillingAddressForm( - self.request.POST, instance=context["address_obj"] - ) - else: - context["address_form"] = BillingAddressForm( - instance=context["address_obj"] - ) - return context - - -class RemoveContactView(SalesAccessRequiredMixin, LoginRequiredMixin, View): - def get(self, request, *args, **kwargs): - return self.post(request, *args, **kwargs) - - def post(self, request, *args, **kwargs): - contact_id = kwargs.get("pk") - self.object = get_object_or_404(Contact, id=contact_id) - if ( - self.request.user.role != "ADMIN" - and not self.request.user.is_superuser - and self.request.user != self.object.created_by - ) or self.object.company != self.request.company: - raise PermissionDenied - else: - if self.object.address_id: - self.object.address.delete() - self.object.delete() - if self.request.is_ajax(): - return JsonResponse({"error": False}) - return redirect("contacts:list") - - -class AddCommentView(LoginRequiredMixin, CreateView): - model = Comment - form_class = ContactCommentForm - http_method_names = ["post"] - - def post(self, request, *args, **kwargs): - self.object = None - self.contact = get_object_or_404(Contact, id=request.POST.get("contactid")) - if ( - request.user in self.contact.assigned_to.all() - or request.user == self.contact.created_by - or request.user.is_superuser - or request.user.role == "ADMIN" - ): - form = self.get_form() - if form.is_valid(): - return self.form_valid(form) - - return self.form_invalid(form) - - data = {"error": "You don't have permission to comment."} - return JsonResponse(data) - - def form_valid(self, form): - comment = form.save(commit=False) - comment.commented_by = self.request.user - comment.contact = self.contact - comment.save() - comment_id = comment.id - current_site = get_current_site(self.request) - send_email_user_mentions.delay( - comment_id, - "contacts", - domain=current_site.domain, - protocol=self.request.scheme, - ) - return JsonResponse( - { - "comment_id": comment.id, - "comment": comment.comment, - "commented_on": comment.commented_on, - "commented_on_arrow": comment.commented_on_arrow, - "commented_by": comment.commented_by.email, - } - ) - - def form_invalid(self, form): - return JsonResponse({"error": form["comment"].errors}) - - -class UpdateCommentView(LoginRequiredMixin, View): - http_method_names = ["post"] - - def post(self, request, *args, **kwargs): - self.comment_obj = get_object_or_404(Comment, id=request.POST.get("commentid")) - if request.user == self.comment_obj.commented_by: - form = ContactCommentForm(request.POST, instance=self.comment_obj) - if form.is_valid(): - return self.form_valid(form) - - return self.form_invalid(form) - - data = {"error": "You don't have permission to edit this comment."} - return JsonResponse(data) - - def form_valid(self, form): - self.comment_obj.comment = form.cleaned_data.get("comment") - self.comment_obj.save(update_fields=["comment"]) - comment_id = self.comment_obj.id - current_site = get_current_site(self.request) - send_email_user_mentions.delay( - comment_id, - "contacts", - domain=current_site.domain, - protocol=self.request.scheme, - ) - return JsonResponse( - { - "commentid": self.comment_obj.id, - "comment": self.comment_obj.comment, - } - ) - - def form_invalid(self, form): - return JsonResponse({"error": form["comment"].errors}) - - -class DeleteCommentView(LoginRequiredMixin, View): - def post(self, request, *args, **kwargs): - self.object = get_object_or_404(Comment, id=request.POST.get("comment_id")) - if request.user == self.object.commented_by: - self.object.delete() - data = {"cid": request.POST.get("comment_id")} - return JsonResponse(data) - - data = {"error": "You don't have permission to delete this comment."} - return JsonResponse(data) - - -class GetContactsView(LoginRequiredMixin, TemplateView): - model = Contact - context_object_name = "contacts" - template_name = "contacts_list.html" - - def get_context_data(self, **kwargs): - context = super(GetContactsView, self).get_context_data(**kwargs) - context["contacts"] = self.get_queryset() - return context - - -class AddAttachmentsView(LoginRequiredMixin, CreateView): - model = Attachments - form_class = ContactAttachmentForm - http_method_names = ["post"] - - def post(self, request, *args, **kwargs): - self.object = None - self.contact = get_object_or_404(Contact, id=request.POST.get("contactid")) - if ( - request.user in self.contact.assigned_to.all() - or request.user == self.contact.created_by - or request.user.is_superuser - or request.user.role == "ADMIN" - ): - form = self.get_form() - if form.is_valid(): - return self.form_valid(form) - - return self.form_invalid(form) - - data = {"error": "You don't have permission to add attachment."} - return JsonResponse(data) - - def form_valid(self, form): - attachment = form.save(commit=False) - attachment.created_by = self.request.user - attachment.file_name = attachment.attachment.name - attachment.contact = self.contact - attachment.save() - return JsonResponse( - { - "attachment_id": attachment.id, - "attachment": attachment.file_name, - "attachment_url": attachment.attachment.url, - "created_on": attachment.created_on, - "created_on_arrow": attachment.created_on_arrow, - "download_url": reverse( - "common:download_attachment", kwargs={"pk": attachment.id} - ), - "attachment_display": attachment.get_file_type_display(), - "created_by": attachment.created_by.email, - "file_type": attachment.file_type(), - } - ) - - def form_invalid(self, form): - return JsonResponse({"error": form["attachment"].errors}) - - -class DeleteAttachmentsView(LoginRequiredMixin, View): - def post(self, request, *args, **kwargs): - self.object = get_object_or_404( - Attachments, id=request.POST.get("attachment_id") - ) - if ( - request.user == self.object.created_by - or request.user.is_superuser - or request.user.role == "ADMIN" - ): - self.object.delete() - data = {"aid": request.POST.get("attachment_id")} - return JsonResponse(data) - - data = {"error": "You don't have permission to delete this attachment."} - return JsonResponse(data) diff --git a/crm/helper.py b/crm/helper.py deleted file mode 100644 index 8f52b8e..0000000 --- a/crm/helper.py +++ /dev/null @@ -1,63 +0,0 @@ -import boto.ses -import sendgrid -import requests -import mandrill -from django.core.mail import EmailMultiAlternatives -from django.conf import settings - - -def send_mail(mto, mfrom, msubject, mbody, user_active): - if mfrom: - mfrom = mfrom - else: - mfrom = settings.DEFAULT_FROM_EMAIL - if user_active: - mail_sender = settings.MAIL_SENDER - else: - mail_sender = settings.INACTIVE_MAIL_SENDER - if mail_sender == "AMAZON": - # conn=SESConnection(settings.AWS_ACCESS_KEY_ID, settings.AWS_SECRET_ACCESS_KEY) - conn = boto.ses.connect_to_region( - settings.AWS_SES_REGION_NAME, - aws_access_key_id=settings.AWS_ACCESS_KEY_ID, - aws_secret_access_key=settings.AWS_SECRET_ACCESS_KEY, - ) - response = conn.send_email(mfrom, msubject, mbody, mto, format="html") - elif mail_sender == "MAILGUN": - response = requests.post( - settings.MGUN_API_URL, - auth=("api", settings.MGUN_API_KEY), - data={ - "from": mfrom, - "to": mto, - "subject": msubject, - "html": mbody, - }, - ) - elif mail_sender == "SENDGRID": - sg = sendgrid.SendGridClient(settings.SG_USER, settings.SG_PWD) - sending_msg = sendgrid.Mail() - sending_msg.set_subject(msubject) - sending_msg.set_html(mbody) - sending_msg.set_text(msubject) - sending_msg.set_from(mfrom) - sending_msg.add_to(mto) - response = sg.send(sending_msg) - elif mail_sender == "MANDRILL": - api_key = settings.MANDRILL_API_KEY - mandrill_client = mandrill.Mandrill(api_key) - - message = { - "html": mbody, - "subject": msubject, - "from_email": mfrom, - "from_name": "Django CRM", - "to": [{"email": i, "type": "to"} for i in mto], - } - response = mandrill_client.messages.send(message=message) - - else: - msg = EmailMultiAlternatives(msubject, mbody, mfrom, [mto]) - msg.attach_alternative(mbody, "text/html") - response = msg.send() - return response diff --git a/crm/server_settings.py b/crm/server_settings.py index 77ebf2e..494795a 100644 --- a/crm/server_settings.py +++ b/crm/server_settings.py @@ -17,19 +17,11 @@ "CacheControl": "max-age=86400", } -STATICFILES_STORAGE = "storages.backends.s3boto3.S3Boto3Storage" - DEFAULT_FILE_STORAGE = "storages.backends.s3boto3.S3Boto3Storage" DEFAULT_S3_PATH = "media" -STATICFILES_STORAGE = "storages.backends.s3boto3.S3Boto3Storage" -STATIC_S3_PATH = "static" -COMPRESS_STORAGE = "storages.backends.s3boto3.S3Boto3Storage" - -COMPRESS_JS_FILTERS = ["compressor.filters.jsmin.JSMinFilter"] MEDIA_ROOT = "/%s/" % DEFAULT_S3_PATH MEDIA_URL = "//%s/%s/" % (S3_DOMAIN, DEFAULT_S3_PATH) -STATIC_ROOT = "/%s/" % STATIC_S3_PATH STATIC_URL = "https://%s/" % (S3_DOMAIN) ADMIN_MEDIA_PREFIX = STATIC_URL + "admin/" @@ -38,7 +30,6 @@ AWS_IS_GZIPPED = True AWS_ENABLED = True AWS_S3_SECURE_URLS = True -COMPRESS_URL = STATIC_URL EMAIL_BACKEND = "django_ses.SESBackend" @@ -52,3 +43,19 @@ # django.contrib.auth) you may enable sending PII data. send_default_pii=True, ) + + +SENTRY_ENABLED = os.getenv("SENTRY_ENABLED", False) + +if SENTRY_ENABLED and not DEBUG: + if os.getenv("SENTRY_DSN") is not None: + RAVEN_CONFIG = { + "dsn": os.getenv("SENTRY_DSN", ""), + } + INSTALLED_APPS = INSTALLED_APPS + [ + "raven.contrib.django.raven_compat", + ] + MIDDLEWARE = [ + "raven.contrib.django.raven_compat.middleware.Sentry404CatchMiddleware", + "raven.contrib.django.raven_compat.middleware.SentryResponseErrorIdMiddleware", + ] + MIDDLEWARE diff --git a/crm/settings.py b/crm/settings.py index ce14fc2..1ecf394 100644 --- a/crm/settings.py +++ b/crm/settings.py @@ -15,18 +15,12 @@ "SECRET_KEY", "&q1&ftrxho9lrzm$$%6!cplb5ac957-9y@t@17u(3yqqb#9xl%" ) +Domain = os.getenv("DOMAIN_NAME") # SECURITY WARNING: don't run with debug turned on in production! DEBUG = os.getenv("DEBUG") -ALLOWED_HOSTS = [".bottlecrm.com", ".localhost"] - -# Application definition - -LOGIN_REDIRECT_URL = "/" - -# LOGIN_URL = "/login/" -LOGIN_URL = "/auth/domain/" +ALLOWED_HOSTS = ["localhost", "127.0.0.1"] INSTALLED_APPS = [ "django.contrib.auth", @@ -34,9 +28,6 @@ "django.contrib.messages", "django.contrib.sessions", "django.contrib.staticfiles", - "simple_pagination", - "compressor", - # 'haystack', "common", "accounts", "cases", @@ -45,10 +36,7 @@ "leads", "opportunity", "planner", - "sorl.thumbnail", "phonenumber_field", - "storages", - "marketing", "tasks", "invoices", "events", @@ -57,7 +45,6 @@ "drf_yasg", "corsheaders", "django_ses", - "django_blog_it", ] MIDDLEWARE = [ @@ -67,7 +54,6 @@ "django.contrib.auth.middleware.AuthenticationMiddleware", "django.contrib.messages.middleware.MessageMiddleware", "django.middleware.clickjacking.XFrameOptionsMiddleware", - "common.middleware.get_company.GetCompany", "corsheaders.middleware.CorsMiddleware", ] @@ -109,12 +95,6 @@ } } - -STATICFILES_DIRS = [ - os.path.join(BASE_DIR, "static"), - # os.path.join(BASE_DIR, "blog_app/static"), -] - # Password validation # https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators @@ -146,98 +126,25 @@ USE_TZ = True -# Static files (CSS, JavaScript, Images) -# https://docs.djangoproject.com/en/1.10/howto/static-files/ - -STATIC_URL = "/static/" - -# EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend" -# EMAIL_BACKEND = 'django.core.mail.backends.dummy.EmailBackend' -# EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' - -# EMAIL_HOST = 'localhost' -# EMAIL_PORT = 25 -# AUTHENTICATION_BACKENDS = ('django.contrib.auth.backends.ModelBackend', ) - - -# EMAIL_HOST = "smtp.sendgrid.net" -# EMAIL_HOST_USER = os.getenv("SG_USER", "") -# EMAIL_HOST_PASSWORD = os.getenv("SG_PWD", "") -# EMAIL_PORT = 587 -# EMAIL_USE_TLS = True +EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend" AUTH_USER_MODEL = "common.User" ENV_TYPE = os.getenv("ENV_TYPE", "dev") - if ENV_TYPE == "dev": DOMAIN_NAME = "localhost:8000" # SESSION_COOKIE_DOMAIN = "localhost:8000" - # DEFAULT_FILE_STORAGE = 'django.core.files.storage.FileSystemStorage' - # STATICFILES_STORAGE = "storages.backends.s3boto3.S3Boto3Storage" - # COMPRESS_STORAGE = "storages.backends.s3boto3.S3Boto3Storage" - MEDIA_ROOT = os.path.join(BASE_DIR, "media") MEDIA_URL = "/media/" STATIC_URL = "/static/" - STATICFILES_DIRS = (BASE_DIR + "/static",) - COMPRESS_ROOT = BASE_DIR + "/static/" - - ADMIN_MEDIA_PREFIX = STATIC_URL + "admin/" - elif ENV_TYPE == "live": - # INSTALLED_APPS = INSTALLED_APPS + [ - # "elasticapm.contrib.django", - # ] - - # MIDDLEWARE = MIDDLEWARE + [ - # "elasticapm.contrib.django.middleware.TracingMiddleware", - # ] from .server_settings import * -STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles") - -# COMPRESS_ROOT = BASE_DIR + "/static/" -COMPRESS_JS_FILTERS = ["compressor.filters.jsmin.JSMinFilter"] - -COMPRESS_ENABLED = True - -COMPRESS_OFFLINE_CONTEXT = { - "STATIC_URL": "STATIC_URL", -} - -STATICFILES_FINDERS = ( - "django.contrib.staticfiles.finders.FileSystemFinder", - "django.contrib.staticfiles.finders.AppDirectoriesFinder", - "compressor.finders.CompressorFinder", -) - -COMPRESS_CSS_FILTERS = [ - "compressor.filters.css_default.CssAbsoluteFilter", - "compressor.filters.cssmin.CSSMinFilter", -] - -COMPRESS_REBUILD_TIMEOUT = 5400 - - -COMPRESS_OUTPUT_DIR = "CACHE" -COMPRESS_URL = STATIC_URL - -COMPRESS_PRECOMPILERS = ( - ("text/less", "lessc {infile} {outfile}"), - ("text/x-sass", "sass {infile} {outfile}"), - ("text/x-scss", "sass {infile} {outfile}"), -) - -COMPRESS_OFFLINE_CONTEXT = { - "STATIC_URL": "STATIC_URL", -} - -DEFAULT_FROM_EMAIL = os.getenv("DEFAULT_FROM_EMAIL") -ADMIN_EMAIL = os.getenv("ADMIN_EMAIL") +DEFAULT_FROM_EMAIL = os.getenv("DEFAULT_FROM_EMAIL", "") +ADMIN_EMAIL = os.getenv("ADMIN_EMAIL", "") MARKETING_REPLY_EMAIL = os.getenv("MARKETING_REPLY_EMAIL", "") PASSWORD_RESET_MAIL_FROM_USER = os.getenv("PASSWORD_RESET_MAIL_FROM_USER", "") @@ -246,63 +153,8 @@ CELERY_BROKER_URL = os.getenv("CELERY_BROKER_URL") CELERY_RESULT_BACKEND = os.getenv("CELERY_RESULT_BACKEND") -CELERY_BEAT_SCHEDULE = { - "runs-campaign-for-every-thiry-minutes": { - "task": "marketing.tasks.run_all_campaigns", - "schedule": crontab(minute=30, hour="*"), - }, - "runs-campaign-for-every-five-minutes": { - "task": "marketing.tasks.list_all_bounces_unsubscribes", - "schedule": crontab(minute="*/5"), - }, - "runs-scheduled-campaigns-for-every-one-hour": { - "task": "marketing.tasks.send_scheduled_campaigns", - "schedule": crontab(hour="*/1"), - }, - "runs-scheduled-emails-for-accounts-every-one-minute": { - "task": "accounts.tasks.send_scheduled_emails", - "schedule": crontab(minute="*/1"), - }, -} - -MAIL_SENDER = "AMAZON" -# INACTIVE_MAIL_SENDER = "MANDRILL" - -# MGUN_API_URL = os.getenv("MGUN_API_URL", "") -# MGUN_API_KEY = os.getenv("MGUN_API_KEY", "") - -# SG_USER = os.getenv("SG_USER", "") -# SG_PWD = os.getenv("SG_PWD", "") - -# MANDRILL_API_KEY = os.getenv("MANDRILL_API_KEY", "") - - -# Marketing app related -# URL_FOR_LINKS = os.getenv("URLFORLINKS") - - -# GP_CLIENT_ID = os.getenv("GP_CLIENT_ID", False) -# GP_CLIENT_SECRET = os.getenv("GP_CLIENT_SECRET", False) -# ENABLE_GOOGLE_LOGIN = os.getenv("ENABLE_GOOGLE_LOGIN", False) - - PASSWORD_RESET_TIMEOUT_DAYS = 3 -SENTRY_ENABLED = os.getenv("SENTRY_ENABLED", False) - -if SENTRY_ENABLED and not DEBUG: - if os.getenv("SENTRY_DSN") is not None: - RAVEN_CONFIG = { - "dsn": os.getenv("SENTRY_DSN", ""), - } - INSTALLED_APPS = INSTALLED_APPS + [ - "raven.contrib.django.raven_compat", - ] - MIDDLEWARE = [ - "raven.contrib.django.raven_compat.middleware.Sentry404CatchMiddleware", - "raven.contrib.django.raven_compat.middleware.SentryResponseErrorIdMiddleware", - ] + MIDDLEWARE - LOGGING = { "version": 1, @@ -363,65 +215,10 @@ }, }, } -# HAYSTACK_CONNECTIONS = { -# 'default': { -# # 'ENGINE': 'haystack.backends.elasticsearch_backend.ElasticsearchSearchEngine', -# 'ENGINE': 'marketing.search_backends.CustomElasticsearchSearchEngine', -# 'URL': 'http://127.0.0.1:9200/', -# 'INDEX_NAME': 'haystack', -# }, -# } - -# HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor' - -# HAYSTACK_SEARCH_RESULTS_PER_PAGE = 10 - -# ELASTICSEARCH_INDEX_SETTINGS = { -# "settings": { -# "analysis": { -# "analyzer": { -# "ngram_analyzer": { -# "type": "custom", -# "tokenizer": "custom_ngram_tokenizer", -# "filter": ["asciifolding", "lowercase"] -# }, -# "edgengram_analyzer": { -# "type": "custom", -# "tokenizer": "custom_edgengram_tokenizer", -# "filter": ["asciifolding", "lowercase"] -# } -# }, -# "tokenizer": { -# "custom_ngram_tokenizer": { -# "type": "nGram", -# "min_gram": 3, -# "max_gram": 12, -# "token_chars": ["letter", "digit"] -# }, -# "custom_edgengram_tokenizer": { -# "type": "edgeNGram", -# "min_gram": 2, -# "max_gram": 12, -# "token_chars": ["letter", "digit"] -# } -# } -# } -# } -# } - -# HAYSTACK_DEFAULT_OPERATOR = 'AND' APPLICATION_NAME = "bottlecrm" -CACHES = { - "default": { - "BACKEND": "django.core.cache.backends.memcached.MemcachedCache", - "LOCATION": os.getenv("MEMCACHELOCATION"), - } -} - - SETTINGS_EXPORT = ["APPLICATION_NAME"] REST_FRAMEWORK = { @@ -442,28 +239,4 @@ }, } -TOKEN_SECRET_KEY = "mk%l3jsghg-u*!luyer@tew$xn!ksb(k$&2rj4h4@%tmy76z" - -JWT_AUTH = { - "JWT_ENCODE_HANDLER": "rest_framework_jwt.utils.jwt_encode_handler", - "JWT_DECODE_HANDLER": "rest_framework_jwt.utils.jwt_decode_handler", - "JWT_PAYLOAD_HANDLER": "common.utils.jwt_payload_handler", - "JWT_RESPONSE_PAYLOAD_HANDLER": "rest_framework_jwt.utils.jwt_response_payload_handler", - "JWT_SECRET_KEY": TOKEN_SECRET_KEY, - "JWT_GET_USER_SECRET_KEY": None, - "JWT_PUBLIC_KEY": None, - "JWT_PRIVATE_KEY": None, - "JWT_ALGORITHM": "HS256", - "JWT_VERIFY": True, - "JWT_VERIFY_EXPIRATION": True, - "JWT_LEEWAY": 0, - "JWT_AUDIENCE": None, - "JWT_ISSUER": None, - "JWT_ALLOW_REFRESH": True, - "JWT_AUTH_HEADER_PREFIX": "JWT", - "JWT_AUTH_COOKIE": None, -} - -CORS_ALLOW_HEADERS = default_headers + ("company",) - CORS_ORIGIN_ALLOW_ALL = True diff --git a/crm/urls.py b/crm/urls.py index b00f385..d8ebaf6 100644 --- a/crm/urls.py +++ b/crm/urls.py @@ -2,7 +2,6 @@ from django.conf.urls.static import static from django.contrib.auth import views from django.urls import include, path -from common.views import handler404, handler500 from drf_yasg.views import get_schema_view from drf_yasg import openapi from django.conf.urls import url @@ -37,30 +36,13 @@ url( r"^redoc/$", schema_view.with_ui("redoc", cache_timeout=0), name="schema-redoc" ), - path("", include("common.urls", namespace="common")), + # path("", include("common.urls", namespace="common")), path("api/", include("common.app_urls", namespace="common_urls")), path("", include("django.contrib.auth.urls")), - path("marketing/", include("marketing.urls", namespace="marketing")), - path("accounts/", include("accounts.urls", namespace="accounts")), - path("leads/", include("leads.urls", namespace="leads")), - path("contacts/", include("contacts.urls", namespace="contacts")), - path("opportunities/", include("opportunity.urls", namespace="opportunities")), - path("cases/", include("cases.urls", namespace="cases")), - path("tasks/", include("tasks.urls", namespace="tasks")), - path("invoices/", include("invoices.urls", namespace="invoices")), - path("events/", include("events.urls", namespace="events")), - path("teams/", include("teams.urls", namespace="teams")), - path("emails/", include("emails.urls", namespace="emails")), - # path('planner/', include('planner.urls', namespace="planner")), path("logout/", views.LogoutView, {"next_page": "/login/"}, name="logout"), - path("", include("django_blog_it.urls")), ] if settings.DEBUG: urlpatterns = urlpatterns + static( settings.MEDIA_URL, document_root=settings.MEDIA_ROOT ) - - -handler404 = handler404 -handler500 = handler500 diff --git a/dump.rdb b/dump.rdb new file mode 100644 index 0000000..937eae5 Binary files /dev/null and b/dump.rdb differ diff --git a/events/api_views.py b/events/api_views.py index 222fdbd..d791fa4 100644 --- a/events/api_views.py +++ b/events/api_views.py @@ -48,8 +48,8 @@ def get_context_data(self, **kwargs): if len(self.request.data) == 0 else self.request.data ) - queryset = self.model.objects.filter(company=self.request.company) - contacts = Contact.objects.filter(company=self.request.company) + queryset = self.model.objects.all() + contacts = Contact.objects.all() if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: queryset = queryset.filter( Q(assigned_to__in=[self.request.user]) | Q(created_by=self.request.user) @@ -102,18 +102,14 @@ def get_context_data(self, **kwargs): users = [] if self.request.user.role == "ADMIN" or self.request.user.is_superuser: users = User.objects.filter( - is_active=True, company=self.request.company + is_active=True, ).order_by("email") else: - users = User.objects.filter( - role="ADMIN", company=self.request.company - ).order_by("email") + users = User.objects.filter(role="ADMIN").order_by("email") context["recurring_days"] = WEEKDAYS context["users"] = UserSerializer(users, many=True).data if self.request.user == "ADMIN": - context["teams_list"] = TeamsSerializer( - Teams.objects.filter(company=self.request.company), many=True - ).data + context["teams_list"] = TeamsSerializer(Teams.objects.all(), many=True).data context["contacts_list"] = ContactSerializer(contacts, many=True).data return context @@ -142,7 +138,6 @@ def post(self, request, *args, **kwargs): if params.get("event_type") == "Non-Recurring": event_obj = serializer.save( created_by=request.user, - company=request.company, date_of_meeting=params.get("start_date"), is_active=True, disabled=False, @@ -150,40 +145,43 @@ def post(self, request, *args, **kwargs): if params.get("contacts"): contacts = json.loads(params.get("contacts")) for contact in contacts: - obj_contact = Contact.objects.filter( - id=contact, company=request.company - ) + obj_contact = Contact.objects.filter(id=contact) if obj_contact: event_obj.contacts.add(contact) else: event_obj.delete() data["contacts"] = "Please enter valid contact" - return Response({"error": True, "errors": data}) + return Response( + {"error": True, "errors": data}, + status=status.HTTP_400_BAD_REQUEST, + ) if self.request.user.role == "ADMIN": if params.get("teams"): teams = json.loads(params.get("teams")) for team in teams: - teams_ids = Teams.objects.filter( - id=team, company=request.company - ) + teams_ids = Teams.objects.filter(id=team) if teams_ids: event_obj.teams.add(team) else: event_obj.delete() data["team"] = "Please enter valid Team" - return Response({"error": True, "errors": data}) + return Response( + {"error": True, "errors": data}, + status=status.HTTP_400_BAD_REQUEST, + ) if params.get("assigned_to"): assinged_to_users_ids = json.loads(params.get("assigned_to")) for user_id in assinged_to_users_ids: - user = User.objects.filter( - id=user_id, company=request.company - ) + user = User.objects.filter(id=user_id) if user: event_obj.assigned_to.add(user_id) else: event_obj.delete() data["assigned_to"] = "Please enter valid User" - return Response({"error": True, "errors": data}) + return Response( + {"error": True, "errors": data}, + status=status.HTTP_400_BAD_REQUEST, + ) assigned_to_list = list( event_obj.assigned_to.all().values_list("id", flat=True) ) @@ -197,7 +195,8 @@ def post(self, request, *args, **kwargs): recurring_days = params.get("recurring_days") if not recurring_days: return Response( - {"error": True, "errors": "Choose atleast one recurring day"} + {"error": True, "errors": "Choose atleast one recurring day"}, + status=status.HTTP_400_BAD_REQUEST, ) end_date = datetime.strptime(end_date, "%Y-%m-%d").date() start_date = datetime.strptime(start_date, "%Y-%m-%d").date() @@ -224,48 +223,50 @@ def post(self, request, *args, **kwargs): start_time=data["start_time"], end_time=data["end_time"], date_of_meeting=each, - company=request.company, ) if params.get("contacts"): contacts = json.loads(params.get("contacts")) for contact in contacts: - obj_contact = Contact.objects.filter( - id=contact, company=request.company - ) + obj_contact = Contact.objects.filter(id=contact) if obj_contact: event.contacts.add(contact) else: event.delete() data["contacts"] = "Please enter valid contact" - return Response({"error": True, "errors": data}) + return Response( + {"error": True, "errors": data}, + status=status.HTTP_400_BAD_REQUEST, + ) if self.request.user.role == "ADMIN": if params.get("teams"): teams = json.loads(params.get("teams")) for team in teams: - teams_ids = Teams.objects.filter( - id=team, company=request.company - ) + teams_ids = Teams.objects.filter(id=team) if teams_ids: event.teams.add(team) else: event.delete() data["team"] = "Please enter valid Team" - return Response({"error": True, "errors": data}) + return Response( + {"error": True, "errors": data}, + status=status.HTTP_400_BAD_REQUEST, + ) if params.get("assigned_to"): assinged_to_users_ids = json.loads( params.get("assigned_to") ) for user_id in assinged_to_users_ids: - user = User.objects.filter( - id=user_id, company=request.company - ) + user = User.objects.filter(id=user_id) if user: event.assigned_to.add(user_id) else: event.delete() data["assigned_to"] = "Please enter valid User" - return Response({"error": True, "errors": data}) + return Response( + {"error": True, "errors": data}, + status=status.HTTP_400_BAD_REQUEST, + ) assigned_to_list = list( event.assigned_to.all().values_list("id", flat=True) ) @@ -306,7 +307,8 @@ def get_context_data(self, **kwargs): { "error": True, "errors": "You don't have Permission to perform this action", - } + }, + status=status.HTTP_403_FORBIDDEN, ) comments = Comment.objects.filter(event=self.event_obj).order_by("-id") @@ -315,7 +317,7 @@ def get_context_data(self, **kwargs): if self.request.user.is_superuser or self.request.user.role == "ADMIN": users_mention = list( User.objects.filter( - is_active=True, company=self.request.company + is_active=True, ).values("username") ) elif self.request.user != self.event_obj.created_by: @@ -324,11 +326,11 @@ def get_context_data(self, **kwargs): users_mention = list(self.event_obj.assigned_to.all().values("username")) if self.request.user.role == "ADMIN" or self.request.user.is_superuser: users = User.objects.filter( - is_active=True, company=self.request.company + is_active=True, ).order_by("email") else: users = User.objects.filter( - role="ADMIN", company=self.request.company + role="ADMIN", ).order_by("email") if self.request.user == self.event_obj.created_by: @@ -339,7 +341,8 @@ def get_context_data(self, **kwargs): { "error": True, "errors": "You don't have Permission to perform this action", - } + }, + status=status.HTTP_403_FORBIDDEN, ) team_ids = [user.id for user in self.event_obj.get_team_users] all_user_ids = users.values_list("id", flat=True) @@ -367,20 +370,14 @@ def get_context_data(self, **kwargs): context["users_excluding_team"] = UserSerializer( users_excluding_team, many=True ).data - context["teams"] = TeamsSerializer( - Teams.objects.filter(company=self.request.company), many=True - ).data + context["teams"] = TeamsSerializer(Teams.objects.all(), many=True).data return context @swagger_auto_schema( - tags=["Events"], manual_parameters=swagger_params.event_delete_params + tags=["Events"], ) def get(self, request, pk, **kwargs): self.event_obj = self.get_object(pk) - if self.event_obj.company != request.company: - return Response( - {"error": True, "errors": "User company doesnot match with header...."} - ) context = self.get_context_data(**kwargs) return Response(context) @@ -395,11 +392,6 @@ def post(self, request, pk, **kwargs): ) context = {} self.event_obj = Event.objects.get(pk=pk) - if self.event_obj.company != request.company: - return Response( - {"error": True, "errors": "User company does not match with header...."} - ) - if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: if not ( (self.request.user == self.event_obj.created_by) @@ -410,7 +402,7 @@ def post(self, request, pk, **kwargs): "error": True, "errors": "You don't have Permission to perform this action", }, - status=status.HTTP_401_UNAUTHORIZED, + status=status.HTTP_403_FORBIDDEN, ) comment_serializer = CommentSerializer(data=params) if comment_serializer.is_valid(): @@ -452,10 +444,6 @@ def put(self, request, pk, **kwargs): ) data = {} self.event_obj = self.get_object(pk) - if self.event_obj.company != request.company: - return Response( - {"error": True, "errors": "User company doesnot match with header...."} - ) serializer = EventCreateSerializer( data=params, instance=self.event_obj, @@ -473,28 +461,30 @@ def put(self, request, pk, **kwargs): if params.get("contacts"): contacts = json.loads(params.get("contacts")) for contact in contacts: - obj_contact = Contact.objects.filter( - id=contact, company=request.company - ) + obj_contact = Contact.objects.filter(id=contact) if obj_contact: event_obj.contacts.add(contact) else: data["contacts"] = "Please enter valid Contact" - return Response({"error": True, "errors": data}) + return Response( + {"error": True, "errors": data}, + status=status.HTTP_400_BAD_REQUEST, + ) if self.request.user.role == "ADMIN": event_obj.teams.clear() if params.get("teams"): teams = json.loads(params.get("teams")) for team in teams: - teams_ids = Teams.objects.filter( - id=team, company=request.company - ) + teams_ids = Teams.objects.filter(id=team) if teams_ids: event_obj.teams.add(team) else: event_obj.delete() data["team"] = "Please enter valid Team" - return Response({"error": True, "errors": data}) + return Response( + {"error": True, "errors": data}, + status=status.HTTP_400_BAD_REQUEST, + ) else: event_obj.teams.clear() @@ -502,13 +492,16 @@ def put(self, request, pk, **kwargs): if params.get("assigned_to"): assinged_to_users_ids = json.loads(params.get("assigned_to")) for user_id in assinged_to_users_ids: - user = User.objects.filter(id=user_id, company=request.company) + user = User.objects.filter(id=user_id) if user: event_obj.assigned_to.add(user_id) else: event_obj.delete() data["assigned_to"] = "Please enter valid User" - return Response({"error": True, "errors": data}) + return Response( + {"error": True, "errors": data}, + status=status.HTTP_400_BAD_REQUEST, + ) else: event_obj.assigned_to.clear() @@ -532,7 +525,7 @@ def put(self, request, pk, **kwargs): ) @swagger_auto_schema( - tags=["Events"], manual_parameters=swagger_params.event_delete_params + tags=["Events"], ) def delete(self, request, pk, **kwargs): self.object = self.get_object(pk) @@ -540,7 +533,7 @@ def delete(self, request, pk, **kwargs): request.user.role == "ADMIN" or request.user.is_superuser or request.user == self.object.created_by - ) and self.object.company == request.company: + ): self.object.delete() return Response( {"error": False, "message": "Event deleted Successfully"}, @@ -588,11 +581,12 @@ def put(self, request, pk, format=None): { "error": True, "errors": "You don't have Permission to perform this action", - } + }, + status=status.HTTP_403_FORBIDDEN, ) @swagger_auto_schema( - tags=["Events"], manual_parameters=swagger_params.event_delete_params + tags=["Events"], ) def delete(self, request, pk, format=None): self.object = self.get_object(pk) @@ -611,7 +605,8 @@ def delete(self, request, pk, format=None): { "error": True, "errors": "You don't have Permission to perform this action", - } + }, + status=status.HTTP_403_FORBIDDEN, ) @@ -621,7 +616,7 @@ class EventAttachmentView(APIView): permission_classes = (IsAuthenticated,) @swagger_auto_schema( - tags=["Events"], manual_parameters=swagger_params.event_delete_params + tags=["Events"], ) def delete(self, request, pk, format=None): self.object = self.model.objects.get(pk=pk) @@ -640,5 +635,6 @@ def delete(self, request, pk, format=None): { "error": True, "errors": "You don't have Permission to perform this action", - } + }, + status=status.HTTP_403_FORBIDDEN, ) diff --git a/events/forms.py b/events/forms.py deleted file mode 100644 index 656d41a..0000000 --- a/events/forms.py +++ /dev/null @@ -1,160 +0,0 @@ -from django import forms -from contacts.models import Contact -from common.models import User, Attachments, Comment -from django.db.models import Q -from events.models import Event -from teams.models import Teams - - -class EventForm(forms.ModelForm): - - WEEKDAYS = ( - ("Monday", "Monday"), - ("Tuesday", "Tuesday"), - ("Wednesday", "Wednesday"), - ("Thursday", "Thursday"), - ("Friday", "Friday"), - ("Saturday", "Saturday"), - ("Sunday", "Sunday"), - ) - - recurring_days = forms.MultipleChoiceField(required=False, choices=WEEKDAYS) - - teams_queryset = [] - teams = forms.MultipleChoiceField(choices=teams_queryset) - - def __init__(self, *args, **kwargs): - request_user = kwargs.pop("request_user", None) - request_obj = kwargs.pop("request_obj", None) - self.obj_instance = kwargs.get("instance", None) - super(EventForm, self).__init__(*args, **kwargs) - for field in self.fields.values(): - field.widget.attrs = {"class": "form-control"} - - if request_user.role == "ADMIN" or request_user.is_superuser: - self.fields["assigned_to"].queryset = User.objects.filter( - is_active=True, company=request_obj.company - ) - self.fields["contacts"].queryset = Contact.objects.filter( - company=request_obj.company - ) - self.fields["assigned_to"].required = True - self.fields["teams"].choices = [ - (team.get("id"), team.get("name")) - for team in Teams.objects.filter(company=request_obj.company).values( - "id", "name" - ) - ] - # elif request_user.google.all(): - # self.fields['assigned_to'].queryset = User.objects.none() - # self.fields["contacts"].queryset = Contact.objects.filter( - # Q(assigned_to__in=[request_user]) | Q(created_by=request_user)) - # self.fields['assigned_to'].required = False - elif request_user.role == "USER": - self.fields["assigned_to"].queryset = User.objects.filter( - role="ADMIN", company=request_obj.company - ) - self.fields["contacts"].queryset = Contact.objects.filter( - Q(assigned_to__in=[request_user]) | Q(created_by=request_user), - company=request_obj.company, - ) - self.fields["assigned_to"].required = True - else: - pass - if self.obj_instance: - # self.fields['name'].widget.attrs['readonly'] = True - self.fields["start_date"].widget.attrs["readonly"] = True - self.fields["end_date"].widget.attrs["readonly"] = True - - self.fields["teams"].required = False - self.fields["name"].required = True - self.fields["event_type"].required = True - self.fields["contacts"].required = True - self.fields["start_date"].required = True - self.fields["start_time"].required = True - self.fields["end_date"].required = True - self.fields["end_time"].required = True - self.fields["description"].required = False - - def clean_recurring_days(self): - recurring_days = self.cleaned_data.get("recurring_days") - if not self.obj_instance: - if self.cleaned_data.get("event_type") == "Recurring": - if len(recurring_days) < 1: - raise forms.ValidationError("Choose atleast one recurring day") - - def clean_name(self): - name = self.cleaned_data.get("name") - if not self.obj_instance: - if Event.objects.filter(name=name).exclude(id=self.instance.id).exists(): - raise forms.ValidationError("Event with this name already exists.") - - return name - - def clean_event_type(self): - """ This Validation Is For Keeping The Field Readonly While Editing or Updating""" - event_type = self.cleaned_data.get("event_type") - if self.obj_instance: - return self.obj_instance.event_type - else: - return event_type - - def clean_start_date(self): - start_date = self.cleaned_data.get("start_date") - if start_date: - if self.obj_instance: - return self.obj_instance.start_date - else: - return start_date - else: - raise forms.ValidationError("Enter a valid Start date.") - - def clean_end_date(self): - end_date = self.cleaned_data.get("end_date") - event_type = self.cleaned_data.get("event_type") - if event_type == "Recurring": - if self.clean_start_date() == end_date: - raise forms.ValidationError( - "Start Date and End Date cannot be equal for recurring events" - ) - if self.clean_start_date() > end_date: - raise forms.ValidationError("End Date cannot be less than start date") - return end_date - - def clean_end_time(self): - end_time = self.cleaned_data.get("end_time") - if not self.cleaned_data.get("start_time"): - raise forms.ValidationError("Enter a valid start time.") - if self.cleaned_data.get("start_time") > end_time: - raise forms.ValidationError("End Time cannot be less than Start Time") - return end_time - - class Meta: - model = Event - fields = ( - "name", - "event_type", - "contacts", - "assigned_to", - "start_date", - "start_time", - "end_date", - "end_time", - "description", - ) - - -class EventCommentForm(forms.ModelForm): - comment = forms.CharField(max_length=255, required=True) - - class Meta: - model = Comment - fields = ("comment", "event", "commented_by") - - -class EventAttachmentForm(forms.ModelForm): - attachment = forms.FileField(max_length=1001, required=True) - - class Meta: - model = Attachments - fields = ("attachment", "event") diff --git a/events/migrations/0005_remove_event_company.py b/events/migrations/0005_remove_event_company.py new file mode 100644 index 0000000..002af94 --- /dev/null +++ b/events/migrations/0005_remove_event_company.py @@ -0,0 +1,17 @@ +# Generated by Django 3.1.7 on 2021-03-24 08:50 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("events", "0004_event_company"), + ] + + operations = [ + migrations.RemoveField( + model_name="event", + name="company", + ), + ] diff --git a/events/models.py b/events/models.py index 908d07e..64e816e 100644 --- a/events/models.py +++ b/events/models.py @@ -3,7 +3,7 @@ from django.db import models from django.utils.translation import pgettext_lazy from django.utils.translation import ugettext_lazy as _ -from common.models import User, Company +from common.models import User from contacts.models import Contact from teams.models import Teams @@ -51,10 +51,6 @@ class Event(models.Model): date_of_meeting = models.DateField(blank=True, null=True) teams = models.ManyToManyField(Teams, related_name="event_teams") - company = models.ForeignKey( - Company, on_delete=models.SET_NULL, null=True, blank=True - ) - # tags = models.ManyToManyField(Tag) @property diff --git a/events/serializer.py b/events/serializer.py index af80ed1..efa7d27 100644 --- a/events/serializer.py +++ b/events/serializer.py @@ -4,7 +4,6 @@ UserSerializer, AttachmentsSerializer, CommentSerializer, - CompanySerializer, ) from contacts.serializer import ContactSerializer from teams.serializer import TeamsSerializer @@ -16,7 +15,6 @@ class EventSerializer(serializers.ModelSerializer): assigned_to = UserSerializer(read_only=True, many=True) contacts = ContactSerializer(read_only=True, many=True) teams = TeamsSerializer(read_only=True, many=True) - company = CompanySerializer() event_attachment = AttachmentsSerializer(read_only=True, many=True) event_comments = CommentSerializer(read_only=True, many=True) @@ -42,7 +40,6 @@ class Meta: "assigned_to", "event_attachment", "event_comments", - "company", ) @@ -51,18 +48,17 @@ def __init__(self, *args, **kwargs): request_obj = kwargs.pop("request_obj", None) super(EventCreateSerializer, self).__init__(*args, **kwargs) self.fields["event_type"].required = True - self.company = request_obj.company def validate_name(self, name): if self.instance: if ( - Event.objects.filter(name__iexact=name, company=self.company) + Event.objects.filter(name__iexact=name) .exclude(id=self.instance.id) .exists() ): raise serializers.ValidationError("Event already exists with this name") else: - if Event.objects.filter(name__iexact=name, company=self.company).exists(): + if Event.objects.filter(name__iexact=name).exists(): raise serializers.ValidationError("Event already exists with this name") return name @@ -125,5 +121,4 @@ class Meta: "description", "created_by", "created_on", - "company", ) diff --git a/events/swagger_params.py b/events/swagger_params.py index c08633d..1c90003 100644 --- a/events/swagger_params.py +++ b/events/swagger_params.py @@ -1,11 +1,6 @@ from drf_yasg import openapi -company_params_in_header = openapi.Parameter( - "company", openapi.IN_HEADER, required=True, type=openapi.TYPE_STRING -) - event_list_get_params = [ - company_params_in_header, openapi.Parameter("name", openapi.IN_QUERY, type=openapi.TYPE_STRING), openapi.Parameter("created_by", openapi.IN_QUERY, type=openapi.TYPE_STRING), openapi.Parameter("assigned_users", openapi.IN_QUERY, type=openapi.TYPE_STRING), @@ -18,7 +13,6 @@ ] event_detail_post_params = [ - company_params_in_header, openapi.Parameter( "event_attachment", openapi.IN_QUERY, @@ -27,12 +21,7 @@ openapi.Parameter("comment", openapi.IN_QUERY, type=openapi.TYPE_STRING), ] -event_delete_params = [ - company_params_in_header, -] - event_create_post_params = [ - company_params_in_header, openapi.Parameter( "name", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING ), @@ -72,6 +61,5 @@ ] event_comment_edit_params = [ - company_params_in_header, openapi.Parameter("comment", openapi.IN_QUERY, type=openapi.TYPE_STRING), ] diff --git a/events/tasks.py b/events/tasks.py index 8b67f9c..6ad5dbb 100644 --- a/events/tasks.py +++ b/events/tasks.py @@ -7,7 +7,6 @@ from common.models import User from contacts.models import Contact from events.models import Event -from marketing.models import BlockedDomain, BlockedEmail app = Celery("redis://") @@ -21,38 +20,29 @@ def send_email(event_id, recipients, domain="demo.django-crm.io", protocol="http context["event_id"] = event_id context["event_created_by"] = event.created_by context["event_date_of_meeting"] = event.date_of_meeting - context["url"] = ( - protocol + "://" + domain + reverse("events:detail_view", args=(event.id,)) - ) + context["url"] = protocol + "://" + domain # recipients = event.assigned_to.filter(is_active=True) - blocked_domains = BlockedDomain.objects.values_list("domain", flat=True) - blocked_emails = BlockedEmail.objects.values_list("email", flat=True) for user in recipients: recipients_list = [] user = User.objects.filter(id=user, is_active=True).first() if user: - if (user.email not in blocked_emails) and ( - user.email.split("@")[-1] not in blocked_domains - ): - recipients_list.append(user.email) - event_members = event.assigned_to.filter(is_active=True) + recipients_list.append(user.email) + event_members = event.assigned_to.filter(is_active=True) - context["other_members"] = list( - event_members.exclude(id=user.id).values_list("email", flat=True) - ) - if len(context["other_members"]) > 0: - context["other_members"] = ", ".join(context["other_members"]) - else: - context["other_members"] = "" - context["user"] = user.email - html_content = render_to_string( - "assigned_to_email_template_event.html", context=context - ) - msg = EmailMessage( - subject=subject, body=html_content, to=recipients_list - ) - msg.content_subtype = "html" - msg.send() + context["other_members"] = list( + event_members.exclude(id=user.id).values_list("email", flat=True) + ) + if len(context["other_members"]) > 0: + context["other_members"] = ", ".join(context["other_members"]) + else: + context["other_members"] = "" + context["user"] = user.email + html_content = render_to_string( + "assigned_to_email_template_event.html", context=context + ) + msg = EmailMessage(subject=subject, body=html_content, to=recipients_list) + msg.content_subtype = "html" + msg.send() # if recipients.count() > 0: # for recipient in recipients: diff --git a/events/templates/event_create.html b/events/templates/event_create.html deleted file mode 100644 index b4f1b64..0000000 --- a/events/templates/event_create.html +++ /dev/null @@ -1,452 +0,0 @@ -{% extends 'sales/base.html' %} -{% load static %} -{% block breadcrumb %} - -{% endblock %} -{% block content %} -
      -
      -
      -
      -
      -
      - {% if event_obj %}EDIT{% else %}CREATE{% endif %} EVENT -
      -
      -
      -
      -
      - - {{ form.name }} - {{ form.name.errors }} -
      -
      -
      -
      - - {{ form.event_type }} - {{ form.event_type.errors }} -
      -
      -
      -
      - - {{ form.contacts }} - {{ form.contacts.errors }} -
      -
      -
      -
      -
      -
      -
      - - {{ form.start_date }} - {{ form.start_date.errors }} -
      -
      -
      -
      - - {{ form.start_time }} - {{ form.start_time.errors }} -
      -
      -
      -
      - - {{ form.end_date }} - {{ form.end_date.errors }} -
      -
      -
      -
      - - {{ form.end_time }} - {{ form.end_time.errors }} -
      -
      -
      -
      -
      -
      -
      - {% if request.user.is_superuser or request.user.role == 'ADMIN' %} -
      -
      - - - {{ form.teams.errors }} -
      -
      - -
      -
      - - -
      -
      - - {% endif %} -
      -
      - - - {{ form.assigned_to.errors }} -
      -
      -
      -
      - - {{ form.description }} - {{ form.description.errors }} -
      -
      - {% if not event_obj %} -
      -

      Days

      -
      - - -
      -
      - - -
      -
      - - -
      -
      - - -
      -
      - - -
      -
      - - -
      -
      - - -
      -
      - -
      -
      - {% endif %} -
      -
      -
      -
      -
      - - Cancel -
      -
      -
      -
      -
      -
      - -
      - -
      -{% endblock %} -{% block js_block %} - - -{% endblock js_block %} \ No newline at end of file diff --git a/events/templates/event_detail.html b/events/templates/event_detail.html deleted file mode 100644 index ad64652..0000000 --- a/events/templates/event_detail.html +++ /dev/null @@ -1,498 +0,0 @@ -{% extends 'sales/base.html' %} -{% load static %} -{% load thumbnail %} -{% block breadcrumb %} -{% block extralinks %} - - -{% endblock extralinks %} - - -{% endblock breadcrumb %} -{% block content %} - -
      -
      -
      -
      -
      -
      -
      - Overview - - - -
      -
      -
      -
      - {% if event.name %} -
      -
      - - -
      -
      - {% endif %} - {% if event.event_type %} -
      -
      - - -
      -
      - {% endif %} - {% if event.start_date %} -
      -
      - - -
      -
      - {% endif %} - {% if event.end_date %} -
      -
      - - -
      -
      - {% endif %} -
      -
      -
      -
      - {% with contacts=event.contacts.all %} - - {% if contacts %} - {% for contact in contacts %} - - {% endfor %} - {% else %} - - {% endif %} - {% endwith %} -
      -
      - -
      -
      - {% with users=event.assigned_to.all %} - - {% if users %} - {% for user in users %} - - {% endfor %} - {% else %} - - {% endif %} - {% endwith %} -
      -
      - {% if event.start_time %} -
      -
      - - -
      -
      - {% endif %} - {% if event.end_time %} -
      -
      - - -
      -
      - {% endif %} -
      -
      - {% if event.description %} -
      -
      - - -
      -
      - {% endif %} - {% if event.date_of_meeting %} -
      -
      - - -
      -
      - {% endif %} -
      -
      -
      -
      -
      - Created by {{ event.created_by }} created on - {{ event.created_on_arrow }} -
      -
      -
      - -
      - -
      -
      -
      Attachments
      -
      -
      -
      -
      -
      - -
      - -
      -
      -
      - -
      -
      - -
      -
        - {% for attachment in attachments %} -
      • - {% if request.user.is_superuser or request.user.role == 'ADMIN' or request.user == attachment.created_by %} -
        -
        - -
        -
        - {% endif %} -
        - {% if attachment.attachment %} - {% if 'image' in attachment.file_type %} - {% thumbnail attachment.attachment "80x80" crop="center" as im %} - - {% endthumbnail %} - {% endif %} - {% endif %} -
          {{attachment.file_name}} Download
        -
        -
        -
        Uploaded by :{{ attachment.created_by }}
        -
        {{ attachment.created_on_arrow }}
        -
        -
      • - {% endfor %} -
      -
      -
      -
      - - -
      -
      -
      Comments
      -
      -
      -
      -
      -
      - -
      - -
      -
      -
      - -
      -
      - -
      -
        - {% for comment in comments %} -
      • - {% if request.user.is_superuser or request.user.role == 'ADMIN' or request.user == comment.commented_by %} -
        - - -
        - {% endif %} -
        -
        {{ comment.comment }}
        -
        -
        -
        {{ comment.commented_by }}
        -
        {{ comment.commented_on_arrow }}
        -
        -
      • - {% endfor %} -
      -
      -
      - -
      - -
      -
      -
      -
      -
      - -
      - Processing File... -
      -
      -
      -
      -
      -
      - - - - - -
      - - - - -{% endblock content %} -{% block js_block %} - - - -{% endblock js_block %} \ No newline at end of file diff --git a/events/templates/events_list.html b/events/templates/events_list.html deleted file mode 100644 index 21da54e..0000000 --- a/events/templates/events_list.html +++ /dev/null @@ -1,434 +0,0 @@ -{% extends 'sales/base.html' %} -{% load static %} -{% load paginate %} -{% load thumbnail %} -{% block extralinks %} - -{% endblock %} -{% block content %} - -
      - - - -
      -
      -
      -
      -
      -
      -
      Filters
      -
      -
      -
      - - -
      -
      -
      -
      - - -
      -
      -
      -
      - - -
      -
      -
      -
      - - -
      -
      -
      -
      - -
      -
      - -
      -
      - - Clear -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      - -
      -
      -
      -
      -
      - Events - {% if show_pageitems %} - {% show_pageitems %}{% else %} - {{ events|length }}{% endif %} - - - -
      -
      - - - {% if events|length > 0 %} - - - - - - - - - - - - - {% endif %} - - - {% if per_page %} - {% paginate per_page events %} - {% else %} - {% paginate 10 events %} - {% endif %} - {% for event in events %} - - - - - - - - - - - - - {% endfor %} - -
      IDNameContactsAssigned ToStart DateDate of MeetingEnd DateCreated OnCreated byActions
      {{ forloop.counter }} - {{ event.name }} - {% with contacts=event.contacts.all %} - {% if contacts %} - {% for contact in contacts %} - - {% empty %} - None - {% endfor %} - {% else %} -
      - None -
      - {% endif %} - {% endwith %} -
      - {% with users=event.get_team_and_assigned_users %} - {% for user in users %} - {% if user.profile_pic %} - {% thumbnail user.profile_pic "40x40" crop="center" as im %} - - - - {% endthumbnail %} - {% else %} - - - - {% endif %} - {% empty %} - None - {% endfor %} - {% endwith %} - {{ event.start_date }} {{ event.date_of_meeting }} {{ event.end_date }} {{ event.created_on_arrow }} - {% if event.created_by %} - {% if event.created_by.profile_pic %} - {% thumbnail event.created_by.profile_pic "40x40" crop="center" as im %} - - {% endthumbnail %} - {% else %} - Micro profile pic - {% endif %} - {% else %} - None - {% endif %} - - {% if request.user == event.created_by or request.user.role == 'ADMIN' or request.user.has_sales_access %} - - - - {% endif %} -
      -
      - {% ifequal events|length 0 %} -
      No Events Found
      - {% endifequal %} -
      - {% show_pages %} -
      -
      -
      -
      - - - -
      -
      -
      -
      -
      - - -{% for event in events %} - - - - - - - -{% endfor %} - -{% endblock %} -{% block js_block %} - - -{% endblock js_block %} diff --git a/events/tests.py b/events/tests.py deleted file mode 100644 index 50578c9..0000000 --- a/events/tests.py +++ /dev/null @@ -1,404 +0,0 @@ -from datetime import datetime, timedelta - -from django.core.files.uploadedfile import SimpleUploadedFile -from django.test import TestCase -from django.urls import reverse - -from common.models import Address, Attachments, Comment, User, Company -from contacts.models import Contact -from events.models import Event -from teams.models import Teams - - -class EventObjectTest(object): - def setUp(self): - self.company, _ = Company.objects.get_or_create( - name="test company", address="IN", sub_domain="test", country="IN" - ) - self.user = User.objects.create( - first_name="johnEvent", - username="johnDoeEvent", - email="johnDoeEvent@example.com", - role="ADMIN", - company=self.company, - ) - self.user.set_password("password") - self.user.save() - - self.user1 = User.objects.create( - first_name="janeEvent", - username="janeDoeEvent", - email="janeDoeEvent@example.com", - role="USER", - has_sales_access=True, - company=self.company, - ) - self.user1.set_password("password") - self.user1.save() - - self.user2 = User.objects.create( - first_name="joeEvent", - username="joeEvent", - email="joeEvent@example.com", - role="USER", - has_sales_access=True, - company=self.company, - ) - self.user2.set_password("password") - self.user2.save() - - self.team_dev = Teams.objects.create(name="events teams") - self.team_dev.users.add(self.user2.id) - - self.contact = Contact.objects.create( - first_name="contact event", - email="contact@event.com", - phone="12345", - description="contact", - created_by=self.user1, - ) - self.contact.assigned_to.add(self.user1) - - self.event = Event.objects.create( - name="event object test", - event_type="Non-Recurring", - start_date=(datetime.now()).strftime("%Y-%m-%d"), - start_time=(datetime.now()).strftime("%H:%M:%S"), - end_date=(datetime.now()).strftime("%Y-%m-%d"), - end_time=(datetime.now() + timedelta(hours=2)).strftime("%H:%M:%S"), - description="non recurring event", - created_by=self.user, - date_of_meeting=(datetime.now()).strftime("%Y-%m-%d"), - ) - self.event.contacts.add(self.contact) - self.event.assigned_to.add(self.user.id, self.user1.id) - - self.event_1 = Event.objects.create( - name="event object test check", - event_type="Non-Recurring", - start_date=(datetime.now()).strftime("%Y-%m-%d"), - start_time=(datetime.now()).strftime("%H:%M:%S"), - end_date=(datetime.now()).strftime("%Y-%m-%d"), - end_time=(datetime.now() + timedelta(hours=2)).strftime("%H:%M:%S"), - description="non recurring event", - created_by=self.user1, - ) - self.event_1.contacts.add(self.contact) - self.event_1.assigned_to.add(self.user2.id) - - self.comment = Comment.objects.create( - comment="test comment", event=self.event, commented_by=self.user - ) - self.attachment = Attachments.objects.create( - attachment="image.png", event=self.event, created_by=self.user - ) - - -class EventListTestCase(EventObjectTest, TestCase): - def test_events_list(self): - self.client.login(email="johnDoeEvent@example.com", password="password") - response = self.client.get(reverse("events:events_list")) - self.assertEqual(response.status_code, 200) - - self.client.login(email="janeDoeEvent@example.com", password="password") - response = self.client.get(reverse("events:events_list")) - self.assertEqual(response.status_code, 200) - - data = { - "event_name": "event name", - "created_by": self.user.id, - "assigned_to": self.user1.id, - "date_of_meeting": (datetime.now()).strftime("%Y-%m-%d"), - } - self.client.login(email="johnDoeEvent@example.com", password="password") - response = self.client.post(reverse("events:events_list"), data) - self.assertEqual(response.status_code, 200) - - self.client.login(email="janeDoeEvent@example.com", password="password") - response = self.client.post(reverse("events:events_list"), data) - self.assertEqual(response.status_code, 200) - - -class EventCreateTestCase(EventObjectTest, TestCase): - def test_events_create(self): - self.client.login(email="janeDoeEvent@example.com", password="password") - response = self.client.get(reverse("events:event_create")) - self.assertEqual(response.status_code, 200) - - self.client.login(email="johnDoeEvent@example.com", password="password") - response = self.client.get(reverse("events:event_create")) - self.assertEqual(response.status_code, 200) - - data = { - "event_name": "event name", - "event_type": "Non-Recurring", - "contacts": self.contact.id, - "teams": self.team_dev.id, - "assigned_to": self.user1.id, - "start_date": (datetime.now()).strftime("%Y-%m-%d"), - "start_time": (datetime.now()).strftime("%H:%M:%S"), - "end_date": (datetime.now()).strftime("%Y-%m-%d"), - "end_time": (datetime.now() + timedelta(hours=2)).strftime("%H:%M:%S"), - } - - response = self.client.post(reverse("events:event_create"), data) - self.assertEqual(response.status_code, 200) - data = {**data, "name": "event name"} - response = self.client.post(reverse("events:event_create"), data) - self.assertEqual(response.status_code, 200) - - data = { - **data, - "event_type": "Recurring", - "recurring_days": [ - "Monday", - "Tuesday", - "Wednesday", - "Thursday", - "Friday", - "Saturday", - "Sunday", - ], - } - response = self.client.post(reverse("events:event_create"), data) - self.assertEqual(response.status_code, 200) - - data = { - **data, - "name": "recurring event test", - "end_date": (datetime.now() + timedelta(days=7)).strftime("%Y-%m-%d"), - "start_date": (datetime.now()).strftime("%Y-%m-%d"), - } - response = self.client.post(reverse("events:event_create"), data) - self.assertEqual(response.status_code, 200) - - data = {**data, "event_type": "Recurring", "recurring_days": []} - response = self.client.post(reverse("events:event_create"), data) - self.assertEqual(response.status_code, 200) - - data = { - **data, - "name": "recurring event test", - "start_date": (datetime.now() + timedelta(days=7)).strftime("%Y-%m-%d"), - "end_date": (datetime.now()).strftime("%Y-%m-%d"), - } - response = self.client.post(reverse("events:event_create"), data) - self.assertEqual(response.status_code, 200) - - data = {**data, "event_type": "Recurring", "start_date": ""} - response = self.client.post(reverse("events:event_create"), data) - self.assertEqual(response.status_code, 200) - - data = {**data, "event_type": "Recurring", "start_time": ""} - response = self.client.post(reverse("events:event_create"), data) - self.assertEqual(response.status_code, 200) - - data = { - **data, - "event_type": "Recurring", - "start_time": (datetime.now() + timedelta(hours=2)).strftime("%H:%M:%S"), - "end_time": (datetime.now()).strftime("%H:%M:%S"), - } - response = self.client.post(reverse("events:event_create"), data) - self.assertEqual(response.status_code, 200) - - -class EventDetailTestCase(EventObjectTest, TestCase): - def test_events_detail(self): - self.client.login(email="johnDoeEvent@example.com", password="password") - response = self.client.get(reverse("events:detail_view", args=(self.event.id,))) - self.assertEqual(response.status_code, 200) - - self.client.login(email="janeDoeEvent@example.com", password="password") - response = self.client.get(reverse("events:detail_view", args=(self.event.id,))) - self.assertEqual(response.status_code, 200) - response = self.client.get( - reverse("events:detail_view", args=(self.event_1.id,)) - ) - self.assertEqual(response.status_code, 200) - - self.client.login(email="joeEvent@example.com", password="password") - response = self.client.get(reverse("events:detail_view", args=(self.event.id,))) - self.assertEqual(response.status_code, 403) - - -class EventEditTestCase(EventObjectTest, TestCase): - def test_events_edit(self): - self.client.login(email="janeDoeEvent@example.com", password="password") - response = self.client.get( - reverse("events:event_update", args=(self.event.id,)) - ) - self.assertEqual(response.status_code, 200) - - self.client.login(email="joeEvent@example.com", password="password") - response = self.client.get( - reverse("events:event_update", args=(self.event.id,)) - ) - self.assertEqual(response.status_code, 403) - - data = { - "event_name": "event name", - "event_type": "Non-Recurring", - "contacts": self.contact.id, - "teams": self.team_dev.id, - "assigned_to": self.user1.id, - "start_date": (datetime.now()).strftime("%Y-%m-%d"), - "start_time": (datetime.now()).strftime("%H:%M:%S"), - "end_date": (datetime.now()).strftime("%Y-%m-%d"), - "end_time": (datetime.now() + timedelta(hours=2)).strftime("%H:%M:%S"), - } - self.client.login(email="johnDoeEvent@example.com", password="password") - response = self.client.post( - reverse("events:event_update", args=(self.event.id,)), data - ) - self.assertEqual(response.status_code, 200) - - data = {**data, "name": "event object test edit"} - response = self.client.post( - reverse("events:event_update", args=(self.event.id,)), data - ) - self.assertEqual(response.status_code, 200) - - self.client.login(email="joeEvent@example.com", password="password") - response = self.client.post( - reverse("events:event_update", args=(self.event.id,)), data - ) - self.assertEqual(response.status_code, 200) - - self.client.login(email="johnDoeEvent@example.com", password="password") - new_data = { - "name": "event name edit object", - "event_type": "Recurring", - "contacts": self.contact.id, - "teams": self.team_dev.id, - "assigned_to": self.user1.id, - "end_date": (datetime.now() + timedelta(days=7)).strftime("%Y-%m-%d"), - "end_time": (datetime.now() + timedelta(hours=2)).strftime("%H:%M:%S"), - "start_time": (datetime.now()).strftime("%H:%M:%S"), - "start_date": (datetime.now()).strftime("%Y-%m-%d"), - "recurring_days": [ - "Monday", - "Tuesday", - "Wednesday", - "Thursday", - "Friday", - "Saturday", - "Sunday", - ], - } - response = self.client.post( - reverse("events:event_update", args=(self.event.id,)), new_data - ) - self.assertEqual(response.status_code, 200) - - -class AddCommentTestCase(EventObjectTest, TestCase): - def test_event_add_comment(self): - - self.client.login(email="johnDoeEvent@example.com", password="password") - data = { - "comment": "", - "event_id": self.event.id, - } - response = self.client.post(reverse("events:add_comment"), data) - self.assertEqual(response.status_code, 200) - - data = { - "comment": "test comment event", - "event_id": self.event.id, - } - response = self.client.post(reverse("events:add_comment"), data) - self.assertEqual(response.status_code, 200) - - self.client.login(email="janeDoeEvent@example.com", password="password") - response = self.client.post(reverse("events:add_comment"), data) - self.assertEqual(response.status_code, 200) - - -class UpdateCommentTestCase(EventObjectTest, TestCase): - def test_event_update_comment(self): - - self.client.login(email="johnDoeEvent@example.com", password="password") - data = {"commentid": self.comment.id, "event_id": self.event.id, "comment": ""} - response = self.client.post(reverse("events:edit_comment"), data) - self.assertEqual(response.status_code, 200) - - data = { - "comment": "test comment", - "commentid": self.comment.id, - "event_id": self.event.id, - } - response = self.client.post(reverse("events:edit_comment"), data) - self.assertEqual(response.status_code, 200) - - self.client.login(email="janeDoeEvent@example.com", password="password") - response = self.client.post(reverse("events:edit_comment"), data) - self.assertEqual(response.status_code, 200) - - -class DeleteCommentTestCase(EventObjectTest, TestCase): - def test_event_delete_comment(self): - - data = { - "comment_id": self.comment.id, - } - self.client.login(email="janeDoeEvent@example.com", password="password") - response = self.client.post(reverse("events:remove_comment"), data) - self.assertEqual(response.status_code, 200) - - self.client.login(email="johnDoeEvent@example.com", password="password") - response = self.client.post(reverse("events:remove_comment"), data) - self.assertEqual(response.status_code, 200) - - -class AddAttachmentTestCase(EventObjectTest, TestCase): - def test_event_add_attachment(self): - - data = { - "attachment": SimpleUploadedFile( - "file_name.txt", bytes("file contents.", "utf-8") - ), - "event_id": self.event.id, - } - self.client.login(email="johnDoeEvent@example.com", password="password") - response = self.client.post(reverse("events:add_attachment"), data) - self.assertEqual(response.status_code, 200) - - self.client.login(email="janeDoeEvent@example.com", password="password") - response = self.client.post(reverse("events:add_attachment"), data) - self.assertEqual(response.status_code, 200) - - data = {"attachment": "", "event_id": self.event.id} - self.client.login(email="johnDoeEvent@example.com", password="password") - response = self.client.post(reverse("events:add_attachment"), data) - self.assertEqual(response.status_code, 200) - - -class DeleteAttachmentTestCase(EventObjectTest, TestCase): - def test_invoice_delete_attachment(self): - - data = { - "attachment_id": self.attachment.id, - } - self.client.login(email="janeDoeEvent@example.com", password="password") - response = self.client.post(reverse("events:remove_attachment"), data) - self.assertEqual(response.status_code, 200) - - self.client.login(email="johnDoeEvent@example.com", password="password") - response = self.client.post(reverse("events:remove_attachment"), data) - self.assertEqual(response.status_code, 200) - - -class EventDeleteTestCase(EventObjectTest, TestCase): - def test_events_delete(self): - - self.client.login(email="janeDoeEvent@example.com", password="password") - response = self.client.get( - reverse("events:event_delete", args=(self.event.id,)) - ) - self.assertEqual(response.status_code, 403) - self.client.login(email="johnDoeEvent@example.com", password="password") - response = self.client.get( - reverse("events:event_delete", args=(self.event.id,)) - ) - self.assertEqual(response.status_code, 302) diff --git a/events/urls.py b/events/urls.py deleted file mode 100644 index baed470..0000000 --- a/events/urls.py +++ /dev/null @@ -1,21 +0,0 @@ -from django.urls import path -from events.views import * - -app_name = "events" - - -urlpatterns = [ - path("", events_list, name="events_list"), - path("create/", event_create, name="event_create"), - path("detail//", event_detail_view, name="detail_view"), - path("edit//", event_update, name="event_update"), - path("delete//", event_delete, name="event_delete"), - path("comment/add/", AddCommentView.as_view(), name="add_comment"), - path("comment/edit/", UpdateCommentView.as_view(), name="edit_comment"), - path("comment/remove/", DeleteCommentView.as_view(), name="remove_comment"), - path("attachment/add/", AddAttachmentView.as_view(), name="add_attachment"), - path( - "attachment/remove/", DeleteAttachmentsView.as_view(), name="remove_attachment" - ), - path("get_teams_and_users/", get_teams_and_users, name="get_teams_and_users"), -] diff --git a/events/views.py b/events/views.py deleted file mode 100644 index 41fd07d..0000000 --- a/events/views.py +++ /dev/null @@ -1,574 +0,0 @@ -from datetime import date, datetime, timedelta - -from django.contrib.auth.decorators import login_required -from django.contrib.auth.mixins import LoginRequiredMixin -from django.contrib.sites.shortcuts import get_current_site -from django.core.exceptions import PermissionDenied -from django.db.models import Q -from django.http import HttpResponse, JsonResponse -from django.shortcuts import get_object_or_404, redirect, render, reverse -from django.views.generic import ( - CreateView, - DeleteView, - DetailView, - FormView, - TemplateView, - UpdateView, - View, -) - -from common.models import Attachments, Comment, User -from common.tasks import send_email_user_mentions -from events.forms import EventAttachmentForm, EventCommentForm, EventForm -from events.models import Event -from events.tasks import send_email -from common.access_decorators_mixins import ( - sales_access_required, - marketing_access_required, - SalesAccessRequiredMixin, - MarketingAccessRequiredMixin, -) -from teams.models import Teams - - -@login_required -def get_teams_and_users(request): - data = {} - teams = Teams.objects.all() - teams_data = [ - {"team": team.id, "users": [user.id for user in team.users.all()]} - for team in teams - ] - users = User.objects.all().values_list("id", flat=True) - data["teams"] = teams_data - data["users"] = list(users) - return JsonResponse(data) - - -@login_required -@sales_access_required -def events_list(request): - - if request.user.role == "ADMIN" or request.user.is_superuser: - users = User.objects.all() - # elif request.user.google.all(): - # # users = User.objects.none() - # users = User.objects.filter(Q(role='ADMIN') | Q(id=request.user.id)) - elif request.user.role == "USER": - # users = User.objects.filter(role='ADMIN') - users = User.objects.filter(Q(role="ADMIN") | Q(id=request.user.id)) - else: - pass - - users = users.filter(company=request.company) - if request.method == "GET": - context = {} - if request.user.role == "ADMIN" or request.user.is_superuser: - events = Event.objects.all().distinct() - else: - events = Event.objects.filter( - Q(created_by=request.user) | Q(assigned_to=request.user) - ).distinct() - context["events"] = events.filter(company=request.company).order_by( - "-created_on" - ) - # context['status'] = status - context["users"] = users - user_ids = list(events.values_list("created_by", flat=True)) - user_ids.append(request.user.id) - context["created_by_users"] = users.filter( - is_active=True, id__in=user_ids, company=request.company - ) - return render(request, "events_list.html", context) - - if request.method == "POST": - context = {} - # context['status'] = status - context["users"] = users - events = Event.objects.filter() - if request.user.role == "ADMIN" or request.user.is_superuser: - events = events - else: - events = events.filter( - Q(created_by=request.user) | Q(assigned_to=request.user) - ).distinct() - - if request.POST.get("event_name", None): - events = events.filter(name__icontains=request.POST.get("event_name")) - - if request.POST.get("created_by", None): - events = events.filter(created_by__id=request.POST.get("created_by")) - - if request.POST.getlist("assigned_to", None): - events = events.filter(assigned_to__in=request.POST.getlist("assigned_to")) - context["assigned_to"] = request.POST.getlist("assigned_to") - - if request.POST.get("date_of_meeting", None): - events = events.filter(date_of_meeting=request.POST.get("date_of_meeting")) - - context["events"] = events.distinct().order_by("-created_on") - user_ids = list(events.values_list("created_by", flat=True)) - user_ids.append(request.user.id) - context["created_by_users"] = users.filter( - is_active=True, id__in=user_ids, company=request.company - ) - return render(request, "events_list.html", context) - - -@login_required -@sales_access_required -def event_create(request): - if request.method == "GET": - context = {} - context["form"] = EventForm(request_user=request.user, request_obj=request) - context["users"] = User.objects.filter(is_active=True, company=request.company) - if request.user.role == "ADMIN" or request.user.is_superuser: - context["teams"] = Teams.objects.filter(company=request.company) - return render(request, "event_create.html", context) - - if request.method == "POST": - form = EventForm(request.POST, request_user=request.user, request_obj=request) - if form.is_valid(): - start_date = form.cleaned_data.get("start_date") - end_date = form.cleaned_data.get("end_date") - # recurring_days - recurring_days = request.POST.getlist("recurring_days") - if form.cleaned_data.get("event_type") == "Non-Recurring": - event = form.save(commit=False) - event.date_of_meeting = start_date - event.created_by = request.user - event.company = request.company - event.save() - form.save_m2m() - if request.POST.getlist("teams", []): - user_ids = Teams.objects.filter( - id__in=request.POST.getlist("teams") - ).values_list("users", flat=True) - assinged_to_users_ids = event.assigned_to.all().values_list( - "id", flat=True - ) - for user_id in user_ids: - if user_id not in assinged_to_users_ids: - event.assigned_to.add(user_id) - - if request.POST.getlist("teams", []): - event.teams.add(*request.POST.getlist("teams")) - assigned_to_list = list( - event.assigned_to.all().values_list("id", flat=True) - ) - send_email.delay( - event.id, - assigned_to_list, - domain=request.get_host(), - protocol=request.scheme, - ) - - if form.cleaned_data.get("event_type") == "Recurring": - delta = end_date - start_date - all_dates = [] - required_dates = [] - - for day in range(delta.days + 1): - each_date = start_date + timedelta(days=day) - if each_date.strftime("%A") in recurring_days: - required_dates.append(each_date) - - for each in required_dates: - each = datetime.strptime(str(each), "%Y-%m-%d").date() - data = form.cleaned_data - - event = Event.objects.create( - created_by=request.user, - start_date=start_date, - end_date=end_date, - name=data["name"], - event_type=data["event_type"], - description=data["description"], - start_time=data["start_time"], - end_time=data["end_time"], - date_of_meeting=each, - company=request.company, - ) - event.contacts.add(*request.POST.getlist("contacts")) - event.assigned_to.add(*request.POST.getlist("assigned_to")) - if request.POST.getlist("teams", []): - user_ids = Teams.objects.filter( - id__in=request.POST.getlist("teams") - ).values_list("users", flat=True) - assinged_to_users_ids = event.assigned_to.all().values_list( - "id", flat=True - ) - for user_id in user_ids: - if user_id not in assinged_to_users_ids: - event.assigned_to.add(user_id) - - if request.POST.getlist("teams", []): - event.teams.add(*request.POST.getlist("teams")) - assigned_to_list = list( - event.assigned_to.all().values_list("id", flat=True) - ) - send_email.delay( - event.id, - assigned_to_list, - domain=request.get_host(), - protocol=request.scheme, - ) - - return JsonResponse( - {"error": False, "success_url": reverse("events:events_list")} - ) - else: - return JsonResponse( - { - "error": True, - "errors": form.errors, - } - ) - - -@login_required -@sales_access_required -def event_detail_view(request, event_id): - event = get_object_or_404(Event, pk=event_id) - if ( - not ( - request.user.role == "ADMIN" - or request.user.is_superuser - or event.created_by == request.user - or request.user in event.assigned_to.all() - ) - or request.company != event.company - ): - - raise PermissionDenied - - if request.method == "GET": - context = {} - context["event"] = event - context["attachments"] = event.events_attachment.all() - context["comments"] = event.events_comments.all() - if request.user.is_superuser or request.user.role == "ADMIN": - context["users_mention"] = list( - User.objects.filter(is_active=True, company=request.company).values( - "username" - ) - ) - elif request.user != event.created_by: - context["users_mention"] = [{"username": event.created_by.username}] - else: - context["users_mention"] = list(event.assigned_to.all().values("username")) - return render(request, "event_detail.html", context) - - -@login_required -@sales_access_required -def event_update(request, event_id): - event_obj = get_object_or_404(Event, pk=event_id) - if ( - not ( - request.user.role == "ADMIN" - or request.user.is_superuser - or event_obj.created_by == request.user - or request.user in event_obj.assigned_to.all() - ) - or request.company != event_obj.company - ): - raise PermissionDenied - - if request.method == "GET": - context = {} - context["event_obj"] = event_obj - context["users"] = User.objects.filter(is_active=True) - context["form"] = EventForm( - instance=event_obj, request_user=request.user, request_obj=request - ) - selected_recurring_days = Event.objects.filter(name=event_obj.name).values_list( - "date_of_meeting", flat=True - ) - selected_recurring_days = [ - day.strftime("%A") for day in selected_recurring_days - ] - context["selected_recurring_days"] = selected_recurring_days - if request.user.role == "ADMIN" or request.user.is_superuser: - context["teams"] = Teams.objects.filter(company=request.company) - return render(request, "event_create.html", context) - - if request.method == "POST": - form = EventForm( - request.POST, - instance=event_obj, - request_user=request.user, - request_obj=request, - ) - if form.is_valid(): - start_date = form.cleaned_data.get("start_date") - end_date = form.cleaned_data.get("end_date") - previous_assigned_to_users = list( - event_obj.assigned_to.all().values_list("id", flat=True) - ) - - # recurring_days - # recurring_days = request.POST.getlist('days') - if form.data.get("event_type") == "Non-Recurring": - event = form.save(commit=False) - event.date_of_meeting = start_date - # event.created_by = request.user - event.save() - form.save_m2m() - if request.POST.getlist("teams", []): - user_ids = Teams.objects.filter( - id__in=request.POST.getlist("teams") - ).values_list("users", flat=True) - assinged_to_users_ids = event.assigned_to.all().values_list( - "id", flat=True - ) - for user_id in user_ids: - if user_id not in assinged_to_users_ids: - event.assigned_to.add(user_id) - if request.POST.getlist("teams", []): - event.teams.clear() - event.teams.add(*request.POST.getlist("teams")) - else: - event.teams.clear() - assigned_to_list = list( - event.assigned_to.all().values_list("id", flat=True) - ) - recipients = list( - set(assigned_to_list) - set(previous_assigned_to_users) - ) - send_email.delay( - event.id, - recipients, - domain=request.get_host(), - protocol=request.scheme, - ) - - if form.data.get("event_type") == "Recurring": - event = form.save(commit=False) - event.save() - form.save_m2m() - if request.POST.getlist("teams", []): - user_ids = Teams.objects.filter( - id__in=request.POST.getlist("teams") - ).values_list("users", flat=True) - assinged_to_users_ids = event.assigned_to.all().values_list( - "id", flat=True - ) - for user_id in user_ids: - if user_id not in assinged_to_users_ids: - event.assigned_to.add(user_id) - if request.POST.getlist("teams", []): - event.teams.clear() - event.teams.add(*request.POST.getlist("teams")) - else: - event.teams.clear() - assigned_to_list = list( - event.assigned_to.all().values_list("id", flat=True) - ) - recipients = list( - set(assigned_to_list) - set(previous_assigned_to_users) - ) - send_email.delay( - event.id, - recipients, - domain=request.get_host(), - protocol=request.scheme, - ) - - # event.contacts.add(*request.POST.getlist('contacts')) - # event.assigned_to.add(*request.POST.getlist('assigned_to')) - - return JsonResponse( - {"error": False, "success_url": reverse("events:events_list")} - ) - else: - return JsonResponse( - { - "error": True, - "errors": form.errors, - } - ) - - -@login_required -@sales_access_required -def event_delete(request, event_id): - event = get_object_or_404(Event, pk=event_id) - if ( - not ( - request.user.role == "ADMIN" - or request.user.is_superuser - or event.created_by == request.user - ) - or request.company != event.company - ): - raise PermissionDenied - - event.delete() - return redirect("events:events_list") - - -class AddCommentView(LoginRequiredMixin, CreateView): - model = Comment - form_class = EventCommentForm - http_method_names = ["post"] - - def post(self, request, *args, **kwargs): - self.object = None - self.event = get_object_or_404(Event, id=request.POST.get("event_id")) - if ( - request.user == self.event.created_by - or request.user.is_superuser - or request.user.role == "ADMIN" - ): - form = self.get_form() - if form.is_valid(): - return self.form_valid(form) - return self.form_invalid(form) - - data = {"error": "You don't have permission to comment for this account."} - return JsonResponse(data) - - def form_valid(self, form): - comment = form.save(commit=False) - comment.commented_by = self.request.user - comment.event = self.event - comment.save() - comment_id = comment.id - current_site = get_current_site(self.request) - send_email_user_mentions.delay( - comment_id, - "events", - domain=current_site.domain, - protocol=self.request.scheme, - ) - return JsonResponse( - { - "comment_id": comment.id, - "comment": comment.comment, - "commented_on": comment.commented_on, - "commented_on_arrow": comment.commented_on_arrow, - "commented_by": comment.commented_by.email, - } - ) - - def form_invalid(self, form): - return JsonResponse({"error": form["comment"].errors}) - - -class UpdateCommentView(LoginRequiredMixin, View): - http_method_names = ["post"] - - def post(self, request, *args, **kwargs): - self.comment_obj = get_object_or_404(Comment, id=request.POST.get("commentid")) - if request.user == self.comment_obj.commented_by: - form = EventCommentForm(request.POST, instance=self.comment_obj) - if form.is_valid(): - return self.form_valid(form) - - return self.form_invalid(form) - - data = {"error": "You don't have permission to edit this comment."} - return JsonResponse(data) - - def form_valid(self, form): - self.comment_obj.comment = form.cleaned_data.get("comment") - self.comment_obj.save(update_fields=["comment"]) - comment_id = self.comment_obj.id - current_site = get_current_site(self.request) - send_email_user_mentions.delay( - comment_id, - "events", - domain=current_site.domain, - protocol=self.request.scheme, - ) - return JsonResponse( - { - "comment_id": self.comment_obj.id, - "comment": self.comment_obj.comment, - } - ) - - def form_invalid(self, form): - return JsonResponse({"error": form["comment"].errors}) - - -class DeleteCommentView(LoginRequiredMixin, View): - def post(self, request, *args, **kwargs): - self.object = get_object_or_404(Comment, id=request.POST.get("comment_id")) - if request.user == self.object.commented_by: - self.object.delete() - data = {"cid": request.POST.get("comment_id")} - return JsonResponse(data) - - data = {"error": "You don't have permission to delete this comment."} - return JsonResponse(data) - - -class AddAttachmentView(LoginRequiredMixin, CreateView): - model = Attachments - form_class = EventAttachmentForm - http_method_names = ["post"] - - def post(self, request, *args, **kwargs): - self.object = None - self.event = get_object_or_404(Event, id=request.POST.get("event_id")) - if ( - request.user == self.event.created_by - or request.user.is_superuser - or request.user.role == "ADMIN" - ): - form = self.get_form() - if form.is_valid(): - return self.form_valid(form) - - return self.form_invalid(form) - - data = { - "error": "You don't have permission to add attachment \ - for this account." - } - return JsonResponse(data) - - def form_valid(self, form): - attachment = form.save(commit=False) - attachment.created_by = self.request.user - attachment.file_name = attachment.attachment.name - attachment.event = self.event - attachment.save() - return JsonResponse( - { - "attachment_id": attachment.id, - "attachment": attachment.file_name, - "attachment_url": attachment.attachment.url, - "download_url": reverse( - "common:download_attachment", kwargs={"pk": attachment.id} - ), - "attachment_display": attachment.get_file_type_display(), - "created_on": attachment.created_on, - "created_on_arrow": attachment.created_on_arrow, - "created_by": attachment.created_by.email, - "file_type": attachment.file_type(), - } - ) - - def form_invalid(self, form): - return JsonResponse({"error": form["attachment"].errors}) - - -class DeleteAttachmentsView(LoginRequiredMixin, View): - def post(self, request, *args, **kwargs): - self.object = get_object_or_404( - Attachments, id=request.POST.get("attachment_id") - ) - if ( - request.user == self.object.created_by - or request.user.is_superuser - or request.user.role == "ADMIN" - ): - self.object.delete() - data = {"acd": request.POST.get("attachment_id")} - return JsonResponse(data) - - data = {"error": "You don't have permission to delete this attachment."} - return JsonResponse(data) diff --git a/invoices/api_views.py b/invoices/api_views.py index fabae90..0951d2b 100644 --- a/invoices/api_views.py +++ b/invoices/api_views.py @@ -39,6 +39,7 @@ from rest_framework.pagination import LimitOffsetPagination from drf_yasg.utils import swagger_auto_schema import json +from crm import settings INVOICE_STATUS = ( ("Draft", "Draft"), @@ -232,12 +233,11 @@ def post(self, request, *args, **kwargs): invoice_obj.assigned_to.all().values_list("id", flat=True) ) - current_site = get_current_site(request) recipients = assigned_to_list send_email.delay( recipients, invoice_obj.id, - domain=current_site.domain, + domain=settings.Domain, protocol=self.request.scheme, ) return Response({"error": False, "message": "Invoice Created Successfully"}) @@ -372,12 +372,11 @@ def put(self, request, pk, format=None): assigned_to_list = list( invoice_obj.assigned_to.all().values_list("id", flat=True) ) - current_site = get_current_site(self.request) recipients = list(set(assigned_to_list) - set(previous_assigned_to_users)) send_email.delay( recipients, invoice_obj.id, - domain=current_site.domain, + domain=settings.Domain, protocol=self.request.scheme, ) return Response( diff --git a/invoices/tasks.py b/invoices/tasks.py index 5aeb680..be138a6 100644 --- a/invoices/tasks.py +++ b/invoices/tasks.py @@ -6,7 +6,6 @@ from common.models import User from invoices.models import Invoice, InvoiceHistory -from marketing.models import BlockedDomain, BlockedEmail app = Celery("redis://") @@ -15,37 +14,30 @@ def send_email(invoice_id, recipients, domain="demo.django-crm.io", protocol="http"): invoice = Invoice.objects.filter(id=invoice_id).first() created_by = invoice.created_by - blocked_domains = BlockedDomain.objects.values_list("domain", flat=True) - blocked_emails = BlockedEmail.objects.values_list("email", flat=True) for user in recipients: recipients_list = [] user = User.objects.filter(id=user, is_active=True).first() if user: - if (user.email not in blocked_emails) and ( - user.email.split("@")[-1] not in blocked_domains - ): - recipients_list.append(user.email) - subject = "Shared an invoice with you." - context = {} - context["invoice_title"] = invoice.invoice_title - context["invoice_id"] = invoice_id - context["invoice_created_by"] = invoice.created_by - context["url"] = ( - protocol - + "://" - + domain - + reverse("invoices:invoice_details", args=(invoice.id,)) - ) + recipients_list.append(user.email) + subject = "Shared an invoice with you." + context = {} + context["invoice_title"] = invoice.invoice_title + context["invoice_id"] = invoice_id + context["invoice_created_by"] = invoice.created_by + context["url"] = ( + protocol + + "://" + + domain + + reverse("invoices:invoice_details", args=(invoice.id,)) + ) - context["user"] = user - html_content = render_to_string( - "assigned_to_email_template.html", context=context - ) - msg = EmailMessage( - subject=subject, body=html_content, to=recipients_list - ) - msg.content_subtype = "html" - msg.send() + context["user"] = user + html_content = render_to_string( + "assigned_to_email_template.html", context=context + ) + msg = EmailMessage(subject=subject, body=html_content, to=recipients_list) + msg.content_subtype = "html" + msg.send() recipients = invoice.accounts.filter(status="open") if recipients.count() > 0: subject = "Shared an invoice with you." diff --git a/invoices/urls.py b/invoices/urls.py index e53db5e..37c9117 100644 --- a/invoices/urls.py +++ b/invoices/urls.py @@ -1,33 +1,33 @@ -from django.urls import path -from invoices.views import * +# from django.urls import path +# from invoices.views import * -app_name = "invoices" +# app_name = "invoices" -urlpatterns = [ - path("", invoices_list, name="invoices_list"), - path("create/", invoices_create, name="invoices_create"), - path("detail//", invoice_details, name="invoice_details"), - path("edit//", invoice_edit, name="invoice_edit"), - path("delete//", invoice_delete, name="invoice_delete"), - path("download//", invoice_download, name="invoice_download"), - path("send-mail//", invoice_send_mail, name="invoice_send_mail"), - path( - "cancelled-mail//", - invoice_change_status_cancelled, - name="invoice_change_status_cancelled", - ), - path( - "paid-mail//", - invoice_change_status_paid, - name="invoice_change_status_paid", - ), - path("comment/add/", AddCommentView.as_view(), name="add_comment"), - path("comment/edit/", UpdateCommentView.as_view(), name="edit_comment"), - path("comment/remove/", DeleteCommentView.as_view(), name="remove_comment"), - path("attachment/add/", AddAttachmentView.as_view(), name="add_attachment"), - path( - "attachment/remove/", DeleteAttachmentsView.as_view(), name="remove_attachment" - ), - path("get_teams_and_users/", get_teams_and_users, name="get_teams_and_users"), -] +# urlpatterns = [ +# path("", invoices_list, name="invoices_list"), +# path("create/", invoices_create, name="invoices_create"), +# path("detail//", invoice_details, name="invoice_details"), +# path("edit//", invoice_edit, name="invoice_edit"), +# path("delete//", invoice_delete, name="invoice_delete"), +# path("download//", invoice_download, name="invoice_download"), +# path("send-mail//", invoice_send_mail, name="invoice_send_mail"), +# path( +# "cancelled-mail//", +# invoice_change_status_cancelled, +# name="invoice_change_status_cancelled", +# ), +# path( +# "paid-mail//", +# invoice_change_status_paid, +# name="invoice_change_status_paid", +# ), +# path("comment/add/", AddCommentView.as_view(), name="add_comment"), +# path("comment/edit/", UpdateCommentView.as_view(), name="edit_comment"), +# path("comment/remove/", DeleteCommentView.as_view(), name="remove_comment"), +# path("attachment/add/", AddAttachmentView.as_view(), name="add_attachment"), +# path( +# "attachment/remove/", DeleteAttachmentsView.as_view(), name="remove_attachment" +# ), +# path("get_teams_and_users/", get_teams_and_users, name="get_teams_and_users"), +# ] diff --git a/invoices/views.py b/invoices/views.py index 67cfbcc..d5ab029 100644 --- a/invoices/views.py +++ b/invoices/views.py @@ -1,678 +1,678 @@ -import io -import os - -import pdfkit -from datetime import datetime -from django.contrib.auth.decorators import login_required -from django.contrib.auth.mixins import LoginRequiredMixin -from django.contrib.sites.shortcuts import get_current_site -from django.core.exceptions import PermissionDenied -from django.db.models import Q -from django.http.response import HttpResponse, JsonResponse -from django.shortcuts import get_object_or_404, redirect, render, reverse -from django.template.loader import render_to_string -from django.views.generic import ( - CreateView, - DeleteView, - DetailView, - FormView, - TemplateView, - UpdateView, - View, -) - -from common.models import Address, Attachments, Comment, User -from common.tasks import send_email_user_mentions -from invoices.forms import ( - InvoiceAddressForm, - InvoiceAttachmentForm, - InvoiceCommentForm, - InvoiceForm, -) -from invoices.models import Invoice -from invoices.tasks import ( - send_email, - send_invoice_email, - send_invoice_email_cancel, - create_invoice_history, -) -from common.access_decorators_mixins import ( - sales_access_required, - marketing_access_required, - SalesAccessRequiredMixin, - MarketingAccessRequiredMixin, -) -from teams.models import Teams - - -@login_required -def get_teams_and_users(request): - data = {} - teams = Teams.objects.all() - teams_data = [ - {"team": team.id, "users": [user.id for user in team.users.all()]} - for team in teams - ] - users = User.objects.all().values_list("id", flat=True) - data["teams"] = teams_data - data["users"] = list(users) - return JsonResponse(data) - - -@login_required -@sales_access_required -def invoices_list(request): - - if request.user.role == "ADMIN" or request.user.is_superuser: - users = User.objects.all() - # elif request.user.google.all(): - # # users = User.objects.none() - # # users = User.objects.filter(id=request.user.id) - # users = User.objects.filter(Q(role='ADMIN') | Q(id=request.user.id)) - elif request.user.role == "USER": - users = User.objects.filter(Q(role="ADMIN") | Q(id=request.user.id)) - status = ( - ("Draft", "Draft"), - ("Sent", "Sent"), - ("Paid", "Paid"), - ("Pending", "Pending"), - ("Cancel", "Cancel"), - ) - - if request.method == "GET": - context = {} - if request.user.role == "ADMIN" or request.user.is_superuser: - invoices = Invoice.objects.all().distinct().order_by("-created_on") - else: - invoices = ( - Invoice.objects.filter( - Q(created_by=request.user) | Q(assigned_to=request.user) - ) - .distinct() - .order_by("-created_on") - ) - context["invoices"] = invoices.filter(company=request.company).order_by( - "-created_on" - ) - context["status"] = status - context["users"] = users.filter(company=request.company) - user_ids = list(invoices.values_list("created_by", flat=True)) - user_ids.append(request.user.id) - context["created_by_users"] = users.filter(is_active=True, id__in=user_ids) - today = datetime.today().date() - context["today"] = today - return render(request, "invoices_list.html", context) - - if request.method == "POST": - context = {} - context["status"] = status - context["users"] = users.filter(company=request.company) - invoices = Invoice.objects.filter(company=request.company).order_by( - "-created_on" - ) - if request.user.role == "ADMIN" or request.user.is_superuser: - invoices = invoices - else: - invoices = invoices.filter( - Q(created_by=request.user) | Q(assigned_to=request.user) - ).distinct() - - if request.POST.get("invoice_title_number", None): - invoices = invoices.filter( - Q(invoice_title__icontains=request.POST.get("invoice_title_number")) - | Q(invoice_number__icontains=request.POST.get("invoice_title_number")) - ) - - if request.POST.get("created_by", None): - invoices = invoices.filter(created_by__id=request.POST.get("created_by")) - - if request.POST.getlist("assigned_to", None): - invoices = invoices.filter( - assigned_to__in=request.POST.getlist("assigned_to") - ) - context["assigned_to"] = request.POST.getlist("assigned_to") - - if request.POST.get("status", None): - invoices = invoices.filter(status=request.POST.get("status")) - - if request.POST.get("total_amount", None): - invoices = invoices.filter(total_amount=request.POST.get("total_amount")) - - user_ids = list(invoices.values_list("created_by", flat=True)) - user_ids.append(request.user.id) - context["created_by_users"] = users.filter(is_active=True, id__in=user_ids) - context["invoices"] = invoices.distinct().order_by("-created_on") - today = datetime.today().date() - context["today"] = today - return render(request, "invoices_list.html", context) - - -@login_required -@sales_access_required -def invoices_create(request): - if request.method == "GET": - context = {} - context["form"] = InvoiceForm(request_user=request.user, request_obj=request) - context["users"] = User.objects.filter(company=request.company) - # "prefix" use case in form, both from address and to address use the - # same model and same model form, so the name attribute in the form will - # be same for the both forms and the address will be same for both - # shipping and to address, so use prefix parameter to distinguish the - # forms, don't remove this comment - context["from_address_form"] = InvoiceAddressForm(prefix="from") - context["to_address_form"] = InvoiceAddressForm(prefix="to") - if request.user.role == "ADMIN" or request.user.is_superuser: - context["teams"] = Teams.objects.filter(company=request.company) - - return render(request, "invoice_create_1.html", context) - - if request.method == "POST": - form = InvoiceForm(request.POST, request_user=request.user, request_obj=request) - from_address_form = InvoiceAddressForm(request.POST, prefix="from") - to_address_form = InvoiceAddressForm(request.POST, prefix="to") - if ( - form.is_valid() - and from_address_form.is_valid() - and to_address_form.is_valid() - ): - from_address_obj = from_address_form.save() - to_address_obj = to_address_form.save() - invoice_obj = form.save(commit=False) - invoice_obj.created_by = request.user - invoice_obj.company = request.company - invoice_obj.from_address = from_address_obj - invoice_obj.to_address = to_address_obj - invoice_obj.save() - form.save_m2m() - - if request.POST.getlist("teams", []): - user_ids = Teams.objects.filter( - id__in=request.POST.getlist("teams") - ).values_list("users", flat=True) - assinged_to_users_ids = invoice_obj.assigned_to.all().values_list( - "id", flat=True - ) - for user_id in user_ids: - if user_id not in assinged_to_users_ids: - invoice_obj.assigned_to.add(user_id) - - if request.POST.getlist("teams", []): - invoice_obj.teams.add(*request.POST.getlist("teams")) - - create_invoice_history(invoice_obj.id, request.user.id, []) - kwargs = {"domain": request.get_host(), "protocol": request.scheme} - assigned_to_list = list( - invoice_obj.assigned_to.all().values_list("id", flat=True) - ) - send_email.delay(invoice_obj.id, assigned_to_list, **kwargs) - if request.POST.get("from_account"): - return JsonResponse( - { - "error": False, - "success_url": reverse( - "accounts:view_account", - args=(request.POST.get("from_account"),), - ), - } - ) - return JsonResponse( - {"error": False, "success_url": reverse("invoices:invoices_list")} - ) - else: - return JsonResponse( - { - "error": True, - "errors": form.errors, - "from_address_errors": from_address_form.errors, - "to_address_errors": to_address_form.errors, - } - ) - - -@login_required -@sales_access_required -def invoice_details(request, invoice_id): - invoice = get_object_or_404( - Invoice.objects.select_related("from_address", "to_address"), pk=invoice_id - ) - - if invoice.company != request.company: - raise PermissionDenied - - user_assigned_account = False - user_assigned_accounts = set( - request.user.account_assigned_users.values_list("id", flat=True) - ) - invoice_accounts = set(invoice.accounts.values_list("id", flat=True)) - if user_assigned_accounts.intersection(invoice_accounts): - user_assigned_account = True - - if not ( - (request.user.role == "ADMIN") - or (request.user.is_superuser) - or (invoice.created_by == request.user) - or (request.user in invoice.assigned_to.all()) - or user_assigned_account - ): - raise PermissionDenied - - if request.method == "GET": - context = {} - context["invoice"] = invoice - context["attachments"] = invoice.invoice_attachment.all() - context["comments"] = invoice.invoice_comments.all() - context["invoice_history"] = invoice.invoice_history.all() - if request.user.is_superuser or request.user.role == "ADMIN": - context["users_mention"] = list( - User.objects.filter(is_active=True, company=request.company).values( - "username" - ) - ) - elif request.user != invoice.created_by: - context["users_mention"] = [{"username": invoice.created_by.username}] - else: - context["users_mention"] = list( - invoice.assigned_to.all().values("username") - ) - return render(request, "invoices_detail_1.html", context) - - -@login_required -@sales_access_required -def invoice_edit(request, invoice_id): - invoice_obj = get_object_or_404(Invoice, pk=invoice_id) - - if invoice_obj.company != request.company: - raise PermissionDenied - - if not ( - request.user.role == "ADMIN" - or request.user.is_superuser - or invoice_obj.created_by == request.user - or request.user in invoice_obj.assigned_to.all() - ): - raise PermissionDenied - - if request.method == "GET": - context = {} - context["invoice_obj"] = invoice_obj - context["teams"] = Teams.objects.filter(company=request.company) - context["users"] = User.objects.filter(company=request.company) - context["form"] = InvoiceForm( - instance=invoice_obj, request_user=request.user, request_obj=request - ) - context["from_address_form"] = InvoiceAddressForm( - prefix="from", instance=invoice_obj.from_address - ) - context["to_address_form"] = InvoiceAddressForm( - prefix="to", instance=invoice_obj.to_address - ) - return render(request, "invoice_create_1.html", context) - - if request.method == "POST": - form = InvoiceForm( - request.POST, - instance=invoice_obj, - request_user=request.user, - request_obj=request, - ) - from_address_form = InvoiceAddressForm( - request.POST, instance=invoice_obj.from_address, prefix="from" - ) - to_address_form = InvoiceAddressForm( - request.POST, instance=invoice_obj.to_address, prefix="to" - ) - previous_assigned_to_users = list( - invoice_obj.assigned_to.all().values_list("id", flat=True) - ) - if ( - form.is_valid() - and from_address_form.is_valid() - and to_address_form.is_valid() - ): - form_changed_data = form.changed_data - form_changed_data.remove("from_address") - form_changed_data.remove("to_address") - form_changed_data = form_changed_data + [ - "from_" + field for field in from_address_form.changed_data - ] - form_changed_data = form_changed_data + [ - "to_" + field for field in to_address_form.changed_data - ] - # if form_changed_data: - # create_invoice_history(invoice_obj.id, request.user.id, form_changed_data) - from_address_obj = from_address_form.save() - to_address_obj = to_address_form.save() - invoice_obj = form.save(commit=False) - invoice_obj.created_by = request.user - invoice_obj.from_address = from_address_obj - invoice_obj.to_address = to_address_obj - invoice_obj.save() - form.save_m2m() - if form_changed_data: - create_invoice_history( - invoice_obj.id, request.user.id, form_changed_data - ) - - if request.POST.getlist("teams", []): - user_ids = Teams.objects.filter( - id__in=request.POST.getlist("teams") - ).values_list("users", flat=True) - assinged_to_users_ids = invoice_obj.assigned_to.all().values_list( - "id", flat=True - ) - for user_id in user_ids: - if user_id not in assinged_to_users_ids: - invoice_obj.assigned_to.add(user_id) - - if request.POST.getlist("teams", []): - invoice_obj.teams.clear() - invoice_obj.teams.add(*request.POST.getlist("teams")) - else: - invoice_obj.teams.clear() - - kwargs = {"domain": request.get_host(), "protocol": request.scheme} - - assigned_to_list = list( - invoice_obj.assigned_to.all().values_list("id", flat=True) - ) - recipients = list(set(assigned_to_list) - set(previous_assigned_to_users)) - # send_email_to_assigned_user.delay(recipients, account_object.id, domain=current_site.domain, - # protocol=self.request.scheme) - - send_email.delay(invoice_obj.id, recipients, **kwargs) - if request.POST.get("from_account"): - return JsonResponse( - { - "error": False, - "success_url": reverse( - "accounts:view_account", - args=(request.POST.get("from_account"),), - ), - } - ) - return JsonResponse( - {"error": False, "success_url": reverse("invoices:invoices_list")} - ) - else: - return JsonResponse( - { - "error": True, - "errors": form.errors, - "from_address_errors": from_address_form.errors, - "to_address_errors": to_address_form.errors, - } - ) - - -@login_required -@sales_access_required -def invoice_delete(request, invoice_id): - invoice = get_object_or_404(Invoice, pk=invoice_id) - - if invoice.company != request.company: - raise PermissionDenied - - if not ( - request.user.role == "ADMIN" - or request.user.is_superuser - or invoice.created_by == request.user - ): - raise PermissionDenied - - if request.method == "GET": - invoice.delete() - if request.GET.get("view_account"): - return redirect( - reverse( - "accounts:view_account", args=(request.GET.get("view_account"),) - ) - ) - return redirect("invoices:invoices_list") - - -@login_required -@sales_access_required -def invoice_send_mail(request, invoice_id): - invoice = get_object_or_404(Invoice, pk=invoice_id) - if not ( - request.user.role == "ADMIN" - or request.user.is_superuser - or invoice.created_by == request.user - ): - raise PermissionDenied - - if request.method == "GET": - Invoice.objects.filter(id=invoice_id).update(is_email_sent=True, status="Sent") - kwargs = {"domain": request.get_host(), "protocol": request.scheme} - send_invoice_email.delay(invoice_id, **kwargs) - return redirect("invoices:invoices_list") - - -@login_required -@sales_access_required -def invoice_change_status_paid(request, invoice_id): - invoice = get_object_or_404(Invoice, pk=invoice_id) - if not ( - request.user.role == "ADMIN" - or request.user.is_superuser - or invoice.created_by == request.user - ): - raise PermissionDenied - - if request.method == "GET": - Invoice.objects.filter(id=invoice_id).update(status="Paid") - kwargs = {"domain": request.get_host(), "protocol": request.scheme} - # send_invoice_email.delay(invoice_id, **kwargs) - return redirect("invoices:invoices_list") - - -@login_required -@sales_access_required -def invoice_change_status_cancelled(request, invoice_id): - invoice = get_object_or_404(Invoice, pk=invoice_id) - if not ( - request.user.role == "ADMIN" - or request.user.is_superuser - or invoice.created_by == request.user - ): - raise PermissionDenied - - if request.method == "GET": - Invoice.objects.filter(id=invoice_id).update(status="Cancelled") - kwargs = {"domain": request.get_host(), "protocol": request.scheme} - send_invoice_email_cancel.delay(invoice_id, **kwargs) - return redirect("invoices:invoices_list") - - -@login_required -@sales_access_required -def invoice_download(request, invoice_id): - invoice = get_object_or_404( - Invoice.objects.select_related("from_address", "to_address"), pk=invoice_id - ) - if not ( - request.user.role == "ADMIN" - or request.user.is_superuser - or invoice.created_by == request.user - or request.user in invoice.assigned_to.all() - ): - raise PermissionDenied - - if request.method == "GET": - context = {} - context["invoice"] = invoice - html = render_to_string("invoice_download_pdf.html", context=context) - pdfkit.from_string(html, "out.pdf", options={"encoding": "UTF-8"}) - pdf = open("out.pdf", "rb") - response = HttpResponse(pdf.read(), content_type="application/pdf") - response["Content-Disposition"] = "attachment; filename=Invoice.pdf" - pdf.close() - os.remove("out.pdf") - return response - - -class AddCommentView(LoginRequiredMixin, CreateView): - model = Comment - form_class = InvoiceCommentForm - http_method_names = ["post"] - - def post(self, request, *args, **kwargs): - self.object = None - self.invoice = get_object_or_404(Invoice, id=request.POST.get("invoice_id")) - if ( - request.user == self.invoice.created_by - or request.user.is_superuser - or request.user.role == "ADMIN" - ): - form = self.get_form() - if form.is_valid(): - return self.form_valid(form) - return self.form_invalid(form) - - data = {"error": "You don't have permission to comment for this account."} - return JsonResponse(data) - - def form_valid(self, form): - comment = form.save(commit=False) - comment.commented_by = self.request.user - comment.invoice = self.invoice - comment.save() - comment_id = comment.id - current_site = get_current_site(self.request) - send_email_user_mentions.delay( - comment_id, - "invoices", - domain=current_site.domain, - protocol=self.request.scheme, - ) - return JsonResponse( - { - "comment_id": comment.id, - "comment": comment.comment, - "commented_on": comment.commented_on, - "commented_on_arrow": comment.commented_on_arrow, - "commented_by": comment.commented_by.email, - } - ) - - def form_invalid(self, form): - return JsonResponse({"error": form["comment"].errors}) - - -class UpdateCommentView(LoginRequiredMixin, View): - http_method_names = ["post"] - - def post(self, request, *args, **kwargs): - self.comment_obj = get_object_or_404(Comment, id=request.POST.get("commentid")) - if request.user == self.comment_obj.commented_by: - form = InvoiceCommentForm(request.POST, instance=self.comment_obj) - if form.is_valid(): - return self.form_valid(form) - - return self.form_invalid(form) - - data = {"error": "You don't have permission to edit this comment."} - return JsonResponse(data) - - def form_valid(self, form): - self.comment_obj.comment = form.cleaned_data.get("comment") - self.comment_obj.save(update_fields=["comment"]) - comment_id = self.comment_obj.id - current_site = get_current_site(self.request) - send_email_user_mentions.delay( - comment_id, - "invoices", - domain=current_site.domain, - protocol=self.request.scheme, - ) - return JsonResponse( - { - "comment_id": self.comment_obj.id, - "comment": self.comment_obj.comment, - } - ) - - def form_invalid(self, form): - return JsonResponse({"error": form["comment"].errors}) - - -class DeleteCommentView(LoginRequiredMixin, View): - def post(self, request, *args, **kwargs): - self.object = get_object_or_404(Comment, id=request.POST.get("comment_id")) - if request.user == self.object.commented_by: - self.object.delete() - data = {"cid": request.POST.get("comment_id")} - return JsonResponse(data) - - data = {"error": "You don't have permission to delete this comment."} - return JsonResponse(data) - - -class AddAttachmentView(LoginRequiredMixin, CreateView): - model = Attachments - form_class = InvoiceAttachmentForm - http_method_names = ["post"] - - def post(self, request, *args, **kwargs): - self.object = None - self.invoice = get_object_or_404(Invoice, id=request.POST.get("invoice_id")) - if ( - request.user == self.invoice.created_by - or request.user.is_superuser - or request.user.role == "ADMIN" - ): - form = self.get_form() - if form.is_valid(): - return self.form_valid(form) - - return self.form_invalid(form) - - data = { - "error": "You don't have permission to add attachment \ - for this account." - } - return JsonResponse(data) - - def form_valid(self, form): - attachment = form.save(commit=False) - attachment.created_by = self.request.user - attachment.file_name = attachment.attachment.name - attachment.invoice = self.invoice - attachment.save() - return JsonResponse( - { - "attachment_id": attachment.id, - "attachment": attachment.file_name, - "attachment_url": attachment.attachment.url, - "download_url": reverse( - "common:download_attachment", kwargs={"pk": attachment.id} - ), - "attachment_display": attachment.get_file_type_display(), - "created_on": attachment.created_on, - "created_on_arrow": attachment.created_on_arrow, - "created_by": attachment.created_by.email, - "file_type": attachment.file_type(), - } - ) - - def form_invalid(self, form): - return JsonResponse({"error": form["attachment"].errors}) - - -class DeleteAttachmentsView(LoginRequiredMixin, View): - def post(self, request, *args, **kwargs): - self.object = get_object_or_404( - Attachments, id=request.POST.get("attachment_id") - ) - if ( - request.user == self.object.created_by - or request.user.is_superuser - or request.user.role == "ADMIN" - ): - self.object.delete() - data = {"acd": request.POST.get("attachment_id")} - return JsonResponse(data) - - data = {"error": "You don't have permission to delete this attachment."} - return JsonResponse(data) +# import io +# import os + +# import pdfkit +# from datetime import datetime +# from django.contrib.auth.decorators import login_required +# from django.contrib.auth.mixins import LoginRequiredMixin +# from django.contrib.sites.shortcuts import get_current_site +# from django.core.exceptions import PermissionDenied +# from django.db.models import Q +# from django.http.response import HttpResponse, JsonResponse +# from django.shortcuts import get_object_or_404, redirect, render, reverse +# from django.template.loader import render_to_string +# from django.views.generic import ( +# CreateView, +# DeleteView, +# DetailView, +# FormView, +# TemplateView, +# UpdateView, +# View, +# ) + +# from common.models import Address, Attachments, Comment, User +# from common.tasks import send_email_user_mentions +# from invoices.forms import ( +# InvoiceAddressForm, +# InvoiceAttachmentForm, +# InvoiceCommentForm, +# InvoiceForm, +# ) +# from invoices.models import Invoice +# from invoices.tasks import ( +# send_email, +# send_invoice_email, +# send_invoice_email_cancel, +# create_invoice_history, +# ) +# from common.access_decorators_mixins import ( +# sales_access_required, +# marketing_access_required, +# SalesAccessRequiredMixin, +# MarketingAccessRequiredMixin, +# ) +# from teams.models import Teams + + +# @login_required +# def get_teams_and_users(request): +# data = {} +# teams = Teams.objects.all() +# teams_data = [ +# {"team": team.id, "users": [user.id for user in team.users.all()]} +# for team in teams +# ] +# users = User.objects.all().values_list("id", flat=True) +# data["teams"] = teams_data +# data["users"] = list(users) +# return JsonResponse(data) + + +# @login_required +# @sales_access_required +# def invoices_list(request): + +# if request.user.role == "ADMIN" or request.user.is_superuser: +# users = User.objects.all() +# # elif request.user.google.all(): +# # # users = User.objects.none() +# # # users = User.objects.filter(id=request.user.id) +# # users = User.objects.filter(Q(role='ADMIN') | Q(id=request.user.id)) +# elif request.user.role == "USER": +# users = User.objects.filter(Q(role="ADMIN") | Q(id=request.user.id)) +# status = ( +# ("Draft", "Draft"), +# ("Sent", "Sent"), +# ("Paid", "Paid"), +# ("Pending", "Pending"), +# ("Cancel", "Cancel"), +# ) + +# if request.method == "GET": +# context = {} +# if request.user.role == "ADMIN" or request.user.is_superuser: +# invoices = Invoice.objects.all().distinct().order_by("-created_on") +# else: +# invoices = ( +# Invoice.objects.filter( +# Q(created_by=request.user) | Q(assigned_to=request.user) +# ) +# .distinct() +# .order_by("-created_on") +# ) +# context["invoices"] = invoices.filter(company=request.company).order_by( +# "-created_on" +# ) +# context["status"] = status +# context["users"] = users.filter(company=request.company) +# user_ids = list(invoices.values_list("created_by", flat=True)) +# user_ids.append(request.user.id) +# context["created_by_users"] = users.filter(is_active=True, id__in=user_ids) +# today = datetime.today().date() +# context["today"] = today +# return render(request, "invoices_list.html", context) + +# if request.method == "POST": +# context = {} +# context["status"] = status +# context["users"] = users.filter(company=request.company) +# invoices = Invoice.objects.filter(company=request.company).order_by( +# "-created_on" +# ) +# if request.user.role == "ADMIN" or request.user.is_superuser: +# invoices = invoices +# else: +# invoices = invoices.filter( +# Q(created_by=request.user) | Q(assigned_to=request.user) +# ).distinct() + +# if request.POST.get("invoice_title_number", None): +# invoices = invoices.filter( +# Q(invoice_title__icontains=request.POST.get("invoice_title_number")) +# | Q(invoice_number__icontains=request.POST.get("invoice_title_number")) +# ) + +# if request.POST.get("created_by", None): +# invoices = invoices.filter(created_by__id=request.POST.get("created_by")) + +# if request.POST.getlist("assigned_to", None): +# invoices = invoices.filter( +# assigned_to__in=request.POST.getlist("assigned_to") +# ) +# context["assigned_to"] = request.POST.getlist("assigned_to") + +# if request.POST.get("status", None): +# invoices = invoices.filter(status=request.POST.get("status")) + +# if request.POST.get("total_amount", None): +# invoices = invoices.filter(total_amount=request.POST.get("total_amount")) + +# user_ids = list(invoices.values_list("created_by", flat=True)) +# user_ids.append(request.user.id) +# context["created_by_users"] = users.filter(is_active=True, id__in=user_ids) +# context["invoices"] = invoices.distinct().order_by("-created_on") +# today = datetime.today().date() +# context["today"] = today +# return render(request, "invoices_list.html", context) + + +# @login_required +# @sales_access_required +# def invoices_create(request): +# if request.method == "GET": +# context = {} +# context["form"] = InvoiceForm(request_user=request.user, request_obj=request) +# context["users"] = User.objects.filter(company=request.company) +# # "prefix" use case in form, both from address and to address use the +# # same model and same model form, so the name attribute in the form will +# # be same for the both forms and the address will be same for both +# # shipping and to address, so use prefix parameter to distinguish the +# # forms, don't remove this comment +# context["from_address_form"] = InvoiceAddressForm(prefix="from") +# context["to_address_form"] = InvoiceAddressForm(prefix="to") +# if request.user.role == "ADMIN" or request.user.is_superuser: +# context["teams"] = Teams.objects.filter(company=request.company) + +# return render(request, "invoice_create_1.html", context) + +# if request.method == "POST": +# form = InvoiceForm(request.POST, request_user=request.user, request_obj=request) +# from_address_form = InvoiceAddressForm(request.POST, prefix="from") +# to_address_form = InvoiceAddressForm(request.POST, prefix="to") +# if ( +# form.is_valid() +# and from_address_form.is_valid() +# and to_address_form.is_valid() +# ): +# from_address_obj = from_address_form.save() +# to_address_obj = to_address_form.save() +# invoice_obj = form.save(commit=False) +# invoice_obj.created_by = request.user +# invoice_obj.company = request.company +# invoice_obj.from_address = from_address_obj +# invoice_obj.to_address = to_address_obj +# invoice_obj.save() +# form.save_m2m() + +# if request.POST.getlist("teams", []): +# user_ids = Teams.objects.filter( +# id__in=request.POST.getlist("teams") +# ).values_list("users", flat=True) +# assinged_to_users_ids = invoice_obj.assigned_to.all().values_list( +# "id", flat=True +# ) +# for user_id in user_ids: +# if user_id not in assinged_to_users_ids: +# invoice_obj.assigned_to.add(user_id) + +# if request.POST.getlist("teams", []): +# invoice_obj.teams.add(*request.POST.getlist("teams")) + +# create_invoice_history(invoice_obj.id, request.user.id, []) +# kwargs = {"domain": request.get_host(), "protocol": request.scheme} +# assigned_to_list = list( +# invoice_obj.assigned_to.all().values_list("id", flat=True) +# ) +# send_email.delay(invoice_obj.id, assigned_to_list, **kwargs) +# if request.POST.get("from_account"): +# return JsonResponse( +# { +# "error": False, +# "success_url": reverse( +# "accounts:view_account", +# args=(request.POST.get("from_account"),), +# ), +# } +# ) +# return JsonResponse( +# {"error": False, "success_url": reverse("invoices:invoices_list")} +# ) +# else: +# return JsonResponse( +# { +# "error": True, +# "errors": form.errors, +# "from_address_errors": from_address_form.errors, +# "to_address_errors": to_address_form.errors, +# } +# ) + + +# @login_required +# @sales_access_required +# def invoice_details(request, invoice_id): +# invoice = get_object_or_404( +# Invoice.objects.select_related("from_address", "to_address"), pk=invoice_id +# ) + +# if invoice.company != request.company: +# raise PermissionDenied + +# user_assigned_account = False +# user_assigned_accounts = set( +# request.user.account_assigned_users.values_list("id", flat=True) +# ) +# invoice_accounts = set(invoice.accounts.values_list("id", flat=True)) +# if user_assigned_accounts.intersection(invoice_accounts): +# user_assigned_account = True + +# if not ( +# (request.user.role == "ADMIN") +# or (request.user.is_superuser) +# or (invoice.created_by == request.user) +# or (request.user in invoice.assigned_to.all()) +# or user_assigned_account +# ): +# raise PermissionDenied + +# if request.method == "GET": +# context = {} +# context["invoice"] = invoice +# context["attachments"] = invoice.invoice_attachment.all() +# context["comments"] = invoice.invoice_comments.all() +# context["invoice_history"] = invoice.invoice_history.all() +# if request.user.is_superuser or request.user.role == "ADMIN": +# context["users_mention"] = list( +# User.objects.filter(is_active=True, company=request.company).values( +# "username" +# ) +# ) +# elif request.user != invoice.created_by: +# context["users_mention"] = [{"username": invoice.created_by.username}] +# else: +# context["users_mention"] = list( +# invoice.assigned_to.all().values("username") +# ) +# return render(request, "invoices_detail_1.html", context) + + +# @login_required +# @sales_access_required +# def invoice_edit(request, invoice_id): +# invoice_obj = get_object_or_404(Invoice, pk=invoice_id) + +# if invoice_obj.company != request.company: +# raise PermissionDenied + +# if not ( +# request.user.role == "ADMIN" +# or request.user.is_superuser +# or invoice_obj.created_by == request.user +# or request.user in invoice_obj.assigned_to.all() +# ): +# raise PermissionDenied + +# if request.method == "GET": +# context = {} +# context["invoice_obj"] = invoice_obj +# context["teams"] = Teams.objects.filter(company=request.company) +# context["users"] = User.objects.filter(company=request.company) +# context["form"] = InvoiceForm( +# instance=invoice_obj, request_user=request.user, request_obj=request +# ) +# context["from_address_form"] = InvoiceAddressForm( +# prefix="from", instance=invoice_obj.from_address +# ) +# context["to_address_form"] = InvoiceAddressForm( +# prefix="to", instance=invoice_obj.to_address +# ) +# return render(request, "invoice_create_1.html", context) + +# if request.method == "POST": +# form = InvoiceForm( +# request.POST, +# instance=invoice_obj, +# request_user=request.user, +# request_obj=request, +# ) +# from_address_form = InvoiceAddressForm( +# request.POST, instance=invoice_obj.from_address, prefix="from" +# ) +# to_address_form = InvoiceAddressForm( +# request.POST, instance=invoice_obj.to_address, prefix="to" +# ) +# previous_assigned_to_users = list( +# invoice_obj.assigned_to.all().values_list("id", flat=True) +# ) +# if ( +# form.is_valid() +# and from_address_form.is_valid() +# and to_address_form.is_valid() +# ): +# form_changed_data = form.changed_data +# form_changed_data.remove("from_address") +# form_changed_data.remove("to_address") +# form_changed_data = form_changed_data + [ +# "from_" + field for field in from_address_form.changed_data +# ] +# form_changed_data = form_changed_data + [ +# "to_" + field for field in to_address_form.changed_data +# ] +# # if form_changed_data: +# # create_invoice_history(invoice_obj.id, request.user.id, form_changed_data) +# from_address_obj = from_address_form.save() +# to_address_obj = to_address_form.save() +# invoice_obj = form.save(commit=False) +# invoice_obj.created_by = request.user +# invoice_obj.from_address = from_address_obj +# invoice_obj.to_address = to_address_obj +# invoice_obj.save() +# form.save_m2m() +# if form_changed_data: +# create_invoice_history( +# invoice_obj.id, request.user.id, form_changed_data +# ) + +# if request.POST.getlist("teams", []): +# user_ids = Teams.objects.filter( +# id__in=request.POST.getlist("teams") +# ).values_list("users", flat=True) +# assinged_to_users_ids = invoice_obj.assigned_to.all().values_list( +# "id", flat=True +# ) +# for user_id in user_ids: +# if user_id not in assinged_to_users_ids: +# invoice_obj.assigned_to.add(user_id) + +# if request.POST.getlist("teams", []): +# invoice_obj.teams.clear() +# invoice_obj.teams.add(*request.POST.getlist("teams")) +# else: +# invoice_obj.teams.clear() + +# kwargs = {"domain": request.get_host(), "protocol": request.scheme} + +# assigned_to_list = list( +# invoice_obj.assigned_to.all().values_list("id", flat=True) +# ) +# recipients = list(set(assigned_to_list) - set(previous_assigned_to_users)) +# # send_email_to_assigned_user.delay(recipients, account_object.id, domain=current_site.domain, +# # protocol=self.request.scheme) + +# send_email.delay(invoice_obj.id, recipients, **kwargs) +# if request.POST.get("from_account"): +# return JsonResponse( +# { +# "error": False, +# "success_url": reverse( +# "accounts:view_account", +# args=(request.POST.get("from_account"),), +# ), +# } +# ) +# return JsonResponse( +# {"error": False, "success_url": reverse("invoices:invoices_list")} +# ) +# else: +# return JsonResponse( +# { +# "error": True, +# "errors": form.errors, +# "from_address_errors": from_address_form.errors, +# "to_address_errors": to_address_form.errors, +# } +# ) + + +# @login_required +# @sales_access_required +# def invoice_delete(request, invoice_id): +# invoice = get_object_or_404(Invoice, pk=invoice_id) + +# if invoice.company != request.company: +# raise PermissionDenied + +# if not ( +# request.user.role == "ADMIN" +# or request.user.is_superuser +# or invoice.created_by == request.user +# ): +# raise PermissionDenied + +# if request.method == "GET": +# invoice.delete() +# if request.GET.get("view_account"): +# return redirect( +# reverse( +# "accounts:view_account", args=(request.GET.get("view_account"),) +# ) +# ) +# return redirect("invoices:invoices_list") + + +# @login_required +# @sales_access_required +# def invoice_send_mail(request, invoice_id): +# invoice = get_object_or_404(Invoice, pk=invoice_id) +# if not ( +# request.user.role == "ADMIN" +# or request.user.is_superuser +# or invoice.created_by == request.user +# ): +# raise PermissionDenied + +# if request.method == "GET": +# Invoice.objects.filter(id=invoice_id).update(is_email_sent=True, status="Sent") +# kwargs = {"domain": request.get_host(), "protocol": request.scheme} +# send_invoice_email.delay(invoice_id, **kwargs) +# return redirect("invoices:invoices_list") + + +# @login_required +# @sales_access_required +# def invoice_change_status_paid(request, invoice_id): +# invoice = get_object_or_404(Invoice, pk=invoice_id) +# if not ( +# request.user.role == "ADMIN" +# or request.user.is_superuser +# or invoice.created_by == request.user +# ): +# raise PermissionDenied + +# if request.method == "GET": +# Invoice.objects.filter(id=invoice_id).update(status="Paid") +# kwargs = {"domain": request.get_host(), "protocol": request.scheme} +# # send_invoice_email.delay(invoice_id, **kwargs) +# return redirect("invoices:invoices_list") + + +# @login_required +# @sales_access_required +# def invoice_change_status_cancelled(request, invoice_id): +# invoice = get_object_or_404(Invoice, pk=invoice_id) +# if not ( +# request.user.role == "ADMIN" +# or request.user.is_superuser +# or invoice.created_by == request.user +# ): +# raise PermissionDenied + +# if request.method == "GET": +# Invoice.objects.filter(id=invoice_id).update(status="Cancelled") +# kwargs = {"domain": request.get_host(), "protocol": request.scheme} +# send_invoice_email_cancel.delay(invoice_id, **kwargs) +# return redirect("invoices:invoices_list") + + +# @login_required +# @sales_access_required +# def invoice_download(request, invoice_id): +# invoice = get_object_or_404( +# Invoice.objects.select_related("from_address", "to_address"), pk=invoice_id +# ) +# if not ( +# request.user.role == "ADMIN" +# or request.user.is_superuser +# or invoice.created_by == request.user +# or request.user in invoice.assigned_to.all() +# ): +# raise PermissionDenied + +# if request.method == "GET": +# context = {} +# context["invoice"] = invoice +# html = render_to_string("invoice_download_pdf.html", context=context) +# pdfkit.from_string(html, "out.pdf", options={"encoding": "UTF-8"}) +# pdf = open("out.pdf", "rb") +# response = HttpResponse(pdf.read(), content_type="application/pdf") +# response["Content-Disposition"] = "attachment; filename=Invoice.pdf" +# pdf.close() +# os.remove("out.pdf") +# return response + + +# class AddCommentView(LoginRequiredMixin, CreateView): +# model = Comment +# form_class = InvoiceCommentForm +# http_method_names = ["post"] + +# def post(self, request, *args, **kwargs): +# self.object = None +# self.invoice = get_object_or_404(Invoice, id=request.POST.get("invoice_id")) +# if ( +# request.user == self.invoice.created_by +# or request.user.is_superuser +# or request.user.role == "ADMIN" +# ): +# form = self.get_form() +# if form.is_valid(): +# return self.form_valid(form) +# return self.form_invalid(form) + +# data = {"error": "You don't have permission to comment for this account."} +# return JsonResponse(data) + +# def form_valid(self, form): +# comment = form.save(commit=False) +# comment.commented_by = self.request.user +# comment.invoice = self.invoice +# comment.save() +# comment_id = comment.id +# current_site = get_current_site(self.request) +# send_email_user_mentions.delay( +# comment_id, +# "invoices", +# domain=current_site.domain, +# protocol=self.request.scheme, +# ) +# return JsonResponse( +# { +# "comment_id": comment.id, +# "comment": comment.comment, +# "commented_on": comment.commented_on, +# "commented_on_arrow": comment.commented_on_arrow, +# "commented_by": comment.commented_by.email, +# } +# ) + +# def form_invalid(self, form): +# return JsonResponse({"error": form["comment"].errors}) + + +# class UpdateCommentView(LoginRequiredMixin, View): +# http_method_names = ["post"] + +# def post(self, request, *args, **kwargs): +# self.comment_obj = get_object_or_404(Comment, id=request.POST.get("commentid")) +# if request.user == self.comment_obj.commented_by: +# form = InvoiceCommentForm(request.POST, instance=self.comment_obj) +# if form.is_valid(): +# return self.form_valid(form) + +# return self.form_invalid(form) + +# data = {"error": "You don't have permission to edit this comment."} +# return JsonResponse(data) + +# def form_valid(self, form): +# self.comment_obj.comment = form.cleaned_data.get("comment") +# self.comment_obj.save(update_fields=["comment"]) +# comment_id = self.comment_obj.id +# current_site = get_current_site(self.request) +# send_email_user_mentions.delay( +# comment_id, +# "invoices", +# domain=current_site.domain, +# protocol=self.request.scheme, +# ) +# return JsonResponse( +# { +# "comment_id": self.comment_obj.id, +# "comment": self.comment_obj.comment, +# } +# ) + +# def form_invalid(self, form): +# return JsonResponse({"error": form["comment"].errors}) + + +# class DeleteCommentView(LoginRequiredMixin, View): +# def post(self, request, *args, **kwargs): +# self.object = get_object_or_404(Comment, id=request.POST.get("comment_id")) +# if request.user == self.object.commented_by: +# self.object.delete() +# data = {"cid": request.POST.get("comment_id")} +# return JsonResponse(data) + +# data = {"error": "You don't have permission to delete this comment."} +# return JsonResponse(data) + + +# class AddAttachmentView(LoginRequiredMixin, CreateView): +# model = Attachments +# form_class = InvoiceAttachmentForm +# http_method_names = ["post"] + +# def post(self, request, *args, **kwargs): +# self.object = None +# self.invoice = get_object_or_404(Invoice, id=request.POST.get("invoice_id")) +# if ( +# request.user == self.invoice.created_by +# or request.user.is_superuser +# or request.user.role == "ADMIN" +# ): +# form = self.get_form() +# if form.is_valid(): +# return self.form_valid(form) + +# return self.form_invalid(form) + +# data = { +# "error": "You don't have permission to add attachment \ +# for this account." +# } +# return JsonResponse(data) + +# def form_valid(self, form): +# attachment = form.save(commit=False) +# attachment.created_by = self.request.user +# attachment.file_name = attachment.attachment.name +# attachment.invoice = self.invoice +# attachment.save() +# return JsonResponse( +# { +# "attachment_id": attachment.id, +# "attachment": attachment.file_name, +# "attachment_url": attachment.attachment.url, +# "download_url": reverse( +# "common:download_attachment", kwargs={"pk": attachment.id} +# ), +# "attachment_display": attachment.get_file_type_display(), +# "created_on": attachment.created_on, +# "created_on_arrow": attachment.created_on_arrow, +# "created_by": attachment.created_by.email, +# "file_type": attachment.file_type(), +# } +# ) + +# def form_invalid(self, form): +# return JsonResponse({"error": form["attachment"].errors}) + + +# class DeleteAttachmentsView(LoginRequiredMixin, View): +# def post(self, request, *args, **kwargs): +# self.object = get_object_or_404( +# Attachments, id=request.POST.get("attachment_id") +# ) +# if ( +# request.user == self.object.created_by +# or request.user.is_superuser +# or request.user.role == "ADMIN" +# ): +# self.object.delete() +# data = {"acd": request.POST.get("attachment_id")} +# return JsonResponse(data) + +# data = {"error": "You don't have permission to delete this attachment."} +# return JsonResponse(data) diff --git a/leads/api_urls.py b/leads/api_urls.py index c42afb1..eb6dd99 100644 --- a/leads/api_urls.py +++ b/leads/api_urls.py @@ -4,6 +4,11 @@ app_name = "api_leads" urlpatterns = [ + path( + "create-from-site/", + api_views.CreateLeadFromSite.as_view(), + name="create_lead_from_site", + ), path("", api_views.LeadListView.as_view()), path("/", api_views.LeadDetailView.as_view()), path("upload/", api_views.LeadUploadView.as_view()), diff --git a/leads/api_views.py b/leads/api_views.py index 7234a2d..9bc102c 100644 --- a/leads/api_views.py +++ b/leads/api_views.py @@ -1,10 +1,12 @@ from django.contrib.sites.shortcuts import get_current_site from django.core.exceptions import PermissionDenied from django.db.models import Q +from django.shortcuts import get_object_or_404 from accounts.models import Account, Tags from accounts.tasks import send_email_to_assigned_user +from contacts.models import Contact from leads import swagger_params -from common.models import User, Attachments, Comment +from common.models import User, Attachments, Comment, APISettings from common.utils import COUNTRIES, LEAD_SOURCE, LEAD_STATUS from common.custom_auth import JSONWebTokenAuthentication from common.serializer import ( @@ -28,11 +30,14 @@ from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.permissions import IsAuthenticated +from rest_framework.pagination import LimitOffsetPagination +from rest_framework.decorators import api_view from drf_yasg.utils import swagger_auto_schema import json +from crm import settings -class LeadListView(APIView): +class LeadListView(APIView, LimitOffsetPagination): model = Lead authentication_classes = (JSONWebTokenAuthentication,) permission_classes = (IsAuthenticated,) @@ -44,7 +49,7 @@ def get_context_data(self, **kwargs): else self.request.data ) queryset = ( - self.model.objects.filter(company=self.request.company) + self.model.objects.all() .exclude(status="converted") .select_related("created_by") .prefetch_related( @@ -93,26 +98,46 @@ def get_context_data(self, **kwargs): ): search = True context["search"] = search - open_leads = queryset.exclude(status="closed").distinct() - close_leads = queryset.filter(status="closed").distinct() - if search: - context["open_leads"] = LeadSerializer(open_leads, many=True).data - return context - - context["open_leads"] = LeadSerializer(open_leads, many=True).data - context["close_leads"] = LeadSerializer(close_leads, many=True).data + queryset_open = queryset.exclude(status="closed").order_by("id") + results_leads_open = self.paginate_queryset( + queryset_open.distinct(), self.request, view=self + ) + open_leads = LeadSerializer(results_leads_open, many=True).data + context["per_page"] = 10 + context["open_leads"] = { + "leads_count": self.count, + "next": self.get_next_link(), + "previous": self.get_previous_link(), + "page_number": int(self.offset / 10) + 1, + "open_leads": open_leads, + } + + queryset_close = queryset.filter(status="closed").order_by("id") + results_leads_close = self.paginate_queryset( + queryset_close.distinct(), self.request, view=self + ) + close_leads = LeadSerializer(results_leads_close, many=True).data + + context["close_leads"] = { + "leads_count": self.count, + "next": self.get_next_link(), + "previous": self.get_previous_link(), + "page_number": int(self.offset / 10) + 1, + "close_leads": close_leads, + } + context["status"] = LEAD_STATUS context["source"] = LEAD_SOURCE users = [] if self.request.user.role == "ADMIN" or self.request.user.is_superuser: users = User.objects.filter( - is_active=True, company=self.request.company + is_active=True, ).order_by("email") elif self.request.user.google.all(): users = [] else: users = User.objects.filter( - role="ADMIN", company=self.request.company + role="ADMIN", ).order_by("email") context["users"] = UserSerializer(users, many=True).data tag_ids = list( @@ -150,7 +175,7 @@ def post(self, request, *args, **kwargs): data = {} serializer = LeadCreateSerializer(data=params, request_obj=request) if serializer.is_valid(): - lead_obj = serializer.save(created_by=request.user, company=request.company) + lead_obj = serializer.save(created_by=request.user) if params.get("tags"): tags = json.loads(params.get("tags")) # for t in tags: @@ -164,12 +189,11 @@ def post(self, request, *args, **kwargs): tag = Tags.objects.create(name=t) lead_obj.tags.add(tag) - current_site = get_current_site(request) recipients = list(lead_obj.assigned_to.all().values_list("id", flat=True)) send_email_to_assigned_user.delay( recipients, lead_obj.id, - domain=current_site.domain, + domain=settings.Domain, protocol=request.scheme, ) @@ -185,25 +209,29 @@ def post(self, request, *args, **kwargs): if params.get("teams"): teams = json.loads(params.get("teams")) for team in teams: - teams_ids = Teams.objects.filter( - id=team, company=request.company - ) + teams_ids = Teams.objects.filter(id=team) if teams_ids: lead_obj.teams.add(team) else: lead_obj.delete() data["team"] = "Please enter valid Team" - return Response({"error": True, "errors": data}) + return Response( + {"error": True, "errors": data}, + status=status.HTTP_400_BAD_REQUEST, + ) if params.get("assigned_to"): assinged_to_users_ids = json.loads(params.get("assigned_to")) for user_id in assinged_to_users_ids: - user = User.objects.filter(id=user_id, company=request.company) + user = User.objects.filter(id=user_id) if user: lead_obj.assigned_to.add(user_id) else: lead_obj.delete() data["assigned_to"] = "Please enter valid User" - return Response({"error": True, "errors": data}) + return Response( + {"error": True, "errors": data}, + status=status.HTTP_400_BAD_REQUEST, + ) if params.get("status") == "converted": account_object = Account.objects.create( created_by=request.user, @@ -212,7 +240,6 @@ def post(self, request, *args, **kwargs): phone=lead_obj.phone, description=params.get("description"), website=params.get("website"), - company=request.company, ) account_object.billing_address_line = lead_obj.address_line account_object.billing_street = lead_obj.street @@ -233,12 +260,11 @@ def post(self, request, *args, **kwargs): if params.get("assigned_to"): assigned_to_list = json.loads(params.getlist("assigned_to")) - current_site = get_current_site(request) recipients = assigned_to_list send_email_to_assigned_user.delay( recipients, lead_obj.id, - domain=current_site.domain, + domain=settings.Domain, protocol=request.scheme, ) return Response( @@ -264,7 +290,7 @@ class LeadDetailView(APIView): permission_classes = (IsAuthenticated,) def get_object(self, pk): - return Lead.objects.get(pk=pk) + return get_object_or_404(Lead, id=pk) def get_context_data(self, **kwargs): params = ( @@ -284,7 +310,8 @@ def get_context_data(self, **kwargs): { "error": True, "errors": "You do not have Permission to perform this action", - } + }, + status=status.HTTP_403_FORBIDDEN, ) comments = Comment.objects.filter(lead=self.lead_obj).order_by("-id") @@ -299,7 +326,7 @@ def get_context_data(self, **kwargs): if self.request.user.is_superuser or self.request.user.role == "ADMIN": users_mention = list( User.objects.filter( - is_active=True, company=self.request.company + is_active=True, ).values("username") ) elif self.request.user != self.lead_obj.created_by: @@ -308,11 +335,11 @@ def get_context_data(self, **kwargs): users_mention = list(self.lead_obj.assigned_to.all().values("username")) if self.request.user.role == "ADMIN" or self.request.user.is_superuser: users = User.objects.filter( - is_active=True, company=self.request.company + is_active=True, ).order_by("email") else: users = User.objects.filter( - role="ADMIN", company=self.request.company + role="ADMIN", ).order_by("email") user_assgn_list = [ assigned_to.id @@ -327,7 +354,8 @@ def get_context_data(self, **kwargs): { "error": True, "errors": "You do not have Permission to perform this action", - } + }, + status=status.HTTP_403_FORBIDDEN, ) team_ids = [user.id for user in self.lead_obj.get_team_users] all_user_ids = [user.id for user in users] @@ -348,22 +376,16 @@ def get_context_data(self, **kwargs): ).data context["source"] = LEAD_SOURCE context["status"] = LEAD_STATUS - context["teams"] = TeamsSerializer( - Teams.objects.filter(company=self.request.company), many=True - ).data + context["teams"] = TeamsSerializer(Teams.objects.all(), many=True).data context["countries"] = COUNTRIES return context @swagger_auto_schema( - tags=["Leads"], manual_parameters=swagger_params.lead_delete_params + tags=["Leads"], ) def get(self, request, pk, **kwargs): self.lead_obj = self.get_object(pk) - if self.lead_obj.company != request.company: - return Response( - {"error": True, "errors": "User company doesnot match with header...."} - ) context = self.get_context_data(**kwargs) return Response(context) @@ -378,11 +400,6 @@ def post(self, request, pk, **kwargs): ) context = {} self.lead_obj = Lead.objects.get(pk=pk) - if self.lead_obj.company != request.company: - return Response( - {"error": True, "errors": "User company does not match with header...."} - ) - if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: if not ( (self.request.user == self.lead_obj.created_by) @@ -393,7 +410,7 @@ def post(self, request, pk, **kwargs): "error": True, "errors": "You do not have Permission to perform this action", }, - status=status.HTTP_401_UNAUTHORIZED, + status=status.HTTP_403_FORBIDDEN, ) comment_serializer = CommentSerializer(data=params) if comment_serializer.is_valid(): @@ -435,10 +452,6 @@ def put(self, request, pk, **kwargs): ) data = {} self.lead_obj = self.get_object(pk) - if self.lead_obj.company != request.company: - return Response( - {"error": True, "errors": "User company doesnot match with header...."} - ) serializer = LeadCreateSerializer( data=params, instance=self.lead_obj, @@ -463,7 +476,6 @@ def put(self, request, pk, **kwargs): tag = Tags.objects.create(name=t) lead_obj.tags.add(tag) - current_site = get_current_site(request) assigned_to_list = list( lead_obj.assigned_to.all().values_list("id", flat=True) ) @@ -471,7 +483,7 @@ def put(self, request, pk, **kwargs): send_email_to_assigned_user.delay( recipients, lead_obj.id, - domain=current_site.domain, + domain=settings.Domain, protocol=request.scheme, ) if request.FILES.get("lead_attachment"): @@ -487,15 +499,16 @@ def put(self, request, pk, **kwargs): if params.get("teams"): teams = json.loads(params.get("teams")) for team in teams: - teams_ids = Teams.objects.filter( - id=team, company=request.company - ) + teams_ids = Teams.objects.filter(id=team) if teams_ids: lead_obj.teams.add(team) else: lead_obj.delete() data["team"] = "Please enter valid Team" - return Response({"error": True, "errors": data}) + return Response( + {"error": True, "errors": data}, + status=status.HTTP_400_BAD_REQUEST, + ) else: lead_obj.teams.clear() @@ -503,13 +516,16 @@ def put(self, request, pk, **kwargs): if params.get("assigned_to"): assinged_to_users_ids = json.loads(params.get("assigned_to")) for user_id in assinged_to_users_ids: - user = User.objects.filter(id=user_id, company=request.company) + user = User.objects.filter(id=user_id) if user: lead_obj.assigned_to.add(user_id) else: lead_obj.delete() data["assigned_to"] = "Please enter valid User" - return Response({"error": True, "errors": data}) + return Response( + {"error": True, "errors": data}, + status=status.HTTP_400_BAD_REQUEST, + ) else: lead_obj.assigned_to.clear() @@ -522,7 +538,6 @@ def put(self, request, pk, **kwargs): description=params.get("description"), website=params.get("website"), lead=lead_obj, - company=request.company, ) account_object.billing_address_line = lead_obj.address_line account_object.billing_street = lead_obj.street @@ -543,12 +558,11 @@ def put(self, request, pk, **kwargs): if params.get("assigned_to"): # account_object.assigned_to.add(*params.getlist('assigned_to')) assigned_to_list = json.loads(params.get("assigned_to")) - current_site = get_current_site(request) recipients = assigned_to_list send_email_to_assigned_user.delay( recipients, lead_obj.id, - domain=current_site.domain, + domain=settings.Domain, protocol=request.scheme, ) @@ -573,7 +587,7 @@ def put(self, request, pk, **kwargs): ) @swagger_auto_schema( - tags=["Leads"], manual_parameters=swagger_params.lead_delete_params + tags=["Leads"], ) def delete(self, request, pk, **kwargs): self.object = self.get_object(pk) @@ -581,7 +595,7 @@ def delete(self, request, pk, **kwargs): request.user.role == "ADMIN" or request.user.is_superuser or request.user == self.object.created_by - ) and self.object.company == request.company: + ): self.object.delete() return Response( {"error": False, "message": "Lead deleted Successfully"}, @@ -610,16 +624,15 @@ def post(self, request, *args, **kwargs): lead_form.invalid_rows, request.user.id, request.get_host(), - request.company.id, ) return Response( {"error": False, "message": "Leads created Successfully"}, - status=status.HTTP_201_CREATED, + status=status.HTTP_200_OK, ) else: return Response( {"error": True, "errors": lead_form.errors}, - status=status.HTTP_200_OK, + status=status.HTTP_400_BAD_REQUEST, ) @@ -656,11 +669,15 @@ def put(self, request, pk, format=None): ) else: return Response( - {"error": True, "errors": "User company doesnot match with header...."} + { + "error": True, + "errors": "You don't have permission to perform this action", + }, + status=status.HTTP_403_FORBIDDEN, ) @swagger_auto_schema( - tags=["Leads"], manual_parameters=swagger_params.lead_delete_params + tags=["Leads"], ) def delete(self, request, pk, format=None): self.object = self.get_object(pk) @@ -679,7 +696,8 @@ def delete(self, request, pk, format=None): { "error": True, "errors": "You do not have permission to perform this action", - } + }, + status=status.HTTP_403_FORBIDDEN, ) @@ -689,7 +707,7 @@ class LeadAttachmentView(APIView): permission_classes = (IsAuthenticated,) @swagger_auto_schema( - tags=["Leads"], manual_parameters=swagger_params.lead_delete_params + tags=["Leads"], ) def delete(self, request, pk, format=None): self.object = self.model.objects.get(pk=pk) @@ -705,5 +723,73 @@ def delete(self, request, pk, format=None): ) else: return Response( - {"error": True, "errors": "User company doesnot match with header...."} + { + "error": True, + "errors": "You don't have permission to perform this action", + }, + status=status.HTTP_403_FORBIDDEN, ) + + +class CreateLeadFromSite(APIView): + @swagger_auto_schema( + tags=["Leads"], manual_parameters=swagger_params.create_lead_from_site + ) + def post(self, request, *args, **kwargs): + params = request.query_params if len(request.data) == 0 else request.data + api_key = params.get("apikey") + # api_setting = APISettings.objects.filter( + # website=website_address, apikey=api_key).first() + api_setting = APISettings.objects.filter(apikey=api_key).first() + if not api_setting: + return Response( + { + "error": True, + "message": "You don't have permission, please contact the admin!.", + }, + status=status.HTTP_403_FORBIDDEN, + ) + + if api_setting and params.get("email") and params.get("title"): + # user = User.objects.filter(is_admin=True, is_active=True).first() + user = api_setting.created_by + lead = Lead.objects.create( + title=params.get("title"), + first_name=params.get("first_name"), + last_name=params.get("last_name"), + status="assigned", + source=api_setting.website, + description=params.get("message"), + email=params.get("email"), + phone=params.get("phone"), + is_active=True, + created_by=user, + ) + lead.assigned_to.add(user) + # Send Email to Assigned Users + site_address = request.scheme + "://" + request.META["HTTP_HOST"] + send_lead_assigned_emails.delay(lead.id, [user.id], site_address) + # Create Contact + try: + contact = Contact.objects.create( + first_name=params.get("title"), + email=params.get("email"), + phone=params.get("phone"), + description=params.get("message"), + created_by=user, + is_active=True, + ) + contact.assigned_to.add(user) + + lead.contacts.add(contact) + except Exception: + pass + + return Response( + {"error": False, "message": "Lead Created sucessfully."}, + status=status.HTTP_200_OK, + ) + return Response( + {"error": True, "message": "Invalid data"}, + status=status.HTTP_400_BAD_REQUEST, + ) diff --git a/leads/forms.py b/leads/forms.py index ab28eb7..83fbb10 100644 --- a/leads/forms.py +++ b/leads/forms.py @@ -1,138 +1,7 @@ import csv -import json import re - -import openpyxl from django import forms -from common.models import Attachments, Comment -from leads.models import Lead -from accounts.models import Account -from phonenumber_field.formfields import PhoneNumberField -from teams.models import Teams - - -class LeadForm(forms.ModelForm): - teams_queryset = [] - teams = forms.MultipleChoiceField(choices=teams_queryset) - LEAD_SOURCE_CHOICES = ( - ("call", "Call"), - ("email", "Email"), - ("existing customer", "Existing Customer"), - ("partner", "Partner"), - ("public relations", "Public Relations"), - ("compaign", "Campaign"), - ("other", "Other"), - ) - source = forms.ChoiceField(choices=LEAD_SOURCE_CHOICES) - - def __init__(self, *args, **kwargs): - request_obj = kwargs.pop("request_obj", None) - assigned_users = kwargs.pop("assigned_to", []) - super(LeadForm, self).__init__(*args, **kwargs) - for field in self.fields.values(): - field.widget.attrs = {"class": "form-control"} - if self.data.get("status") == "converted": - self.fields["account_name"].required = True - self.fields["email"].required = True - self.fields["first_name"].required = False - self.fields["last_name"].required = False - self.fields["title"].required = True - if assigned_users: - self.fields["assigned_to"].queryset = assigned_users - self.fields["assigned_to"].required = False - for key, value in self.fields.items(): - if key == "phone": - value.widget.attrs[ - "placeholder" - ] = "Enter phone number with country code" - else: - value.widget.attrs["placeholder"] = value.label - - self.fields["first_name"].widget.attrs.update({"placeholder": "First Name"}) - self.fields["last_name"].widget.attrs.update({"placeholder": "Last Name"}) - self.fields["account_name"].widget.attrs.update({"placeholder": "Account Name"}) - self.fields["phone"].widget.attrs.update({"placeholder": "+911234567890"}) - self.fields["description"].widget.attrs.update({"rows": "6"}) - self.fields["address_line"].widget.attrs.update({"placeholder": "Address Line"}) - self.fields["street"].widget.attrs.update({"placeholder": "Street"}) - self.fields["city"].widget.attrs.update({"placeholder": "City"}) - self.fields["state"].widget.attrs.update({"placeholder": "State"}) - self.fields["postcode"].widget.attrs.update({"placeholder": "Postcode"}) - self.fields["country"].choices = [("", "--Country--"),] + list( - self.fields["country"].choices - )[1:] - self.fields["teams"].choices = [ - (team.get("id"), team.get("name")) - for team in Teams.objects.filter(company=request_obj.company).values( - "id", "name" - ) - ] - self.fields["teams"].required = False - - if self.instance.id: - if self.instance.created_from_site: - prev_choices = self.fields["source"]._get_choices() - prev_choices = prev_choices + [("micropyramid", "Micropyramid")] - self.fields["source"]._set_choices(prev_choices) - self.company = request_obj.company - - def clean_account_name(self): - account_name = self.cleaned_data.get("account_name") - if self.instance.id: - if self.instance.account_name != account_name: - if not Account.objects.filter( - name__iexact=self.cleaned_data.get("account_name"), - company=self.company, - ).exists(): - return self.cleaned_data.get("account_name") - raise forms.ValidationError("Account already exists with this name") - return self.cleaned_data.get("account_name") - if not Account.objects.filter( - name__iexact=self.cleaned_data.get("account_name"), company=self.company - ).exists(): - return self.cleaned_data.get("account_name") - raise forms.ValidationError("Account already exists with this name") - - class Meta: - model = Lead - fields = ( - "assigned_to", - "first_name", - "last_name", - "account_name", - "title", - "phone", - "email", - "status", - "source", - "website", - "description", - "address_line", - "street", - "city", - "state", - "postcode", - "country", - ) - - -class LeadCommentForm(forms.ModelForm): - comment = forms.CharField(max_length=255, required=True) - - class Meta: - model = Comment - fields = ("comment", "lead", "commented_by") - - -class LeadAttachmentForm(forms.ModelForm): - attachment = forms.FileField(max_length=1001, required=True) - - class Meta: - model = Attachments - fields = ("attachment", "lead") - - email_regex = "^[_a-zA-Z0-9-]+(\.[_a-zA-Z0-9-]+)*@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*(\.[a-zA-Z]{2,4})$" diff --git a/leads/migrations/0013_remove_lead_company.py b/leads/migrations/0013_remove_lead_company.py new file mode 100644 index 0000000..950a67a --- /dev/null +++ b/leads/migrations/0013_remove_lead_company.py @@ -0,0 +1,17 @@ +# Generated by Django 3.1.7 on 2021-03-24 05:43 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("leads", "0012_lead_company"), + ] + + operations = [ + migrations.RemoveField( + model_name="lead", + name="company", + ), + ] diff --git a/leads/migrations/0014_auto_20210324_1208.py b/leads/migrations/0014_auto_20210324_1208.py new file mode 100644 index 0000000..97af4c7 --- /dev/null +++ b/leads/migrations/0014_auto_20210324_1208.py @@ -0,0 +1,18 @@ +# Generated by Django 3.1.7 on 2021-03-24 06:38 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("leads", "0013_remove_lead_company"), + ] + + operations = [ + migrations.RenameField( + model_name="lead", + old_name="enquery_type", + new_name="enquiry_type", + ), + ] diff --git a/leads/models.py b/leads/models.py index 94604e4..2e1066b 100644 --- a/leads/models.py +++ b/leads/models.py @@ -6,7 +6,7 @@ from phonenumber_field.modelfields import PhoneNumberField from accounts.models import Tags -from common.models import User, Company +from common.models import User from common.utils import COUNTRIES, LEAD_SOURCE, LEAD_STATUS, return_complete_address from contacts.models import Contact from teams.models import Teams @@ -46,14 +46,11 @@ class Lead(models.Model): ) created_on = models.DateTimeField(_("Created on"), auto_now_add=True) is_active = models.BooleanField(default=False) - enquery_type = models.CharField(max_length=255, blank=True, null=True) + enquiry_type = models.CharField(max_length=255, blank=True, null=True) tags = models.ManyToManyField(Tags, blank=True) contacts = models.ManyToManyField(Contact, related_name="lead_contacts") created_from_site = models.BooleanField(default=False) teams = models.ManyToManyField(Teams, related_name="lead_teams") - company = models.ForeignKey( - Company, on_delete=models.SET_NULL, null=True, blank=True - ) class Meta: ordering = ["-created_on"] diff --git a/leads/serializer.py b/leads/serializer.py index 801fde0..c6febaf 100644 --- a/leads/serializer.py +++ b/leads/serializer.py @@ -5,7 +5,6 @@ UserSerializer, AttachmentsSerializer, LeadCommentSerializer, - CompanySerializer, ) from contacts.serializer import ContactSerializer from teams.serializer import TeamsSerializer @@ -23,7 +22,6 @@ class LeadSerializer(serializers.ModelSerializer): tags = TagsSerializer(read_only=True, many=True) lead_attachment = AttachmentsSerializer(read_only=True, many=True) teams = TeamsSerializer(read_only=True, many=True) - company = CompanySerializer() lead_comments = LeadCommentSerializer(read_only=True, many=True) class Meta: @@ -54,11 +52,10 @@ class Meta: "created_by", "created_on", "is_active", - "enquery_type", + "enquiry_type", "tags", "created_from_site", "teams", - "company", ) @@ -78,14 +75,12 @@ def __init__(self, *args, **kwargs): prev_choices = self.fields["source"]._get_choices() prev_choices = prev_choices + [("micropyramid", "Micropyramid")] self.fields["source"]._set_choices(prev_choices) - self.company = request_obj.company def validate_account_name(self, account_name): if self.instance: if ( Account.objects.filter( name__iexact=account_name, - company=self.company, ) .exclude(id=self.instance.id) .exists() @@ -95,7 +90,7 @@ def validate_account_name(self, account_name): ) else: if Account.objects.filter( - name__iexact=account_name, company=self.company + name__iexact=account_name, ).exists(): raise serializers.ValidationError( "Account already exists with this name" @@ -107,14 +102,13 @@ def validate_title(self, title): if ( Lead.objects.filter( title__iexact=title, - company=self.company, ) .exclude(id=self.instance.id) .exists() ): raise serializers.ValidationError("Lead already exists with this title") else: - if Lead.objects.filter(title__iexact=title, company=self.company).exists(): + if Lead.objects.filter(title__iexact=title).exists(): raise serializers.ValidationError("Lead already exists with this title") return title diff --git a/leads/signals.py b/leads/signals.py deleted file mode 100644 index e4ec5f9..0000000 --- a/leads/signals.py +++ /dev/null @@ -1,22 +0,0 @@ -# from django.db.models.signals import post_delete, post_save -# from django.dispatch import receiver - -# from common.models import User -# from leads.models import Lead - - -# @receiver([post_delete, post_save], sender=User) -# def update_cache_for_leads_list_users(sender, **kwargs): -# print('after registering it in the app') -# lead_users = User.objects.filter( -# is_active=True).order_by('email').values('id', 'email') -# cache.set('lead_form_users', lead_users, 60*60) - -# @receiver([post_delete, post_save], sender=Lead) -# def update_cache_for_leads_list_page(sender, **kwargs): -# queryset = Lead.objects.all().exclude(status='converted').select_related('created_by' -# ).prefetch_related('tags', 'assigned_to',) -# open_leads = queryset.exclude(status='closed') -# close_leads = queryset.filter(status='closed') -# cache.set('admin_leads_open_queryset', open_leads, 60*60) -# cache.set('admin_leads_close_queryset', close_leads, 60*60) diff --git a/leads/swagger_params.py b/leads/swagger_params.py index f1092fb..b85930a 100644 --- a/leads/swagger_params.py +++ b/leads/swagger_params.py @@ -1,11 +1,6 @@ from drf_yasg import openapi -company_params_in_header = openapi.Parameter( - "company", openapi.IN_HEADER, required=True, type=openapi.TYPE_STRING -) - lead_list_get_params = [ - company_params_in_header, openapi.Parameter("title", openapi.IN_QUERY, type=openapi.TYPE_STRING), openapi.Parameter("source", openapi.IN_QUERY, type=openapi.TYPE_STRING), openapi.Parameter("assigned_to", openapi.IN_QUERY, type=openapi.TYPE_STRING), @@ -14,7 +9,6 @@ ] lead_detail_get_params = [ - company_params_in_header, openapi.Parameter( "lead_attachment", openapi.IN_QUERY, @@ -23,12 +17,7 @@ openapi.Parameter("comment", openapi.IN_QUERY, type=openapi.TYPE_STRING), ] -lead_delete_params = [ - company_params_in_header, -] - lead_create_post_params = [ - company_params_in_header, openapi.Parameter( "title", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING ), @@ -58,7 +47,6 @@ ] lead_upload_post_params = [ - company_params_in_header, openapi.Parameter( "leads_file", openapi.IN_QUERY, @@ -67,6 +55,24 @@ ] lead_comment_edit_params = [ - company_params_in_header, openapi.Parameter("comment", openapi.IN_QUERY, type=openapi.TYPE_STRING), ] + +create_lead_from_site = [ + openapi.Parameter( + "apikey", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING + ), + openapi.Parameter( + "title", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING + ), + openapi.Parameter("first_name", openapi.IN_QUERY, type=openapi.TYPE_STRING), + openapi.Parameter("last_name", openapi.IN_QUERY, type=openapi.TYPE_STRING), + openapi.Parameter("phone", openapi.IN_QUERY, type=openapi.TYPE_STRING), + openapi.Parameter( + "email", openapi.IN_QUERY, type=openapi.TYPE_STRING, required=True + ), + openapi.Parameter( + "source", openapi.IN_QUERY, type=openapi.TYPE_STRING, required=True + ), + openapi.Parameter("description", openapi.IN_QUERY, type=openapi.TYPE_STRING), +] diff --git a/leads/tasks.py b/leads/tasks.py index c6b84b0..c7418a3 100644 --- a/leads/tasks.py +++ b/leads/tasks.py @@ -8,9 +8,8 @@ from django.shortcuts import reverse from django.template.loader import render_to_string -from accounts.models import User, Company +from accounts.models import User from leads.models import Lead -from marketing.models import BlockedDomain, BlockedEmail app = Celery("redis://") @@ -84,44 +83,33 @@ def send_email_to_assigned_user( """ Send Mail To Users When they are assigned to a lead """ lead = Lead.objects.get(id=lead_id) created_by = lead.created_by - blocked_domains = BlockedDomain.objects.values_list("domain", flat=True) - blocked_emails = BlockedEmail.objects.values_list("email", flat=True) for user in recipients: recipients_list = [] user = User.objects.filter(id=user, is_active=True).first() if user: - if (user.email not in blocked_emails) and ( - user.email.split("@")[-1] not in blocked_domains - ): - recipients_list.append(user.email) - context = {} - context["url"] = ( - protocol - + "://" - + domain - + reverse("leads:view_lead", args=(lead.id,)) - ) - context["user"] = user - context["lead"] = lead - context["created_by"] = created_by - context["source"] = source - subject = "Assigned a lead for you. " - html_content = render_to_string( - "assigned_to/leads_assigned.html", context=context - ) - msg = EmailMessage(subject, html_content, to=recipients_list) - msg.content_subtype = "html" - msg.send() + recipients_list.append(user.email) + context = {} + context["url"] = protocol + "://" + domain + context["user"] = user + context["lead"] = lead + context["created_by"] = created_by + context["source"] = source + subject = "Assigned a lead for you. " + html_content = render_to_string( + "assigned_to/leads_assigned.html", context=context + ) + msg = EmailMessage(subject, html_content, to=recipients_list) + msg.content_subtype = "html" + msg.send() @app.task -def create_lead_from_file(validated_rows, invalid_rows, user_id, source, company_id): +def create_lead_from_file(validated_rows, invalid_rows, user_id, source): """Parameters : validated_rows, invalid_rows, user_id. This function is used to create leads from a given file. """ email_regex = "^[_a-zA-Z0-9-]+(\.[_a-zA-Z0-9-]+)*@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*(\.[a-zA-Z]{2,4})$" user = User.objects.get(id=user_id) - company = Company.objects.filter(id=company_id).first() for row in validated_rows: if not Lead.objects.filter(title=row.get("title")).exists(): if re.match(email_regex, row.get("email")) is not None: @@ -143,7 +131,6 @@ def create_lead_from_file(validated_rows, invalid_rows, user_id, source, company lead.account_name = row.get("account_name", "")[:255] lead.created_from_site = False lead.created_by = user - lead.company = company lead.save() except Exception as e: print(e) diff --git a/leads/templates/checkbox.html b/leads/templates/checkbox.html deleted file mode 100644 index 0a01a1e..0000000 --- a/leads/templates/checkbox.html +++ /dev/null @@ -1,402 +0,0 @@ -{% extends 'sales/base.html' %} -{% load static %} -{% block breadcrumb %} -
      - - Account
      - Contact
      - Opportunity
      - - -
      -
      -
      -
      - Overview -
      -
      -
      -
      -
      -
      - * -
      -
      -
      -
      -
      -

      - {% if error_lead_form.name%} - {{error_lead_form.name}} - {% endif %} -
      -
      -
      -
      - * - - {% if err_contct_form.account %} -

      {{err_contct_form.account}}

      - {% endif %} -
      -
      -
      -
      - * - - {% if error_lead_form.phone %} -

      {{error_lead_form.phone}}

      - {% endif %} -
      -
      -
      -
      - * - - {% if error_lead_form %} -

      {{error_lead_form.email}}

      - {% endif %} -
      -
      -
      -
      -
      -
      -
      - - - {% if error_address_form%} -

      {{error_address_form.street}}

      - {% endif %} -
      -
      - -
      -
      - -
      -
      -
      -
      -
      -
      -
      - - -
      -
      -
      -
      -
      -
      -
      -
      - - -
      -
      -
      -
      -
      -
      -
      - - CANCEL -
      -
      -
      -{% endblock %} -{# {% endblock %} #} -{% block js_block %} - -{% endblock js_block %} \ No newline at end of file diff --git a/leads/templates/create_lead.html b/leads/templates/create_lead.html deleted file mode 100644 index 961619d..0000000 --- a/leads/templates/create_lead.html +++ /dev/null @@ -1,542 +0,0 @@ -{% extends 'sales/base.html' %} -{% load static %} -{% block breadcrumb %} - -{% endblock %} -{%block content%} - - - - -
      -
      -
      -
      -
      -
      - {% if lead_obj %}EDIT{% else %}CREATE{% endif %} LEAD -
      -
      -
      -
      -
      -
      -
      - - {{ lead_form.first_name }} - {{ lead_form.first_name.errors }} -
      -
      - - {{ lead_form.last_name }} - {{ lead_form.last_name.errors }} -
      -
      -
      -
      -
      -
      - - {{ lead_form.account_name }} - {{ lead_form.account_name.errors }} - {% if error %} - {{ error }} - {% endif %} -
      -
      -
      -
      - - {{ lead_form.title }} - {{ lead_form.title.errors }} -
      -
      -
      -
      - - - {{ lead_form.phone.errors }} -
      -
      -
      -
      - - {{ lead_form.email }} - {{ lead_form.email.errors }} - {% if error %} - {{ error }} - {% endif %} -
      -
      - -
      -
      - - - {% if lead_obj.lead_attachment.count %} - {% for attachment in lead_obj.lead_attachment.all %} -
      - {{ attachment.file_name }} - {% if not attachment.created_by.role == 'ADMIN' or attachment.created_by.role == request.user.role %} - X - {% endif %} -
      - {% endfor %} - {% endif %} - -
      -
      -
      -
      -
      -
      - - {{ lead_form.website }} - {{ lead_form.website.errors }} -
      -
      -
      -
      - - {{ lead_form.description }} - {{ lead_form.description.errors }} -
      -
      - {% if request.user.is_superuser or request.user.role == 'ADMIN' %} -
      -
      - - - {{ lead_form.teams.errors }} -
      -
      - -
      -
      - - -
      -
      - - {% endif %} -
      -
      - - - {{ lead_form.assigned_to.errors }} -
      -
      -
      -
      -
      -
      - - {{ lead_form.status }} - {{ lead_form.status.errors }} -
      -
      -
      -
      - - {{ lead_form.source }} - {{ lead_form.source.errors }} -
      -
      -
      -
      - - {{ lead_form.address_line }} - {{ lead_form.address_line.errors }} -
      - {{ lead_form.street }} - {{ lead_form.street.errors }} -
      -
      - {{ lead_form.city }} - {{ lead_form.city.errors }} -
      -
      - {{ lead_form.state }} - {{ lead_form.state.errors }} -
      - -
      - {{ lead_form.postcode }} - {{ lead_form.postcode.errors }} -
      -
      - {{ lead_form.country }} - {{ lead_form.country.errors }} -
      -
      -
      -
      -
      -
      - -
      -
      -
      -
      -
      -
      -
      - - {% if not lead_obj %} - - {% endif %} - Cancel -
      -
      -
      -
      -
      -
      - -
      -
      -
      - -
      - 0% -
      -
      -
      -{% endblock %} -{% block js_block %} - -{% endblock js_block %} \ No newline at end of file diff --git a/leads/templates/lead_assigned.html b/leads/templates/lead_assigned.html deleted file mode 100644 index 620beee..0000000 --- a/leads/templates/lead_assigned.html +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - Django CRM - - - - - - - - - -
      - - - - - - -
      - - - - - - - - - - - - - - - -
      - - Django - CRM -
      - Dear {{ user.get_full_name }} !!! -
      -
      Here are the Lead details:

      -
      Title: {{ lead_instance.title }}

      -
      Email: {{ lead_instance.email }}

      -
      Source: {{ lead_instance.source }}

      -
      Status: {{ lead_instance.status }}

      -
      Description: {{ lead_instance.description }}

      -
      - Click Here to view '{{ lead_instance.title }}' details -
      -

      -

      -
      - Yours sincerely, Administration of the service, Django-CRM. -
      -
      -
      - - \ No newline at end of file diff --git a/leads/templates/leads.html b/leads/templates/leads.html deleted file mode 100644 index 7930cb9..0000000 --- a/leads/templates/leads.html +++ /dev/null @@ -1,943 +0,0 @@ -{% extends 'sales/base.html' %} -{% load static %} -{% load paginate %} -{% load thumbnail %} -{% load cache %} - -{% block extralinks %} - -{% endblock %} -{% block content %} - -
      - - - -
      -
      -
      -
      -
      -
      -
      Filters
      -
      -
      -
      - - -
      -
      -
      -
      - - -
      -
      -
      -
      - - -
      -
      -
      -
      - - -
      -
      -
      -
      - - -
      -
      - -
      -
      - - Clear -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      - -
      -
      -
      -
      -
      - Open Leads - {% if show_pageitems %} {% show_pageitems %}{% else %} - {{ open_leads|length }}{% endif %} - - - -
      -
      - - - {% if open_leads|length > 0 %} - - - - - - - - - - - - - {% endif %} - - - {% if per_page %} - {% paginate per_page open_leads %} - {% else %} - {% paginate 10 open_leads %} - {% endif %} - {% for lead in open_leads %} - - - - - - - - - - - - - - {% endfor %} - -
      IDTitleCreated BySourceStatusAssigned ToTagsCountry Created OnActions
      {{ forloop.counter }} - - {{ lead.title }} - - - {% if lead.created_by %} - {% if lead.created_by.profile_pic %} - {% thumbnail lead.created_by.profile_pic "40x40" crop="center" as im %} - - - - {% endthumbnail %} - {% else %} - - Micro profile pic - - {% endif %} - {% else %} - None - {% endif %} - {{ lead.source }}{{ lead.get_status_display }} - {% with lead_users=lead.get_team_and_assigned_users %} - {% for user in lead_users %} - {% if user.profile_pic %} - {% thumbnail user.profile_pic "40x40" crop="center" as im %} - - - - {% endthumbnail %} - {% else %} - - - - {% endif %} - {% empty %} - None - {% endfor %} - {% endwith %} - -
      - {% with tags=lead.tags.all %} - {% if tags %} - {% for tag in tags %} - - - - {{ tag.name }} - - - - - {% endfor %} - - {% else %} - No Tags - {% endif %} - {% endwith %} - -
      -
      {{ lead.country }}{{ lead.created_on_arrow }} - - - {% if request.user == lead.created_by or request.user.role == "ADMIN" or request.user.is_superuser %} - - {% endif %} -
      -
      - {%ifequal open_leads|length 0%} -
      No Open Lead Records Found
      - {%endifequal%} -
      - {% show_pages %} -
      -
      -
      -
      -
      -
      -
      -
      - Closed Leads - {% if show_pageitems %} {% show_pageitems %}{% else %} - {{ close_leads|length }}{% endif %} - - - -
      -
      - - - {% if close_leads|length > 0 %} - - - - - - - - - - - - {% endif %} - - - {% if per_page %} - {% paginate per_page close_leads %} - {% else %} - {% paginate 10 close_leads %} - {% endif %} - {% for lead in close_leads %} - - - - - - - - - - - - {% endfor %} - -
      IDTitleSourceStatusAssigned UserTagsCountryCreated OnActions
      {{ forloop.counter }} - {{ lead.title }}{{ lead.source }}{{ lead.get_status_display }} - {% with lead_users=lead.get_team_and_assigned_users %} - {% for user in lead_users %} - {% if user.profile_pic %} - {% thumbnail user.profile_pic "40x40" crop="center" as im %} - - - - {% endthumbnail %} - {% else %} - - - - {% endif %} - {% empty %} - None - {% endfor %} - {% endwith %} - -
      - {% with tags=lead.tags.all %} - {% if tags %} - {% for tag in tags %} - - - - {{ tag.name }} - - - - - {% endfor %} - - {% else %} - No Tags - {% endif %} - {% endwith %} - -
      -
      {{ lead.country }}{{ lead.created_on_arrow }} - - - {% if request.user == lead.created_by or request.user.is_superuser or request.user.role == 'ADMIN' %} - - {% endif %} -
      -
      - {%ifequal close_leads|length 0%} -
      No Closed Lead Records Found
      - {%endifequal%} -
      - {% show_pages %} -
      -
      -
      -
      -
      -
      -
      -
      -
      - - - - -{% for lead_record in open_leads %} - - - - - -{% endfor %} - - -{% for lead_record in close_leads %} - - - - - - - - - - - -{% endfor %} - - - - - -{% endblock %} - -{% block js_block %} - -{% endblock js_block %} diff --git a/leads/templates/leads_list.html b/leads/templates/leads_list.html deleted file mode 100644 index 0c0b20e..0000000 --- a/leads/templates/leads_list.html +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - {% ifequal leads|length 0 %} - - - - {% endifequal %} - {% for lead in leads %} - - - - - {% endfor %} - -
      - - Name - - - - - Email - -
      - NO LEADS FOUND!! -
      - - {{ lead.first_name }} - - - {{ lead.email }} -
      \ No newline at end of file diff --git a/leads/templates/view_leads.html b/leads/templates/view_leads.html deleted file mode 100644 index a403cdd..0000000 --- a/leads/templates/view_leads.html +++ /dev/null @@ -1,533 +0,0 @@ -{% extends 'sales/base.html' %} -{% load static %} -{% load thumbnail %} -{% block breadcrumb %} - -{% block extralinks %} - - -{% endblock extralinks %} - - -{%endblock%} - -{% block content %} -
      -
      -
      -
      - -
      -
      -
      - Overview - - - -
      -
      -
      -
      -
      -
      - -
      {% if lead_record.first_name %} - {{ lead_record.first_name }}{% endif %} {% if lead_record.last_name %} - {{ lead_record.last_name }}{% endif %}
      -
      -
      -
      -
      - - {% if lead_record.account_name %} -
      {{ lead_record.account_name }}
      - {% else %} -
      Not Specified
      - {% endif %} -
      -
      -
      -
      - - {% if lead_record.title %} -
      {{ lead_record.title }}
      - {% else %} -
      Not Specified
      - {% endif %} -
      -
      -
      -
      - - {% if lead_record.lead_record.phone_raw_input %} -
      {{ lead_record.phone_raw_input }}
      - {% else %} -
      Not specified
      - {% endif %} -
      -
      - -
      -
      -
      -
      - - {% if lead_record.email %} -
      {{ lead_record.email }}
      - {% else %} -
      Not Specified
      - {% endif %} -
      -
      -
      -
      - - {% if lead_record.status %} -
      {{ lead_record.status }}
      - {% else %} -
      Not Specified
      - {% endif %} -
      -
      -
      -
      - - {% if lead_record.source %} -
      {{ lead_record.source }}
      - {% else %} -
      Not Specified
      - {% endif %} -
      -
      -
      -
      - - {% if lead_record.website %} -
      {{ lead_record.website }}
      - {% else %} -
      Not Specified
      - {% endif %} -
      -
      -
      -
      -
      -
      -
      - {% for tag in lead_record.tags.all %} - - - {{ tag.name }} - - - - {% empty %} -
      Not Specified
      - {% endfor %} -
      -
      -
      - -
      -
      - {% if lead_record.address_line or lead_record.street or lead_record.city or lead_record.state or lead_record.postcode or lead_record.country %} - -
      - {{lead_record.get_complete_address}} -
      - {% endif %} -
      -
      -
      - {% if lead_record.description %} -
      - -
      {{ lead_record.description }}
      -
      - {% endif %} -
      -
      -
      -
      - Created by {{ lead_record.created_by }} created on {{ lead_record.created_on_arrow }} -
      -
      -
      -
      - - -
      -
      -
      -
      Attachments
      -
      -
      -
      -
      -
      - -
      - -
      -
      -
      - -
      -
      - -
      -
        - {% for attachment in attachments %} -
      • - {% if request.user.is_superuser or request.user.role == 'ADMIN' or request.user == attachment.created_by %} -
        -
        - -
        -
        - {% endif %} - -
        - {% if attachment.attachment %} - {% if 'image' in attachment.file_type %} - {% thumbnail attachment.attachment "80x80" crop="center" as im %} - - {% endthumbnail %} - {% endif %} - {% endif %} -
          {{attachment.file_name}}  Download
        -
        - -
        -
        Uploaded by :{{ attachment.created_by }}
        -
        {{ attachment.created_on_arrow }}
        -
        -
      • - {% endfor %} -
      -
      -
      -
      - - - -
      -
      -
      -
      Comments
      -
      -
      -
      -
      -
      - -
      - -
      -
      -
      - -
      -
      - -
      -
        - {% for comment in comments %} -
      • - {% if request.user.is_superuser or request.user.role == 'ADMIN' or request.user == comment.commented_by %} -
        -
        - - -
        -
        - {% endif %} -
        -
        {{ comment.comment }}
        -
        -
        -
        {{ comment.commented_by}}
        -
        {{ comment.commented_on_arrow }}
        -
        -
      • - {% endfor %} -
      -
      -
      - -
      -
      - -
      -
      - -
      -
      - -
      - Processing File... -
      -
      -
      - -{% endblock %} - -{% block js_block %} - - - - - -{% endblock js_block %} diff --git a/leads/tests.py b/leads/tests.py deleted file mode 100644 index 0b90545..0000000 --- a/leads/tests.py +++ /dev/null @@ -1,851 +0,0 @@ -from django.core.files.uploadedfile import SimpleUploadedFile -from django.test import Client, TestCase -from django.urls import reverse -from django.utils.encoding import force_text - -from accounts.models import Account, Tags -from cases.models import Case -from common.models import APISettings, Attachments, Comment, User, Company -from leads.forms import * -from leads.models import Lead -from leads.tasks import * -from teams.models import Teams - - -class TestLeadModel(object): - def setUp(self): - self.client = Client() - self.company, _ = Company.objects.get_or_create( - name="test company", address="IN", sub_domain="test", country="IN" - ) - - self.user = User.objects.create( - username="johnLead", - email="johnLead@example.com", - role="ADMIN", - company=self.company, - ) - self.user.set_password("password") - self.user.save() - - self.user1 = User.objects.create( - first_name="janeLead1", - username="janeLead1", - email="janeLead1@example.com", - role="USER", - company=self.company, - ) - self.user1.set_password("password") - self.user1.save() - - self.user2 = User.objects.create( - first_name="janeLead2", - username="janeLead2", - email="janeLead2@example.com", - role="USER", - has_sales_access=True, - company=self.company, - ) - self.user2.set_password("password") - self.user2.save() - - self.user3 = User.objects.create( - first_name="janeLead3", - username="janeLead3", - email="janeLead3@example.com", - role="USER", - has_sales_access=True, - company=self.company, - ) - self.user3.set_password("password") - self.user3.save() - - self.client.login(username="johnLead@example.com", password="password") - - self.account = Account.objects.create( - name="account", - email="account@example.com", - phone="12345", - billing_address_line="", - billing_street="billing street", - billing_city="city of billing", - billing_state="state", - billing_postcode="1234", - billing_country="AD", - website="www.example.com", - industry="IT", - description="account", - created_by=self.user, - ) - - self.lead = Lead.objects.create( - title="john lead", - first_name="jane doe", - last_name="doe", - email="janeDoe@example.com", - address_line="address line", - street="address street", - city="city name", - state="state name", - postcode="2134", - country="IN", - website="www.example.com", - status="assigned", - source="call", - opportunity_amount="700", - description="lead description", - created_by=self.user, - account_name="account", - phone="+91-123-456-7890", - is_active=True, - ) - - self.lead1 = Lead.objects.create(title="jane doe lead", created_by=self.user3) - self.lead.assigned_to.add(self.user) - self.lead.assigned_to.add(self.user2) - self.lead.assigned_to.add(self.user3) - self.case = Case.objects.create( - name="john case", - case_type="Problem", - status="New", - account=self.account, - priority="Low", - description="description", - created_by=self.user, - closed_on="2016-05-04", - ) - self.comment = Comment.objects.create( - comment="comment text", case=self.case, commented_by=self.user - ) - self.comment_mp = Comment.objects.create( - comment="comment body", case=self.case, commented_by=self.user2 - ) - self.attachment = Attachments.objects.create( - attachment="image.png", - case=self.case, - created_by=self.user, - account=self.account, - lead=self.lead, - ) - self.api_seetings = APISettings.objects.create( - title="api", apikey="api", created_by=self.user - ) - - self.tag_1 = Tags.objects.create(name="tag1") - self.tag_2 = Tags.objects.create(name="tag2") - self.tag_3 = Tags.objects.create(name="tag3") - self.lead.tags.add(self.tag_1, self.tag_2, self.tag_3) - - self.lead_1 = Lead.objects.create( - title="john's lead", - first_name="lead first name", - last_name="lead last name", - address_line="address line", - street=" street", - city="city", - state="state name", - postcode="1234", - country="IN", - website="www.example.com", - status="assigned", - source="call", - opportunity_amount="700", - description="Iam an Lead", - created_by=self.user, - phone="+91-123-456-7890", - ) - - -class LeadsPostrequestTestCase(TestLeadModel, TestCase): - def test_valid_postrequesttestcase_date(self): - data = { - "title": "lead title", - "first_name": "john doe", - "last_name": "doe", - "email": "johnDoeLeadtitle@example.com", - "account": self.account, - "address_line": "", - "street": "street", - "city": "city name", - "state": "state", - "postcode": "1234", - "country": "IN", - "website": "www.example.com", - "status ": "assigned", - "source": "call", - "opportunity_amount": "700", - "description": "Description of lead", - } - resp = self.client.post("/leads/create/", data) - self.assertEqual(resp.status_code, 200) - - def test_leads_list(self): - self.lead = Lead.objects.all() - get_name = Lead.objects.get(first_name="jane doe") - # print(get_name.first_name+get_name.last_name,str(get_name)) - self.assertEqual(get_name.title, str(get_name)) - response = self.client.get(reverse("leads:list")) - self.assertEqual(response.status_code, 200) - - def test_leads_list_html(self): - response = self.client.get(reverse("leads:list")) - self.assertTemplateUsed(response, "leads.html") - - -class LeadsCreateUrlTestCase(TestLeadModel, TestCase): - def test_leads_create_url(self): - response = self.client.post( - "/leads/create/", - { - "title": "LeadCreation", - "first_name": "john doe", - "email": "johnDoeLeadCreation@example.com", - "account": self.account, - "address_line": "", - "street": "street", - "city": "new town", - "state": "state", - "postcode": "1234", - "country": "IN", - "website": "www.example.com", - "status": "assigned", - "source": "call", - "opportunity_amount": "700", - "description": "Lead object creaton description", - "created_by": self.user, - "tags": "tag1, tag4, tag5", - }, - ) - self.assertEqual(response.status_code, 200) - - def test_leads_create_html(self): - response = self.client.post( - "/leads/create/", - { - "title": "LeadCreation title", - "name": "john doe", - "email": "johnDoeLeadCreation@example.com", - "account": self.account, - "address_line": "", - "street": "street", - "city": "city name", - "state": "state name", - "postcode": "1234", - "country": "AD", - "website": "www.example.com", - "status": "assigned", - "source": "call", - "opportunity_amount": "700", - "description": "lead description", - "created_by": self.user, - }, - ) - # self.assertTemplateUsed(response, 'create_lead.html') - self.assertEqual(response.status_code, 200) - - def test_leads_create_with_status_converted(self): - response = self.client.post( - "/leads/create/", - { - "title": "LeadCreation title", - "name": "john doe", - "email": "johnDoeLeadCreation@example.com", - "account": self.account, - "address_line": "", - "account_name": "account1", - "street": "", - "city": "city name", - "state": "state name", - "postcode": "1234", - "country": "IN", - "website": "www.example.com", - "status": "converted", - "source": "call", - "opportunity_amount": "700", - "description": "Lead description", - "created_by": self.user, - }, - ) - self.assertEqual(response.status_code, 200) - - -class LeadsEditUrlTestCase(TestLeadModel, TestCase): - def test_leads_editurl(self): - response = self.client.get("/leads/" + str(self.lead.id) + "/edit/") - self.assertEqual(response.status_code, 200) - - -class LeadsViewTestCase(TestLeadModel, TestCase): - def test_leads_view(self): - response = self.client.get("/leads/" + str(self.lead.id) + "/view/") - self.assertEqual(response.status_code, 200) - - -class LeadListTestCase(TestLeadModel, TestCase): - def test_leads_list(self): - self.lead = Lead.objects.all() - response = self.client.get(reverse("leads:list")) - self.assertEqual(response.status_code, 200) - self.assertTemplateUsed(response, "leads.html") - - def test_leads_list_queryset(self): - self.lead = Lead.objects.all() - data = { - "fist_name": "john doe lead", - "last_name": "lead last name", - "city": "", - "email": "johnlead@example.com", - "status": "Assigned", - } - response = self.client.post(reverse("leads:list"), data) - self.assertEqual(response.status_code, 200) - self.assertTemplateUsed(response, "leads.html") - - -class GetLeadsViewTestCase(TestLeadModel, TestCase): - def test_get_lead(self): - url = "/leads/get/list/" - response = self.client.get(url) - self.assertEqual(response.status_code, 200) - - -class LeadsRemoveTestCase(TestLeadModel, TestCase): - def test_leads_remove(self): - response = self.client.get("/leads/" + str(self.lead.id) + "/delete/") - self.assertEqual(response["location"], "/leads/") - - def test_leads_remove_status(self): - self.client.login(username="janeLead1@example.com", password="password") - response = self.client.get(reverse("leads:remove_lead", args=(self.lead.id,))) - self.assertEqual(response.status_code, 403) - self.client.logout() - - # Lead.objects.filter(id=self.lead.id).delete() - response = self.client.get(reverse("leads:remove_lead", args=(self.lead.id,))) - self.assertEqual(response.status_code, 302) - - -class UpdateLeadTestCase(TestLeadModel, TestCase): - def test_update_lead(self): - url = "/leads/" + str(self.lead.id) + "/edit/" - data = { - "title": "Creation", - "first_name": "update first", - "last_name": "update last name", - "email": "janeDoeLead@example.com", - "account": self.account, - "address_line": "", - "street": "street", - "city": "city name", - "state": "state name", - "postcode": "213", - "country": "IN", - "phone": "+911234567892", - "website": "www.example.com", - "status": "", - "source": "", - "opportunity_amount": "700", - "description": "lead description", - "created_by": self.user, - } - response = self.client.post(url, data) - self.assertEqual(response.status_code, 200) - - -class LeadDetailTestCase(TestLeadModel, TestCase): - def test_lead_detail(self): - url = "/leads/" + str(self.lead.id) + "/view/" - response = self.client.get(url, {"status": ""}) - self.assertEqual(response.status_code, 200) - - -class CommentTestCase(TestLeadModel, TestCase): - def test_comment_add(self): - self.client.login(email="janeLead1@example.com", password="password") - response = self.client.post("/leads/comment/add/", {"leadid": self.lead.id}) - self.assertEqual(response.status_code, 200) - - def test_comment_create(self): - response = self.client.post( - "/leads/comment/add/", {"leadid": self.lead.id, "comment": "comment"} - ) - self.assertEqual(response.status_code, 200) - - def test_comment_edit(self): - response = self.client.post( - "/leads/comment/edit/", {"commentid": self.comment.id, "comment": "comment"} - ) - self.assertEqual(response.status_code, 200) - - def test_comment_update(self): - self.client.login(email="janeLead1@example.com", password="password") - response = self.client.post( - "/leads/comment/edit/", {"commentid": self.comment.id} - ) - self.assertEqual(response.status_code, 200) - - def test_comment_delete(self): - response = self.client.post( - "/leads/comment/remove/", {"comment_id": self.comment.id} - ) - self.assertEqual(response.status_code, 200) - - def test_comment_deletion(self): - self.client.login(email="janeLead1@example.com", password="password") - response = self.client.post( - "/leads/comment/remove/", {"comment_id": self.comment.id} - ) - self.assertEqual(response.status_code, 200) - - -class AttachmentTestCase(TestLeadModel, TestCase): - def test_attachment_add(self): - self.client.login(email="janeLead1@example.com", password="password") - response = self.client.post("/leads/attachment/add/", {"leadid": self.lead.id}) - self.assertEqual(response.status_code, 200) - - def test_attachment_delete(self): - response = self.client.post( - "/leads/attachment/remove/", {"attachment_id": self.attachment.id} - ) - self.assertEqual(response.status_code, 200) - - def test_attachment_deletion(self): - self.client.login(email="janeLead1@example.com", password="password") - response = self.client.post( - "/leads/attachment/remove/", {"attachment_id": self.attachment.id} - ) - self.assertEqual(response.status_code, 200) - - def test_attachment_valid(self): - upload_file = open("static/images/user.png", "rb") - response = self.client.post( - "/leads/attachment/add/", - { - "leadid": self.lead.id, - "attachment": SimpleUploadedFile(upload_file.name, upload_file.read()), - }, - ) - self.assertEqual(response.status_code, 200) - - -class TestTemplates(TestLeadModel, TestCase): - def test_lead_list_view(self): - resp = self.client.post( - reverse("leads:list"), - { - "name": "search filter", - "tag": "123", - "source": "call", - "assigned_to": "1", - "tab_status": "Open", - }, - ) - self.assertEqual(resp.status_code, 200) - # print(resp.name) - # self.assertTrue(resp.name) - - # def test_lead_from_site(self): - # resp = self.client.get() - - -class TestConvertLeadView(TestLeadModel, TestCase): - def test_get_fun(self): - resp = self.client.get("/leads/" + str(self.lead.id) + "/convert/") - self.assertEqual(resp.status_code, 302) - - -class TestCreateLeadPostView(TestLeadModel, TestCase): - def test_create_lead_post_status(self): - upload_file = open("static/images/user.png", "rb") - response = self.client.post( - "/leads/create/", - { - "first_name": "jane doe", - "last_name": "doe lead", - "title": "lead", - "status": "converted", - "description": "lead descriptoin", - "website": "www.example.com", - "phone": "+91-123-456-7890", - "email": "janedoeLead@example.com", - "account_name": "account", - "address_line": self.lead.address_line, - "street": self.lead.street, - "city": self.lead.city, - "state": self.lead.state, - "postcode": self.lead.postcode, - "country": self.lead.country, - "lead_attachment": SimpleUploadedFile( - upload_file.name, upload_file.read() - ), - "assigned_to": str(self.user.id), - "tags": "tag", - }, - ) - self.assertEqual(response.status_code, 200) - - def test_create_lead_get_request(self): - response = self.client.get(reverse("leads:add_lead")) - self.assertEqual(response.status_code, 200) - - def test_update_lead_post_status(self): - upload_file = open("static/images/user.png", "rb") - response = self.client.post( - "/leads/" + str(self.lead.id) + "/edit/", - { - "first_name": "jane doe lead", - "last_name": "lead last name", - "title": "jane doe", - "created_by": self.user, - "status": "converted", - "description": "description", - "website": "www.example.com", - "phone": "+91-123-456-7890", - "email": "janedoeLead@example.com", - "account_name": "account", - "address_line": self.lead.address_line, - "street": self.lead.street, - "city": self.lead.city, - "state": self.lead.state, - "postcode": self.lead.postcode, - "country": self.lead.country, - "lead_attachment": SimpleUploadedFile( - upload_file.name, upload_file.read() - ), - "assigned_to": str(self.user.id), - "tags": "tag", - }, - ) - self.assertEqual(response.status_code, 200) - - def test_lead_convert(self): - response = self.client.get("/leads/" + str(self.lead.id) + "/convert/") - self.assertEqual(response.status_code, 302) - - -class TestLeadDetailView(TestLeadModel, TestCase): - def test_lead_detail_view(self): - response = self.client.get( - reverse("leads:view_lead", kwargs={"pk": self.lead.id}) - ) - self.assertEqual(response.status_code, 200) - - -class TestLeadFromSite(TestLeadModel, TestCase): - def create_lead_from_site(self): - response = self.client.post( - "/leads/create/from-site/", {"apikey": self.api_seetings.apikey} - ) - self.assertEqual(response.status_code, 200) - - -class TestLeadListView(TestCase): - def setUp(self): - self.client = Client() - self.company, _ = Company.objects.get_or_create( - name="test company", address="IN", sub_domain="test", country="IN" - ) - - self.user = User.objects.create( - username="johnDoeG@lead.com", - email="johnDoeG@lead.com", - has_sales_access=True, - company=self.company, - ) - self.user.set_password("password") - self.user.save() - - self.client.login(username="johnDoeG@lead.com", password="password") - - def test_lead_list_view(self): - response = self.client.get(reverse("leads:list")) - self.assertEqual(response.status_code, 200) - - # response = self.client.post('/leads/create/',{}) - # self.assertEqual(force_text(response.content), {"errors": {"title": ["This field is required."]}, "error": True}) - - -class TestUpdateLeadView(TestLeadModel, TestCase): - def test_lead_update_view(self): - response = self.client.post( - reverse("leads:edit_lead", args=(self.lead.id,)), - {"status": "converted", "country": "AD", "title": "update_title"}, - ) - self.assertEqual(response.status_code, 200) - - response = self.client.post( - reverse("leads:edit_lead", args=(self.lead.id,)), - {"status": "assigned", "country": "AD", "title": "update_title"}, - ) - self.assertEqual(response.status_code, 200) - - response = self.client.post( - reverse("leads:edit_lead", args=(self.lead.id,)), - { - "status": "assigned", - "country": "AD", - "title": "update_title", - "tags": "tag3, tag4", - }, - ) - self.assertEqual(response.status_code, 200) - - response = self.client.post( - reverse("leads:edit_lead", args=(self.lead.id,)), - { - "status": "assigned", - "country": "AD", - "title": "update_title", - "assigned_to": str(self.user.id), - }, - ) - self.assertEqual(response.status_code, 200) - - self.client.login(username="janeLead2@example.com", password="password") - response = self.client.get( - reverse("leads:edit_lead", args=(self.lead.id,)), - {"status": "assigned", "country": "AD", "title": "update_title"}, - ) - self.assertEqual(response.status_code, 200) - self.client.logout() - - -class TestConvertLeadView1(TestLeadModel, TestCase): - def test_convert_lead_view(self): - resp = self.client.get("/leads/" + str(self.lead.id) + "/convert/") - self.assertEqual(resp.status_code, 302) - - -class TestLeadDetailView1(TestLeadModel, TestCase): - def test_lead_detail_view(self): - self.client.login(username="janeLead2@example.com", password="password") - resp = self.client.get(reverse("leads:view_lead", args=(self.lead.id,))) - self.assertEqual(resp.status_code, 200) - self.client.logout() - - -class TestCommentAddResponse(TestLeadModel, TestCase): - def test_comment_add_response(self): - self.client.login(username="janeLead3@example.com", password="password") - response = self.client.post("/leads/comment/add/", {"leadid": self.lead.id}) - self.assertJSONEqual( - force_text(response.content), {"error": ["This field is required."]} - ) - - self.comment_mp = Comment.objects.create( - comment="testikd", case=self.case, commented_by=self.user3 - ) - response = self.client.post( - "/leads/comment/edit/", {"commentid": self.comment_mp.id} - ) - self.assertJSONEqual( - force_text(response.content), {"error": ["This field is required."]} - ) - - response = self.client.post("/leads/attachment/add/", {"leadid": self.lead1.id}) - self.assertJSONEqual( - force_text(response.content), {"error": ["This field is required."]} - ) - - def test_file_upload_for_leads(self): - self.client.logout() - self.client.login(email="johnLead@example.com", password="password") - - file_content = [ - "title,first name,last name,website,phone,email,address\n", - "lead1,john,doe,www.example.com,911234567890,user1@email.com,address for lead1\n", - "lead2,jane,doe,www.website.com,911234567891,user2@email.com,address for lead2\n", - "lead3,joe,doe,www.test.com,911234567892,user3@email.com,address for lead3\n", - "lead4,john,doe,www.sample.com,911234567893,user4@email.com,address for lead4\n", - ] - file_content = bytes("".join(file_content), "utf-8") - data = {"leads_file": SimpleUploadedFile("file name", file_content)} - response = self.client.post(reverse("leads:upload_lead_csv_file"), data) - self.assertEqual(201, response.status_code) - - file_content_missing_headers = [ - ",first name,last name,website,phone,,address\n", - "lead1,john,doe,www.example.com,911234567890,user1@email.com,address for lead1\n", - "lead2,jane,doe,www.website.com,911234567891,user2@email.com,address for lead2\n", - "lead3,joe,doe,www.test.com,911234567892,user3@email.com,address for lead3\n", - "lead4,john,doe,www.sample.com,911234567893,user4@email.com,address for lead4\n", - ] - file_content_missing_headers = bytes( - "".join(file_content_missing_headers), "utf-8" - ) - data = { - "leads_file": SimpleUploadedFile("file name", file_content_missing_headers) - } - response = self.client.post(reverse("leads:upload_lead_csv_file"), data) - - # for invalid lead titles - file_content = [ - "title,first name,last name,website,phone,email,address\n", - ",john,doe,www.example.com,911234567890,user1@email.com,address for lead1\n", - ",jane,doe,www.website.com,911234567891,user2@email.com,address for lead2\n", - ",joe,doe,www.test.com,911234567892,user3@email.com,address for lead3\n", - ",john,doe,www.sample.com,911234567893,user4@email.com,address for lead4\n", - ] - file_content = bytes("".join(file_content), "utf-8") - data = {"leads_file": SimpleUploadedFile("file name", file_content)} - response = self.client.post(reverse("leads:upload_lead_csv_file"), data) - self.assertEqual(200, response.status_code) - - # for invalid email - file_content = [ - "title,first name,last name,website,phone,email,address\n", - "lead1,john,doe,www.example.com,911234567890,user1@email.com,address for lead1\n", - "lead2,jane,doe,www.website.com,911234567891,user2@email.com,address for lead2\n", - "lead3,joe,doe,www.test.com,911234567892,useremail.com,address for lead3\n", - "lead4,john,doe,www.sample.com,911234567893,user4@email,address for lead4\n", - ] - file_content = bytes("".join(file_content), "utf-8") - data = {"leads_file": SimpleUploadedFile("file name", file_content)} - response = self.client.post(reverse("leads:upload_lead_csv_file"), data) - self.assertEqual(201, response.status_code) - - # for invalid file type - data = {"leads_file": b""} - response = self.client.post(reverse("leads:upload_lead_csv_file"), data) - self.assertEqual(200, response.status_code) - - file_content_missing_headers = [ - ",first name,last name,website,phone,,address\n", - "lead1,john,doe,www.example.com,911234567890,user1@email,address for lead1\n", - "lead2,jane,doe,www.website.com,911234567891,user2@email.com,address for lead2\n", - "lead3,joe,doe,www.test.com,911234567892,user3@email.com,address for lead3\n", - "lead4,john,doe,www.sample.com,911234567893,user4@email,address for lead4\n", - ] - file_content_missing_headers = bytes( - "".join(file_content_missing_headers), "utf-8" - ) - data = { - "leads_file": SimpleUploadedFile("file name", file_content_missing_headers) - } - response = self.client.post(reverse("leads:upload_lead_csv_file"), data) - - response = self.client.post(reverse("leads:list") + "?tag=0", {"city": "city"}) - self.assertEqual(response.status_code, 200) - - self.teams_leads = Teams.objects.create(name="teams leads") - self.teams_leads.users.add(self.user1) - response = self.client.post( - reverse("leads:add_lead"), - { - "title": "new lead title", - "teams": [ - self.teams_leads.id, - ], - "savenewform": "true", - }, - ) - self.assertEqual(response.status_code, 200) - response = self.client.post(reverse("leads:add_lead"), {"title": ""}) - self.assertEqual(response.status_code, 200) - - self.client.logout() - self.client.login(email="janeLead3@example.com", password="password") - - response = self.client.get(reverse("leads:view_lead", args=(self.lead_1.id,))) - self.assertEqual(response.status_code, 403) - - response = self.client.get(reverse("leads:view_lead", args=(self.lead1.id,))) - self.assertEqual(response.status_code, 200) - - self.client.logout() - self.client.login(email="janeLead2@example.com", password="password") - self.lead_user = Lead.objects.create( - title="jane doe lead 2", created_by=self.user2 - ) - response = self.client.get( - reverse("leads:view_lead", args=(self.lead_user.id,)) - ) - self.assertEqual(response.status_code, 200) - - self.client.logout() - self.client.login(email="johnLead@example.com", password="password") - response = self.client.get( - reverse("leads:edit_lead", args=(self.lead_1.id,)) + "?status=converted" - ) - self.assertEqual(response.status_code, 200) - - response = self.client.get( - reverse("leads:edit_lead", args=(self.lead_1.id,)) + "?status=c" - ) - self.assertEqual(response.status_code, 200) - - response = self.client.get( - reverse("leads:edit_lead", args=(self.lead_1.id,)) + "?status=converted" - ) - self.assertEqual(response.status_code, 200) - - self.teams_leads.users.add(self.user3) - data = { - "title": self.lead_1.title, - "teams": [ - self.teams_leads.id, - ], - "status": "converted", - "account_name": "lead_conversion", - "email": "account@lead.com", - } - comment = Comment.objects.create( - comment="comment text lead", lead=self.lead_1, commented_by=self.user - ) - response = self.client.post( - reverse("leads:edit_lead", args=(self.lead_1.id,)) + "?status=converted", - data, - ) - self.assertEqual(response.status_code, 200) - - self.client.logout() - self.client.login(email="janeLead3@example.com", password="password") - - response = self.client.get(reverse("leads:remove_lead", args=(self.lead_1.id,))) - self.assertEqual(response.status_code, 403) - - self.client.logout() - self.client.login(email="johnLead@example.com", password="password") - self.lead.email = None - self.lead.save() - response = self.client.get( - reverse("leads:leads_convert", args=(self.lead.id,)) + "?status=converted" - ) - self.assertEqual(response.status_code, 302) - - self.tag_for_lead = Tags.objects.create(name="tag for lead") - data = {"tags": "tag1 lead,tag2 lead,tag for lead"} - response = self.client.post( - reverse("leads:update_lead_tags", args=(self.lead.id,)), data - ) - self.assertEqual(response.status_code, 302) - - self.client.logout() - self.client.login(email="janeLead3@example.com", password="password") - response = self.client.post( - reverse("leads:update_lead_tags", args=(self.lead.id,)), data - ) - self.assertEqual(response.status_code, 403) - - self.client.logout() - self.client.login(email="johnLead@example.com", password="password") - data = {"lead": self.lead.id, "tag": self.tag_for_lead.id} - response = self.client.post(reverse("leads:remove_lead_tag"), data) - self.assertEqual(response.status_code, 200) - - self.client.logout() - self.client.login(email="janeLead3@example.com", password="password") - response = self.client.post(reverse("leads:remove_lead_tag"), data) - self.assertEqual(response.status_code, 200) - - response = self.client.get(reverse("leads:sample_lead_file")) - sample_data = [ - "title,first name,last name,website,phone,email,address\n", - "lead1,john,doe,www.example.com,+911234567890,user1@email.com,address for lead1\n", - "lead2,jane,doe,www.website.com,+911234567891,user2@email.com,address for lead2\n", - "lead3,joe,doe,www.test.com,+911234567892,user3@email.com,address for lead3\n", - "lead4,john,doe,www.sample.com,+911234567893,user4@email.com,address for lead4\n", - ] - content = bytes("".join(sample_data), "utf-8") - self.assertEqual(response.content, content) diff --git a/leads/urls.py b/leads/urls.py deleted file mode 100644 index 75b8c2e..0000000 --- a/leads/urls.py +++ /dev/null @@ -1,51 +0,0 @@ -from django.urls import path -from leads.views import ( - LeadListView, - create_lead, - LeadDetailView, - update_lead, - DeleteLeadView, - convert_lead, - GetLeadsView, - AddCommentView, - UpdateCommentView, - DeleteCommentView, - AddAttachmentsView, - DeleteAttachmentsView, - create_lead_from_site, - update_lead_tags, - remove_lead_tag, - upload_lead_csv_file, - sample_lead_file, - lead_list_view, - get_teams_and_users, -) - - -app_name = "leads" - - -urlpatterns = [ - # path('', LeadListView.as_view(), name='list'), - path("", lead_list_view, name="list"), - path("create/", create_lead, name="add_lead"), - # create_lead_from_site - path("create/from-site/", create_lead_from_site, name="create_lead_from_site"), - path("/view/", LeadDetailView.as_view(), name="view_lead"), - path("/edit/", update_lead, name="edit_lead"), - path("/delete/", DeleteLeadView.as_view(), name="remove_lead"), - path("/convert/", convert_lead, name="leads_convert"), - path("get/list/", GetLeadsView.as_view(), name="get_lead"), - path("comment/add/", AddCommentView.as_view(), name="add_comment"), - path("comment/edit/", UpdateCommentView.as_view(), name="edit_comment"), - path("comment/remove/", DeleteCommentView.as_view(), name="remove_comment"), - path("attachment/add/", AddAttachmentsView.as_view(), name="add_attachment"), - path( - "attachment/remove/", DeleteAttachmentsView.as_view(), name="remove_attachment" - ), - path("update_lead_tags//", update_lead_tags, name="update_lead_tags"), - path("remove_lead_tag/", remove_lead_tag, name="remove_lead_tag"), - path("upload_lead_csv_file/", upload_lead_csv_file, name="upload_lead_csv_file"), - path("sample_lead_file/", sample_lead_file, name="sample_lead_file"), - path("get_teams_and_users/", get_teams_and_users, name="get_teams_and_users"), -] diff --git a/leads/views.py b/leads/views.py deleted file mode 100644 index c2ab17d..0000000 --- a/leads/views.py +++ /dev/null @@ -1,1152 +0,0 @@ -import json - -from django.contrib.auth.decorators import login_required -from django.contrib.auth.mixins import LoginRequiredMixin -from django.contrib.sites.shortcuts import get_current_site -from django.core.exceptions import PermissionDenied -from django.core.mail import EmailMessage -from django.db.models import Q -from django.forms.models import modelformset_factory -from django.http import HttpResponse, HttpResponseRedirect, JsonResponse -from django.shortcuts import get_object_or_404, redirect, render -from django.template.loader import render_to_string -from django.urls import reverse -from django.views.generic import CreateView, DetailView, ListView, TemplateView, View - -from accounts.models import Account, Tags -from common import status -from common.access_decorators_mixins import ( - MarketingAccessRequiredMixin, - SalesAccessRequiredMixin, - marketing_access_required, - sales_access_required, -) -from common.models import APISettings, Attachments, Comment, User -from common.tasks import send_email_user_mentions -from common.utils import COUNTRIES, LEAD_SOURCE, LEAD_STATUS -from contacts.models import Contact -from leads.forms import LeadAttachmentForm, LeadCommentForm, LeadForm, LeadListForm -from leads.models import Lead -from leads.tasks import ( - create_lead_from_file, - send_email_to_assigned_user, - send_lead_assigned_emails, - update_leads_cache, -) -from planner.forms import ReminderForm -from planner.models import Event, Reminder -from teams.models import Teams -from django.core.cache import cache -from django.db.models.functions import Concat -from django.db.models import Value as V - - -@login_required -def get_teams_and_users(request): - data = {} - teams = Teams.objects.all() - teams_data = [ - {"team": team.id, "users": [user.id for user in team.users.all()]} - for team in teams - ] - users = User.objects.all().values_list("id", flat=True) - data["teams"] = teams_data - data["users"] = list(users) - return JsonResponse(data) - - -@login_required -@sales_access_required -def lead_list_view(request): - - queryset = ( - Lead.objects.filter(company=request.company) - .exclude(status="converted") - .select_related("created_by") - .prefetch_related( - "tags", - "assigned_to", - ) - ) - if request.user.role == "ADMIN" or request.user.is_superuser: - queryset = queryset - else: - queryset = queryset.filter( - Q(assigned_to__in=[request.user]) | Q(created_by=request.user) - ) - - if request.method == "GET": - context = {} - if request.GET.get("tag", None): - queryset = queryset.filter(tags__in=request.GET.getlist("tag")) - - open_leads = queryset.exclude(status="closed") - close_leads = queryset.filter(status="closed") - - context["status"] = LEAD_STATUS - context["open_leads"] = open_leads - context["close_leads"] = close_leads - context["per_page"] = request.POST.get("per_page") - context["source"] = LEAD_SOURCE - - context["users"] = ( - User.objects.filter(is_active=True, company=request.company) - .order_by("username") - .values("id", "username") - ) - - tag_ids = list( - set( - queryset.values_list( - "tags", - flat=True, - ) - ) - ) - context["tags"] = Tags.objects.filter(id__in=tag_ids) - return render(request, "leads.html", context) - - if request.method == "POST": - context = {} - search = ( - True - if ( - request.POST.get("name") - or request.POST.get("city") - or request.POST.get("email") - or request.POST.get("tag") - or request.POST.get("status") - or request.POST.get("source") - or request.POST.get("assigned_to") - ) - else False - ) - context["search"] = search - - request_post = request.POST - if request_post: - if request_post.get("name"): - queryset = queryset.annotate( - full_name=Concat("first_name", V(" "), "last_name") - ).filter(full_name__icontains=request_post.get("name")) - if request_post.get("title"): - queryset = queryset.filter( - Q(title__icontains=request_post.get("title")) - ) - # or Q(last_name__icontains=request_post.get('name'))) - if request_post.get("city"): - queryset = queryset.filter(city__icontains=request_post.get("city")) - if request_post.get("email"): - queryset = queryset.filter(email__icontains=request_post.get("email")) - if request_post.get("status"): - queryset = queryset.filter(status=request_post.get("status")) - if request_post.get("tag"): - queryset = queryset.filter(tags__in=request_post.getlist("tag")) - if request_post.get("source"): - queryset = queryset.filter(source=request_post.get("source")) - if request_post.getlist("assigned_to"): - queryset = queryset.filter( - assigned_to__id__in=request_post.getlist("assigned_to") - ) - queryset = queryset.distinct() - - open_leads = queryset.exclude(status="closed") - close_leads = queryset.filter(status="closed") - - context["status"] = LEAD_STATUS - context["open_leads"] = open_leads - context["close_leads"] = close_leads - context["per_page"] = request.POST.get("per_page") - context["source"] = LEAD_SOURCE - - context["users"] = ( - User.objects.filter(is_active=True, company=request.company) - .order_by("email") - .values("id", "email") - ) - tag_ids = list( - set( - queryset.values_list( - "tags", - flat=True, - ) - ) - ) - context["tags"] = Tags.objects.filter(id__in=tag_ids) - - context["assignedto_list"] = [ - int(i) for i in request.POST.getlist("assigned_to", []) if i - ] - context["request_tags"] = request.POST.getlist("tag") - - tab_status = "Open" - if request.POST.get("tab_status"): - tab_status = request.POST.get("tab_status") - context["tab_status"] = tab_status - return render(request, "leads.html", context) - # return context - - -class LeadListView(SalesAccessRequiredMixin, LoginRequiredMixin, TemplateView): - model = Lead - context_object_name = "lead_obj" - template_name = "leads.html" - - def get_queryset(self): - queryset = ( - self.model.objects.all() - .exclude(status="converted") - .select_related("created_by") - .prefetch_related( - "tags", - "assigned_to", - ) - ) # .defer('first_name', 'last_name', 'email', - # 'phone', 'address_line', 'street', 'city', 'postcode', 'website', 'description', - # 'account_name', 'opportunity_amount', 'enquery_type', 'created_from_site', - # 'teams', 'contacts', 'tags__slug', 'created_by__username', 'created_by__first_name', - # 'created_by__last_name', 'created_by__last_login', 'created_by__password', - # 'created_by__date_joined', 'assigned_to__username', 'assigned_to__first_name', - # 'assigned_to__last_name', 'assigned_to__last_login', 'assigned_to__password', - # 'assigned_to__date_joined') - if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: - queryset = queryset.filter( - Q(assigned_to__in=[self.request.user]) | Q(created_by=self.request.user) - ) - - if self.request.GET.get("tag", None): - queryset = queryset.filter(tags__in=self.request.GET.getlist("tag")) - - request_post = self.request.POST - if request_post: - if request_post.get("name"): - queryset = queryset.filter( - Q(first_name__icontains=request_post.get("name")) - & Q(last_name__icontains=request_post.get("name")) - ) - if request_post.get("city"): - queryset = queryset.filter(city__icontains=request_post.get("city")) - if request_post.get("email"): - queryset = queryset.filter(email__icontains=request_post.get("email")) - if request_post.get("status"): - queryset = queryset.filter(status=request_post.get("status")) - if request_post.get("tag"): - queryset = queryset.filter(tags__in=request_post.getlist("tag")) - if request_post.get("source"): - queryset = queryset.filter(source=request_post.get("source")) - if request_post.getlist("assigned_to"): - queryset = queryset.filter( - assigned_to__id__in=request_post.getlist("assigned_to") - ) - return queryset.distinct() - - def get_context_data(self, **kwargs): - context = super(LeadListView, self).get_context_data(**kwargs) - # context["lead_obj"] = self.get_queryset() - open_leads = self.get_queryset().exclude(status="closed") - close_leads = self.get_queryset().filter(status="closed") - # # code for caching - # if self.request.user.role == 'ADMIN' or self.request.user.is_superuser: - # if not cache.get('admin_leads_open_queryset'): - # open_leads = self.get_queryset().exclude(status='closed') - # close_leads = self.get_queryset().filter(status='closed') - # cache.set('admin_leads_open_queryset', open_leads, 60*60) - # cache.set('admin_leads_close_queryset', close_leads, 60*60) - # else: - # open_leads = cache.get('admin_leads_open_queryset') - # close_leads = cache.get('admin_leads_close_queryset') - # else: - # open_leads = self.get_queryset().exclude(status='closed') - # close_leads = self.get_queryset().filter(status='closed') - - context["status"] = LEAD_STATUS - context["open_leads"] = open_leads - context["close_leads"] = close_leads - context["per_page"] = self.request.POST.get("per_page") - context["source"] = LEAD_SOURCE - # if not cache.get('lead_form_users'): - # lead_users = User.objects.filter( - # is_active=True).order_by('email').values('id', 'email') - # cache.set('lead_form_users', lead_users, 60*60) - # else: - # lead_users = cache.get('lead_form_users') - context["users"] = ( - User.objects.filter(is_active=True).order_by("email").values("id", "email") - ) - - context["assignedto_list"] = [ - int(i) for i in self.request.POST.getlist("assigned_to", []) if i - ] - context["request_tags"] = self.request.POST.getlist("tag") - - search = ( - True - if ( - self.request.POST.get("name") - or self.request.POST.get("city") - or self.request.POST.get("email") - or self.request.POST.get("tag") - or self.request.POST.get("status") - or self.request.POST.get("source") - or self.request.POST.get("assigned_to") - ) - else False - ) - - context["search"] = search - - tag_ids = list( - set( - self.get_queryset().values_list( - "tags", - flat=True, - ) - ) - ) - context["tags"] = Tags.objects.filter(id__in=tag_ids) - - tab_status = "Open" - if self.request.POST.get("tab_status"): - tab_status = self.request.POST.get("tab_status") - context["tab_status"] = tab_status - return context - - def post(self, request, *args, **kwargs): - context = self.get_context_data(**kwargs) - return self.render_to_response(context) - - -@login_required -@sales_access_required -def create_lead(request): - template_name = "create_lead.html" - users = [] - if request.user.role == "ADMIN" or request.user.is_superuser: - users = User.objects.filter(is_active=True, company=request.company).order_by( - "email" - ) - elif request.user.google.all(): - users = [] - else: - users = User.objects.filter(role="ADMIN", company=request.company).order_by( - "email" - ) - form = LeadForm(assigned_to=users, request_obj=request) - - if request.POST: - form = LeadForm( - request.POST, request.FILES, assigned_to=users, request_obj=request - ) - if form.is_valid(): - lead_obj = form.save(commit=False) - lead_obj.created_by = request.user - lead_obj.company = request.company - lead_obj.save() - if request.POST.get("tags", ""): - tags = request.POST.get("tags") - splitted_tags = tags.split(",") - for t in splitted_tags: - tag = Tags.objects.filter(name=t) - if tag: - tag = tag[0] - else: - tag = Tags.objects.create(name=t) - lead_obj.tags.add(tag) - if request.POST.getlist("assigned_to", []): - lead_obj.assigned_to.add(*request.POST.getlist("assigned_to")) - assigned_to_list = request.POST.getlist("assigned_to") - # current_site = get_current_site(request) - # recipients = assigned_to_list - # send_email_to_assigned_user.delay(recipients, lead_obj.id, domain=current_site.domain, - # protocol=request.scheme) - # for assigned_to_user in assigned_to_list: - # user = get_object_or_404(User, pk=assigned_to_user) - # mail_subject = 'Assigned to lead.' - # message = render_to_string( - # 'assigned_to/leads_assigned.html', { - # 'user': user, - # 'domain': current_site.domain, - # 'protocol': request.scheme, - # 'lead': lead_obj - # }) - # email = EmailMessage( - # mail_subject, message, to=[user.email]) - # email.content_subtype = "html" - # email.send() - if request.POST.getlist("teams", []): - user_ids = Teams.objects.filter( - id__in=request.POST.getlist("teams") - ).values_list("users", flat=True) - assinged_to_users_ids = lead_obj.assigned_to.all().values_list( - "id", flat=True - ) - for user_id in user_ids: - if user_id not in assinged_to_users_ids: - lead_obj.assigned_to.add(user_id) - - if request.POST.getlist("teams", []): - lead_obj.teams.add(*request.POST.getlist("teams")) - - current_site = get_current_site(request) - recipients = list(lead_obj.assigned_to.all().values_list("id", flat=True)) - send_email_to_assigned_user.delay( - recipients, - lead_obj.id, - domain=current_site.domain, - protocol=request.scheme, - ) - - if request.FILES.get("lead_attachment"): - attachment = Attachments() - attachment.created_by = request.user - attachment.file_name = request.FILES.get("lead_attachment").name - attachment.lead = lead_obj - attachment.attachment = request.FILES.get("lead_attachment") - attachment.save() - - if request.POST.get("status") == "converted": - account_object = Account.objects.create( - created_by=request.user, - name=lead_obj.account_name, - email=lead_obj.email, - phone=lead_obj.phone, - description=request.POST.get("description"), - website=request.POST.get("website"), - company=request.company, - ) - account_object.billing_address_line = lead_obj.address_line - account_object.billing_street = lead_obj.street - account_object.billing_city = lead_obj.city - account_object.billing_state = lead_obj.state - account_object.billing_postcode = lead_obj.postcode - account_object.billing_country = lead_obj.country - for tag in lead_obj.tags.all(): - account_object.tags.add(tag) - - if request.POST.getlist("assigned_to", []): - # account_object.assigned_to.add(*request.POST.getlist('assigned_to')) - assigned_to_list = request.POST.getlist("assigned_to") - current_site = get_current_site(request) - recipients = assigned_to_list - send_email_to_assigned_user.delay( - recipients, - lead_obj.id, - domain=current_site.domain, - protocol=request.scheme, - ) - # for assigned_to_user in assigned_to_list: - # user = get_object_or_404(User, pk=assigned_to_user) - # mail_subject = 'Assigned to account.' - # message = render_to_string( - # 'assigned_to/account_assigned.html', { - # 'user': user, - # 'domain': current_site.domain, - # 'protocol': request.scheme, - # 'account': account_object - # }) - # email = EmailMessage( - # mail_subject, message, to=[user.email]) - # email.content_subtype = "html" - # email.send() - - account_object.save() - # update_leads_cache.delay() - success_url = reverse("leads:list") - if request.POST.get("savenewform"): - success_url = reverse("leads:add_lead") - return JsonResponse({"error": False, "success_url": success_url}) - return JsonResponse({"error": True, "errors": form.errors}) - context = {} - context["lead_form"] = form - context["accounts"] = Account.objects.filter(status="open") - context["users"] = users - context["countries"] = COUNTRIES - context["status"] = LEAD_STATUS - context["source"] = LEAD_SOURCE - context["teams"] = Teams.objects.filter(company=request.company) - context["assignedto_list"] = [ - int(i) for i in request.POST.getlist("assigned_to", []) if i - ] - - return render(request, template_name, context) - - -class LeadDetailView(SalesAccessRequiredMixin, LoginRequiredMixin, DetailView): - model = Lead - context_object_name = "lead_record" - template_name = "view_leads.html" - - def dispatch(self, request, *args, **kwargs): - contact = self.get_object() - if contact.company != request.company: - raise PermissionDenied - return super(LeadDetailView, self).dispatch(request, *args, **kwargs) - - def get_context_data(self, **kwargs): - context = super(LeadDetailView, self).get_context_data(**kwargs) - user_assgn_list = [ - assigned_to.id for assigned_to in context["object"].assigned_to.all() - ] - if self.request.user == context["object"].created_by: - user_assgn_list.append(self.request.user.id) - if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: - if self.request.user.id not in user_assgn_list: - raise PermissionDenied - comments = Comment.objects.filter(lead__id=self.object.id).order_by("-id") - attachments = Attachments.objects.filter(lead__id=self.object.id).order_by( - "-id" - ) - events = Event.objects.filter( - Q(created_by=self.request.user) | Q(updated_by=self.request.user) - ).filter(attendees_leads=context["lead_record"]) - meetings = events.filter(event_type="Meeting").order_by("-id") - calls = events.filter(event_type="Call").order_by("-id") - RemindersFormSet = modelformset_factory( - Reminder, form=ReminderForm, can_delete=True - ) - reminder_form_set = RemindersFormSet( - { - "form-TOTAL_FORMS": "1", - "form-INITIAL_FORMS": "0", - "form-MAX_NUM_FORMS": "10", - } - ) - - assigned_data = [] - for each in context["lead_record"].assigned_to.all(): - assigned_dict = {} - assigned_dict["id"] = each.id - assigned_dict["name"] = each.email - assigned_data.append(assigned_dict) - - if self.request.user.is_superuser or self.request.user.role == "ADMIN": - users_mention = list( - User.objects.filter( - is_active=True, company=self.request.company - ).values("username") - ) - elif self.request.user != context["object"].created_by: - users_mention = [{"username": context["object"].created_by.username}] - else: - users_mention = list(context["object"].assigned_to.all().values("username")) - - context.update( - { - "attachments": attachments, - "comments": comments, - "status": LEAD_STATUS, - "countries": COUNTRIES, - "reminder_form_set": reminder_form_set, - "meetings": meetings, - "calls": calls, - "users_mention": users_mention, - "assigned_data": json.dumps(assigned_data), - } - ) - return context - - -@login_required -@sales_access_required -def update_lead(request, pk): - lead_record = Lead.objects.filter(pk=pk).first() - - if lead_record.company != request.company: - raise PermissionDenied - - template_name = "create_lead.html" - users = [] - if request.user.role == "ADMIN" or request.user.is_superuser: - users = User.objects.filter(is_active=True, company=request.company).order_by( - "email" - ) - else: - users = User.objects.filter(role="ADMIN", company=request.company).order_by( - "email" - ) - status = request.GET.get("status", None) - initial = {} - if status and status == "converted": - error = "This field is required." - lead_record.status = "converted" - initial.update({"status": status, "lead": lead_record.id}) - error = "" - form = LeadForm( - instance=lead_record, - initial=initial, - assigned_to=users, - request_obj=request, - ) - - if request.POST: - form = LeadForm( - request.POST, - request.FILES, - instance=lead_record, - initial=initial, - assigned_to=users, - request_obj=request, - ) - - if request.POST.get("status") == "converted": - form.fields["account_name"].required = True - form.fields["email"].required = True - else: - form.fields["account_name"].required = False - form.fields["email"].required = False - if form.is_valid(): - assigned_to_ids = lead_record.assigned_to.all().values_list("id", flat=True) - lead_obj = form.save(commit=False) - lead_obj.save() - previous_assigned_to_users = list( - lead_obj.assigned_to.all().values_list("id", flat=True) - ) - lead_obj.tags.clear() - all_members_list = [] - if request.POST.get("tags", ""): - tags = request.POST.get("tags") - splitted_tags = tags.split(",") - for t in splitted_tags: - tag = Tags.objects.filter(name=t) - if tag: - tag = tag[0] - else: - tag = Tags.objects.create(name=t) - lead_obj.tags.add(tag) - if request.POST.getlist("assigned_to", []): - if request.POST.get("status") != "converted": - - current_site = get_current_site(request) - - assigned_form_users = form.cleaned_data.get( - "assigned_to" - ).values_list("id", flat=True) - all_members_list = list( - set(list(assigned_form_users)) - set(list(assigned_to_ids)) - ) - # current_site = get_current_site(request) - # recipients = all_members_list - # send_email_to_assigned_user.delay(recipients, lead_obj.id, domain=current_site.domain, - # protocol=request.scheme) - # if all_members_list: - # for assigned_to_user in all_members_list: - # user = get_object_or_404(User, pk=assigned_to_user) - # mail_subject = 'Assigned to lead.' - # message = render_to_string( - # 'assigned_to/leads_assigned.html', { - # 'user': user, - # 'domain': current_site.domain, - # 'protocol': request.scheme, - # 'lead': lead_obj - # }) - # email = EmailMessage( - # mail_subject, message, to=[user.email]) - # email.content_subtype = "html" - # email.send() - - lead_obj.assigned_to.clear() - lead_obj.assigned_to.add(*request.POST.getlist("assigned_to")) - else: - lead_obj.assigned_to.clear() - - if request.POST.getlist("teams", []): - user_ids = Teams.objects.filter( - id__in=request.POST.getlist("teams") - ).values_list("users", flat=True) - assinged_to_users_ids = lead_obj.assigned_to.all().values_list( - "id", flat=True - ) - for user_id in user_ids: - if user_id not in assinged_to_users_ids: - lead_obj.assigned_to.add(user_id) - - if request.POST.getlist("teams", []): - lead_obj.teams.clear() - lead_obj.teams.add(*request.POST.getlist("teams")) - else: - lead_obj.teams.clear() - - current_site = get_current_site(request) - assigned_to_list = list( - lead_obj.assigned_to.all().values_list("id", flat=True) - ) - recipients = list(set(assigned_to_list) - set(previous_assigned_to_users)) - send_email_to_assigned_user.delay( - recipients, - lead_obj.id, - domain=current_site.domain, - protocol=request.scheme, - ) - # update_leads_cache.delay() - if request.FILES.get("lead_attachment"): - attachment = Attachments() - attachment.created_by = request.user - attachment.file_name = request.FILES.get("lead_attachment").name - attachment.lead = lead_obj - attachment.attachment = request.FILES.get("lead_attachment") - attachment.save() - - if request.POST.get("status") == "converted": - account_object = Account.objects.create( - created_by=request.user, - name=lead_obj.account_name, - email=lead_obj.email, - phone=lead_obj.phone, - description=request.POST.get("description"), - website=request.POST.get("website"), - lead=lead_obj, - company=request.company, - ) - account_object.billing_address_line = lead_obj.address_line - account_object.billing_street = lead_obj.street - account_object.billing_city = lead_obj.city - account_object.billing_state = lead_obj.state - account_object.billing_postcode = lead_obj.postcode - account_object.billing_country = lead_obj.country - for tag in lead_obj.tags.all(): - account_object.tags.add(tag) - if request.POST.getlist("assigned_to", []): - # account_object.assigned_to.add(*request.POST.getlist('assigned_to')) - assigned_to_list = request.POST.getlist("assigned_to") - current_site = get_current_site(request) - recipients = assigned_to_list - send_email_to_assigned_user.delay( - recipients, - lead_obj.id, - domain=current_site.domain, - protocol=request.scheme, - ) - # current_site = get_current_site(request) - # for assigned_to_user in assigned_to_list: - # user = get_object_or_404(User, pk=assigned_to_user) - # mail_subject = 'Assigned to account.' - # message = render_to_string( - # 'assigned_to/account_assigned.html', { - # 'user': user, - # 'domain': current_site.domain, - # 'protocol': request.scheme, - # 'account': account_object - # }) - # email = EmailMessage( - # mail_subject, message, to=[user.email]) - # email.content_subtype = "html" - # email.send() - - for comment in lead_obj.leads_comments.all(): - comment.account = account_object - comment.save() - account_object.save() - status = request.GET.get("status", None) - success_url = reverse("leads:list") - if status: - success_url = reverse("accounts:list") - return JsonResponse({"error": False, "success_url": success_url}) - return JsonResponse({"error": True, "errors": form.errors}) - context = {} - context["lead_obj"] = lead_record - user_assgn_list = [ - assigned_to.id for assigned_to in lead_record.get_assigned_users_not_in_teams - ] - - if request.user == lead_record.created_by: - user_assgn_list.append(request.user.id) - if request.user.role != "ADMIN" and not request.user.is_superuser: - if request.user.id not in user_assgn_list: - raise PermissionDenied - team_ids = [user.id for user in lead_record.get_team_users] - all_user_ids = [user.id for user in users] - users_excluding_team_id = set(all_user_ids) - set(team_ids) - users_excluding_team = User.objects.filter(id__in=users_excluding_team_id) - context["lead_form"] = form - context["accounts"] = Account.objects.filter(status="open") - context["users"] = users - context["users_excluding_team"] = users_excluding_team - context["countries"] = COUNTRIES - context["status"] = LEAD_STATUS - context["source"] = LEAD_SOURCE - context["error"] = error - context["teams"] = Teams.objects.filter(company=request.company) - context["assignedto_list"] = [ - int(i) for i in request.POST.getlist("assigned_to", []) if i - ] - return render(request, template_name, context) - - -class DeleteLeadView(SalesAccessRequiredMixin, LoginRequiredMixin, View): - def get(self, request, *args, **kwargs): - return self.post(request, *args, **kwargs) - - def post(self, request, *args, **kwargs): - self.object = get_object_or_404(Lead, id=kwargs.get("pk")) - if ( - self.request.user.role == "ADMIN" - or self.request.user.is_superuser - or self.request.user == self.object.created_by - ) and self.object.company == request.company: - self.object.delete() - # update_leads_cache.delay() - if request.GET.get("page"): - return HttpResponseRedirect( - reverse("leads:list") + "?page=" + request.GET.get("page") - ) - return redirect("leads:list") - raise PermissionDenied - - -def convert_lead(request, pk): - lead_obj = get_object_or_404(Lead, id=pk) - if lead_obj.account_name and lead_obj.email: - lead_obj.status = "converted" - lead_obj.save() - account_object = Account.objects.create( - created_by=request.user, - name=lead_obj.account_name, - email=lead_obj.email, - phone=lead_obj.phone, - description=lead_obj.description, - website=lead_obj.website, - billing_address_line=lead_obj.address_line, - billing_street=lead_obj.street, - billing_city=lead_obj.city, - billing_state=lead_obj.state, - billing_postcode=lead_obj.postcode, - billing_country=lead_obj.country, - lead=lead_obj, - ) - contacts_list = lead_obj.contacts.all().values_list("id", flat=True) - account_object.contacts.add(*contacts_list) - account_obj = account_object.save() - current_site = get_current_site(request) - for assigned_to_user in lead_obj.assigned_to.all().values_list("id", flat=True): - user = get_object_or_404(User, pk=assigned_to_user) - mail_subject = "Assigned to account." - message = render_to_string( - "assigned_to/account_assigned.html", - { - "user": user, - "domain": current_site.domain, - "protocol": request.scheme, - "account": account_object, - }, - ) - email = EmailMessage(mail_subject, message, to=[user.email]) - email.content_subtype = "html" - email.send() - return redirect("accounts:list") - - return HttpResponseRedirect( - reverse("leads:edit_lead", kwargs={"pk": lead_obj.id}) + "?status=converted" - ) - - -class AddCommentView(LoginRequiredMixin, CreateView): - model = Comment - form_class = LeadCommentForm - http_method_names = ["post"] - - def post(self, request, *args, **kwargs): - self.object = None - self.lead = get_object_or_404(Lead, id=request.POST.get("leadid")) - if ( - request.user in self.lead.assigned_to.all() - or request.user == self.lead.created_by - or request.user.is_superuser - or request.user.role == "ADMIN" - ): - form = self.get_form() - if form.is_valid(): - return self.form_valid(form) - - return self.form_invalid(form) - - data = {"error": "You don't have permission to comment."} - return JsonResponse(data) - - def form_valid(self, form): - comment = form.save(commit=False) - comment.commented_by = self.request.user - comment.lead = self.lead - comment.save() - comment_id = comment.id - current_site = get_current_site(self.request) - send_email_user_mentions.delay( - comment_id, - "leads", - domain=current_site.domain, - protocol=self.request.scheme, - ) - return JsonResponse( - { - "comment_id": comment.id, - "comment": comment.comment, - "commented_on": comment.commented_on, - "commented_on_arrow": comment.commented_on_arrow, - "commented_by": comment.commented_by.email, - } - ) - - def form_invalid(self, form): - return JsonResponse({"error": form["comment"].errors}) - - -class UpdateCommentView(LoginRequiredMixin, View): - http_method_names = ["post"] - - def post(self, request, *args, **kwargs): - self.comment_obj = get_object_or_404(Comment, id=request.POST.get("commentid")) - if request.user == self.comment_obj.commented_by: - form = LeadCommentForm(request.POST, instance=self.comment_obj) - if form.is_valid(): - return self.form_valid(form) - - return self.form_invalid(form) - - data = {"error": "You don't have permission to edit this comment."} - return JsonResponse(data) - - def form_valid(self, form): - self.comment_obj.comment = form.cleaned_data.get("comment") - self.comment_obj.save(update_fields=["comment"]) - comment_id = self.comment_obj.id - current_site = get_current_site(self.request) - send_email_user_mentions.delay( - comment_id, - "leads", - domain=current_site.domain, - protocol=self.request.scheme, - ) - return JsonResponse( - { - "commentid": self.comment_obj.id, - "comment": self.comment_obj.comment, - } - ) - - def form_invalid(self, form): - return JsonResponse({"error": form["comment"].errors}) - - -class DeleteCommentView(LoginRequiredMixin, View): - def post(self, request, *args, **kwargs): - self.object = get_object_or_404(Comment, id=request.POST.get("comment_id")) - if request.user == self.object.commented_by: - self.object.delete() - data = {"cid": request.POST.get("comment_id")} - return JsonResponse(data) - - data = {"error": "You don't have permission to delete this comment."} - return JsonResponse(data) - - -class GetLeadsView(LoginRequiredMixin, ListView): - model = Lead - context_object_name = "leads" - template_name = "leads_list.html" - - -class AddAttachmentsView(LoginRequiredMixin, CreateView): - model = Attachments - form_class = LeadAttachmentForm - http_method_names = ["post"] - - def post(self, request, *args, **kwargs): - self.object = None - self.lead = get_object_or_404(Lead, id=request.POST.get("leadid")) - if ( - request.user in self.lead.assigned_to.all() - or request.user == self.lead.created_by - or request.user.is_superuser - or request.user.role == "ADMIN" - ): - form = self.get_form() - if form.is_valid(): - return self.form_valid(form) - return self.form_invalid(form) - - data = {"error": "You don't have permission to add attachment."} - return JsonResponse(data) - - def form_valid(self, form): - attachment = form.save(commit=False) - attachment.created_by = self.request.user - attachment.file_name = attachment.attachment.name - attachment.lead = self.lead - attachment.save() - return JsonResponse( - { - "attachment_id": attachment.id, - "attachment": attachment.file_name, - "attachment_url": attachment.attachment.url, - "created_on": attachment.created_on, - "created_on_arrow": attachment.created_on_arrow, - "created_by": attachment.created_by.email, - "download_url": reverse( - "common:download_attachment", kwargs={"pk": attachment.id} - ), - "attachment_display": attachment.get_file_type_display(), - "file_type": attachment.file_type(), - } - ) - - def form_invalid(self, form): - return JsonResponse({"error": form["attachment"].errors}) - - -class DeleteAttachmentsView(LoginRequiredMixin, View): - def post(self, request, *args, **kwargs): - self.object = get_object_or_404( - Attachments, id=request.POST.get("attachment_id") - ) - if ( - request.user == self.object.created_by - or request.user.is_superuser - or request.user.role == "ADMIN" - ): - self.object.delete() - data = {"aid": request.POST.get("attachment_id")} - return JsonResponse(data) - - data = {"error": "You don't have permission to delete this attachment."} - return JsonResponse(data) - - -def create_lead_from_site(request): - if request.method == "POST": - # ip_addres = get_client_ip(request) - # website_address = request.scheme + '://' + ip_addres - api_key = request.POST.get("apikey") - # api_setting = APISettings.objects.filter( - # website=website_address, apikey=api_key).first() - api_setting = APISettings.objects.filter(apikey=api_key).first() - if not api_setting: - return JsonResponse( - { - "error": True, - "message": "You don't have permission, please contact the admin!.", - }, - status=status.HTTP_400_BAD_REQUEST, - ) - - if api_setting and request.POST.get("email") and request.POST.get("full_name"): - # user = User.objects.filter(is_admin=True, is_active=True).first() - user = api_setting.created_by - lead = Lead.objects.create( - title=request.POST.get("full_name"), - status="assigned", - source=api_setting.website, - description=request.POST.get("message"), - email=request.POST.get("email"), - phone=request.POST.get("phone"), - is_active=True, - created_by=user, - ) - lead.assigned_to.add(user) - # Send Email to Assigned Users - site_address = request.scheme + "://" + request.META["HTTP_HOST"] - send_lead_assigned_emails.delay(lead.id, [user.id], site_address) - # Create Contact - contact = Contact.objects.create( - first_name=request.POST.get("full_name"), - email=request.POST.get("email"), - phone=request.POST.get("phone"), - description=request.POST.get("message"), - created_by=user, - is_active=True, - ) - contact.assigned_to.add(user) - - lead.contacts.add(contact) - - return JsonResponse( - {"error": False, "message": "Lead Created sucessfully."}, - status=status.HTTP_201_CREATED, - ) - return JsonResponse( - {"error": True, "message": "In-valid data."}, - status=status.HTTP_400_BAD_REQUEST, - ) - return JsonResponse( - {"error": True, "message": "In-valid request method."}, - status=status.HTTP_400_BAD_REQUEST, - ) - - -@login_required -@sales_access_required -def update_lead_tags(request, pk): - lead = get_object_or_404(Lead, pk=pk) - if ( - request.user == lead.created_by - or request.user.role == "ADMIN" - or request.user.is_superuser - ): - lead.tags.clear() - if request.POST.get("tags", ""): - tags = request.POST.get("tags") - splitted_tags = tags.split(",") - for t in splitted_tags: - tag = Tags.objects.filter(name=t) - if tag: - tag = tag[0] - else: - tag = Tags.objects.create(name=t) - lead.tags.add(tag) - else: - raise PermissionDenied - return HttpResponseRedirect(request.POST.get("full_path")) - - -@login_required -@sales_access_required -def remove_lead_tag(request): - data = {} - lead_id = request.POST.get("lead") - tag_id = request.POST.get("tag") - lead = get_object_or_404(Lead, pk=lead_id) - if ( - request.user == lead.created_by - or request.user.role == "ADMIN" - or request.user.is_superuser - ): - lead.tags.remove(tag_id) - data = {"data": "Tag Removed"} - else: - data = {"error": "You don't have permission to delete this tag."} - return JsonResponse(data) - - -@login_required -@sales_access_required -def upload_lead_csv_file(request): - if request.method == "POST": - lead_form = LeadListForm(request.POST, request.FILES) - if lead_form.is_valid(): - create_lead_from_file.delay( - lead_form.validated_rows, - lead_form.invalid_rows, - request.user.id, - request.get_host(), - request.company.id, - ) - return JsonResponse( - {"error": False, "data": lead_form.data}, status=status.HTTP_201_CREATED - ) - else: - return JsonResponse( - {"error": True, "errors": lead_form.errors}, status=status.HTTP_200_OK - ) - - -def sample_lead_file(request): - sample_data = [ - "title,first name,last name,website,phone,email,address\n", - "lead1,john,doe,www.example.com,+911234567890,user1@email.com,address for lead1\n", - "lead2,jane,doe,www.website.com,+911234567891,user2@email.com,address for lead2\n", - "lead3,joe,doe,www.test.com,+911234567892,user3@email.com,address for lead3\n", - "lead4,john,doe,www.sample.com,+911234567893,user4@email.com,address for lead4\n", - ] - response = HttpResponse(sample_data, content_type="text/plain") - response["Content-Disposition"] = "attachment; filename={}".format( - "sample_data.csv" - ) - return response diff --git a/marketing/__init__.py b/marketing/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/marketing/admin.py b/marketing/admin.py deleted file mode 100644 index 8c38f3f..0000000 --- a/marketing/admin.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.contrib import admin - -# Register your models here. diff --git a/marketing/apps.py b/marketing/apps.py deleted file mode 100644 index 5d6b252..0000000 --- a/marketing/apps.py +++ /dev/null @@ -1,5 +0,0 @@ -from django.apps import AppConfig - - -class MarketingConfig(AppConfig): - name = "marketing" diff --git a/marketing/forms.py b/marketing/forms.py deleted file mode 100644 index a6a881c..0000000 --- a/marketing/forms.py +++ /dev/null @@ -1,596 +0,0 @@ -import csv -import datetime -import re - -import openpyxl -import xlrd -from django import forms - -from marketing.models import ( - BlockedDomain, - BlockedEmail, - Campaign, - Contact, - ContactEmailCampaign, - ContactList, - EmailTemplate, -) - -# from haystack.forms import SearchForm - -email_regex = r"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)" - - -def csv_doc_validate(document): - temp_row = [] - invalid_row = [] - # this stores all the failed csv contacts - failed_contacts_csv = [] - reader = csv.reader((document.read().decode("iso-8859-1")).splitlines()) - # csv_headers = ["first name", "last name", "email"] - csv_headers = ["first name", "email"] - # required_headers = ["first name", "last name", "email"] - required_headers = ["first name", "email"] - for y_index, row in enumerate(reader): - each = {} - invalid_each = {} - if y_index == 0: - csv_headers = [header_name.lower() for header_name in row if header_name] - missing_headers = set(required_headers) - set([r.lower() for r in row]) - if missing_headers: - missing_headers_str = ", ".join(missing_headers) - message = "Missing headers: %s" % (missing_headers_str) - return {"error": True, "message": message} - continue - elif not "".join(str(x) for x in row): - continue - else: - for x_index, cell_value in enumerate(row): - try: - csv_headers[x_index] - except IndexError: - continue - if csv_headers[x_index] in required_headers: - if not cell_value: - # message = 'Missing required value %s for row %s' % ( - # csv_headers[x_index], y_index + 1) - # return {"error": True, "message": message} - invalid_each[csv_headers[x_index]] = cell_value - else: - if csv_headers[x_index] == "email": - if re.match(email_regex, cell_value) is None: - invalid_each[csv_headers[x_index]] = cell_value - each[csv_headers[x_index]] = cell_value - if invalid_each: - invalid_row.append(each) - failed_contacts_csv.append(list(each.values())) - else: - temp_row.append(each) - return { - "error": False, - "validated_rows": temp_row, - "invalid_rows": invalid_row, - "headers": csv_headers, - "failed_contacts_csv": failed_contacts_csv, - } - - -# def get_validated_rows(wb, sheet_name, validated_rows, invalid_rows): -# # headers = ["first name", "last name", "email"] -# # required_headers = ["first name", "last name", "email"] -# headers = ["first name", "email"] -# required_headers = ["first name", "email"] -# work_sheet = wb.get_sheet_by_name(name=sheet_name) -# for y_index, row in enumerate(work_sheet.iter_rows()): -# if y_index == 0: -# missing_headers = set(required_headers) - \ -# set([str(cell.value).lower() for cell in row]) -# if missing_headers: -# missing_headers_str = ', '.join(missing_headers) -# message = "Missing headers: %s %s" % ( -# missing_headers_str, sheet_name) -# return {"error": True, "message": message} -# continue -# elif not ''.join(str(cell.value) for cell in row): -# continue -# else: -# temp_row = [] -# invalid_row = [] -# for x_index, cell in enumerate(row): -# try: -# headers[x_index] -# except IndexError: -# continue -# if headers[x_index] in required_headers: -# if not cell.value: -# # message = 'Missing required \ -# # value %s for row %s in sheet %s'\ -# # % (headers[x_index], y_index + 1, sheet_name) -# # return {"error": True, "message": message} -# invalid_row.append(headers[x_index]) -# temp_row.append(cell.value) -# if len(invalid_row) > 0: -# invalid_rows.append(temp_row) -# else: -# if len(temp_row) >= len(required_headers): -# validated_rows.append(temp_row) -# return validated_rows, invalid_rows - - -def get_validated_rows(wb, sheet_name, validated_rows, invalid_rows): - wb_sheet = wb[sheet_name] - sheet_headers = [cell.value for cell in wb_sheet[1]] - required_headers = ["first name", "email"] - - # this condition will check if the both fields in required_headers exist - if not len(set(sheet_headers).intersection(required_headers)) == 2: - missing_headers = set(required_headers) - set(sheet_headers) - missing_headers_str = ", ".join(missing_headers) - message = "Missing headers: {}".format(missing_headers_str) - return {"error": True, "message": message}, message - else: - data = [] - for row in wb_sheet.rows: - d = {} - for key, cell_value in zip(sheet_headers, row): - d[key] = cell_value.value - data.append(d) - # remove the first element, it contains no values - data.pop(0) - if len(data): - validated_rows = [] - invalid_rows = [] - for row in data: - if row.get("email", None): - if re.match(email_regex, row.get("email", None)) is None: - invalid_rows.append(row) - else: - validated_rows.append(row) - return validated_rows, invalid_rows - - -def xlsx_doc_validate(document): - wb = openpyxl.load_workbook(document) - sheets = wb.sheetnames - validated_rows = [] - invalid_rows = [] - for sheet_name in sheets: - valid_data, invalid_data = get_validated_rows( - wb, sheet_name, validated_rows, invalid_rows - ) - if isinstance(valid_data, dict): - return valid_data - validated_rows = validated_rows + valid_data - invalid_rows = invalid_rows + invalid_data - return { - "error": False, - "validated_rows": validated_rows, - "invalid_rows": invalid_rows, - } - - -def get_validated_rows_xls(wb, sheet_name, validated_rows, invalid_rows): - wb_sheet = wb.sheet_by_name(sheet_name) - sheet_headers = [cell.value for cell in wb_sheet.row(0)] - required_headers = ["first name", "email"] - - # this condition will check if the both fields in required_headers exist - if not len(set(sheet_headers).intersection(required_headers)) == 2: - missing_headers = set(required_headers) - set(sheet_headers) - missing_headers_str = ", ".join(missing_headers) - message = "Missing headers: {}".format(missing_headers_str) - return {"error": True, "message": message}, message - else: - no_of_rows = wb_sheet.nrows - data = [] - for nrow in range(no_of_rows): - d = {} - for key, cell_value in zip( - sheet_headers, [cell.value for cell in wb_sheet.row(nrow)] - ): - d[key] = cell_value - data.append(d) - # remove the first element, it contains no values - data.pop(0) - if len(data): - validated_rows = [] - invalid_rows = [] - for row in data: - if row.get("email", None): - if re.match(email_regex, row.get("email", None)) is None: - invalid_rows.append(row) - else: - validated_rows.append(row) - return validated_rows, invalid_rows - - -def xls_doc_validate(document): - wb = xlrd.open_workbook(file_contents=document.open().read()) - sheets = wb.sheet_names() - validated_rows = [] - invalid_rows = [] - for sheet_name in sheets: - valid_data, invalid_data = get_validated_rows_xls( - wb, sheet_name, validated_rows, invalid_rows - ) - # if the data is valid data we'll get a list or else a dict - if type(valid_data) == dict: - return valid_data - validated_rows = validated_rows + valid_data - invalid_rows = invalid_rows + invalid_data - return { - "error": False, - "validated_rows": validated_rows, - "invalid_rows": invalid_rows, - } - - -def import_document_validator(document): - try: - # dialect = csv.Sniffer().sniff(document.read(1024).decode("ascii")) - document.seek(0, 0) # csv file - return csv_doc_validate(document) - except Exception as e: - print(e) - print("csv") - try: - return xlsx_doc_validate(document) # xlsx file - except Exception as e: - print(e) - print("xlsx") - try: - return xls_doc_validate(document) # xls file - except Exception as e: - print(e) - print("xls") - return {"error": True, "message": "Not a valid CSV/XLS, XLSX file"} - - -class ContactListForm(forms.ModelForm): - tags = forms.CharField(max_length=5000, required=False) - contacts_file = forms.FileField(required=False) - - class Meta: - model = ContactList - fields = ["name"] - - def __init__(self, *args, **kwargs): - super(ContactListForm, self).__init__(*args, **kwargs) - self.fields["contacts_file"].widget.attrs.update( - { - "accept": ".csv,.xls,.xlsx,.xlsm,.xlsb,.xml", - } - ) - if self.instance.id is None: - self.fields["contacts_file"].required = True - else: - self.fields["contacts_file"].required = False - if self.data.get("contacts_file"): - self.fields["contacts_file"].widget.attrs.update( - { - "accept": ".csv,.xls,.xlsx,.xlsm,.xlsb,.xml", - } - ) - - def clean_name(self): - name = self.cleaned_data.get("name") - if ( - ContactList.objects.filter(name__iexact=name) - .exclude(id=self.instance.id) - .exists() - ): - raise forms.ValidationError("Contact List with this Name already exists.") - return name - - def clean_contacts_file(self): - document = self.cleaned_data.get("contacts_file") - if document: - data = import_document_validator(document) - if data.get("error"): - raise forms.ValidationError(data.get("message")) - else: - self.validated_rows = data.get("validated_rows", []) - self.invalid_rows = data.get("invalid_rows", []) - if len(self.validated_rows) == 0: - raise forms.ValidationError( - "All the contacts in the file are invalid." - ) - # self.headers = data.get("headers", []) - # self.failed_contacts_csv = data.get("failed_contacts_csv", []) - # failed_csv_data = [] - # failed_csv_data = (self.failed_contacts_csv) - # failed_csv_data.insert(0, self.headers) - # if self.invalid_rows: - # self.add_error(None, json.dumps(failed_csv_data)) - # raise forms.ValidationError('Uploaded file is not valid.') - return document - - # def clean_visible_to(self): - # visible_to_data = json.loads(self.data['visible_to']) - # if len(visible_to_data) > 0: - # instance_visible_to = [] - # if self.instance and self.instance.id is not None: - # instance_visible_to = list( - # set(self.instance.visible_to.all().values_list( - # 'email', flat=True))) - # for each in visible_to_data: - # visible_to = User.objects.filter(email=each) - # if instance_visible_to: - # visible_to = visible_to.exclude( - # email__in=instance_visible_to) - # if visible_to: - # raise forms.ValidationError( - # str(each) + ' User aleady existed') - # return self.data['visible_to'] - # raise forms.ValidationError("Select any of the users") - - -class ContactForm(forms.ModelForm): - contact_list = forms.CharField(max_length=5000) - - def __init__(self, *args, **kwargs): - # request_user = kwargs.pop("request_user", None) - self.obj_instance = kwargs.get("instance", None) - super(ContactForm, self).__init__(*args, **kwargs) - for field in self.fields.values(): - field.widget.attrs = {"class": "form-control"} - - self.fields["name"].required = True - self.fields["email"].required = True - self.fields["last_name"].required = False - self.fields["city"].required = False - self.fields["state"].required = False - self.fields["company_name"].required = False - self.fields["contact_list"].required = False - - class Meta: - model = Contact - fields = [ - "name", - "email", - "contact_number", - "last_name", - "city", - "state", - "company_name", - ] - - def clean_email(self): - email = self.cleaned_data.get("email") - if Contact.objects.filter(email=email).exclude(id=self.instance.id).exists(): - raise forms.ValidationError("Contact with this Email already exists") - return email - - # def clean_contact_list(self): - # contact_list = self.cleaned_data.get("contact_list") - # if not contact_list or contact_list == '[]' or\ - # json.loads(contact_list) == []: - # raise forms.ValidationError( - # "Please choose any of the Contact List") - # else: - # for each in json.loads(contact_list): - # if not ContactList.objects.filter(id=each).first(): - # raise forms.ValidationError( - # "Please choose a valid Contact List") - - # return contact_list - - -# class ContactsCSVUploadForm(forms.Form): -# contacts_file = forms.FileField() -# contact_list = forms.CharField(max_length=5000) - -# def __init__(self, *args, **kwargs): -# super(ContactsCSVUploadForm, self).__init__(*args, **kwargs) -# self.fields['contacts_file'].widget.attrs.update({ -# "accept": ".csv,.xls,.xlsx,.xlsm,.xlsb,.xml", -# }) -# self.fields['contacts_file'].required = True - -# def clean_contacts_file(self): -# document = self.cleaned_data.get("contacts_file") -# data = import_document_validator(document) -# if data.get("error"): -# raise forms.ValidationError(data.get("message")) -# else: -# self.validated_rows = data.get("validated_rows") -# return document - -# def clean_contact_list(self): -# contact_list = self.cleaned_data.get("contact_list") -# if not contact_list or contact_list == '[]' or\ -# json.loads(contact_list) == []: -# raise forms.ValidationError( -# "Please choose any of the Contact List") -# else: -# for each in json.loads(contact_list): -# if not ContactList.objects.filter(id=each).first(): -# raise forms.ValidationError( -# "Please choose a valid Contact List") - -# return contact_list - - -class EmailTemplateForm(forms.ModelForm): - class Meta: - model = EmailTemplate - fields = ["title", "subject", "html"] - - -class SendCampaignForm(forms.ModelForm): - schedule_later = forms.BooleanField(required=False) - reply_to_crm = forms.BooleanField(required=False) - timezone = forms.CharField(max_length=500, required=False) - schedule_date_time = forms.CharField(max_length=100, required=False) - reply_to_email = forms.EmailField(max_length=100, required=False) - from_email = forms.EmailField(max_length=100, required=True) - from_name = forms.CharField(max_length=100, required=True) - contact_list = forms.CharField(max_length=5000, required=True) - tags = forms.CharField(max_length=5000, required=False) - - class Meta: - model = Campaign - fields = [ - "title", - "subject", - "html", - "email_template", - "attachment", - ] - - def __init__(self, *args, **kwargs): - self.contacts_list = kwargs.pop("contacts_list") - super(SendCampaignForm, self).__init__(*args, **kwargs) - if self.data.get("schedule_later") and self.data["schedule_later"] == "true": - self.fields["timezone"].required = True - self.fields["schedule_date_time"].required = True - if not self.data.get("reply_to_crm"): - self.fields["reply_to_email"].required = True - - def clean_schedule_date_time(self): - schedule_date_time = self.cleaned_data.get("schedule_date_time") - if self.cleaned_data.get("schedule_later") == True: - schedule_date_time = datetime.datetime.strptime( - schedule_date_time, "%Y-%m-%d %H:%M" - ) - if schedule_date_time < datetime.datetime.now(): - raise forms.ValidationError( - "Schedule Date Time should be greater than current time" - ) - return schedule_date_time - - def clean_contact_list(self): - contact_list = self.contacts_list - if not contact_list or contact_list == "[]" or contact_list == []: - raise forms.ValidationError("Please choose any of the Contact List") - else: - for each in contact_list: - contacts_list_obj = ContactList.objects.filter(id=each).first() - if not contacts_list_obj: - raise forms.ValidationError("Please choose a valid Contact List") - - if contacts_list_obj.contacts.count() < 1: - raise forms.ValidationError( - 'The contact list "{}" does not have any contacts in it .'.format( - contacts_list_obj.name - ) - ) - - return contact_list - - def clean_html(self): - html = self.cleaned_data.get("html") - count = 0 - for i in html: - if i == "{": - count += 1 - elif i == "}": - count -= 1 - if count < 0: - raise forms.ValidationError("Brackets do not match, Enter valid tags.") - if count != 0: - raise forms.ValidationError("Brackets do not match, Enter valid tags.") - return html - - def clean_title(self): - title = self.cleaned_data.get("title") - if ( - Campaign.objects.filter(title__iexact=title) - .exclude(id=self.instance.id) - .exists() - ): - raise forms.ValidationError("Campaign with this title already exists.") - return title - - -class EmailCampaignForm(forms.ModelForm): - def __init__(self, *args, **kwargs): - self.obj_instance = kwargs.get("instance", None) - super(EmailCampaignForm, self).__init__(*args, **kwargs) - for field in self.fields.values(): - field.widget.attrs = {"class": "form-control"} - - self.fields["name"].required = True - self.fields["email"].required = True - self.fields["last_name"].required = False - - class Meta: - model = ContactEmailCampaign - fields = [ - "name", - "email", - "last_name", - ] - - def clean_email(self): - email = self.cleaned_data.get("email") - if ( - ContactEmailCampaign.objects.filter(email=email) - .exclude(id=self.instance.id) - .exists() - ): - raise forms.ValidationError("Contact with this Email already exists.") - return email - - -class BlockedDomainsForm(forms.ModelForm): - class Meta: - model = BlockedDomain - fields = [ - "domain", - ] - - def clean_domain(self): - domain = self.cleaned_data.get("domain") - domain_regex = "^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$" - if re.match(domain_regex, domain) is None: - raise forms.ValidationError("Enter a valid domain.") - if ( - BlockedDomain.objects.filter(domain__iexact=domain) - .exclude(id=self.instance.id) - .exists() - ): - raise forms.ValidationError("Domain with this name already exists.") - return domain - - -class BlockedEmailForm(forms.ModelForm): - class Meta: - model = BlockedEmail - fields = [ - "email", - ] - - def clean_email(self): - email = self.cleaned_data.get("email") - if ( - BlockedEmail.objects.filter(email__iexact=email) - .exclude(id=self.instance.id) - .exists() - ): - raise forms.ValidationError("Email already exists.") - return email - - -# class MarketingContactEmailSearchForm(SearchForm): -# email_domain = forms.CharField() - -# def search(self): -# # First, store the SearchQuerySet received from other processing. -# sqs = super(MarketingContactEmailSearchForm, self).search() - -# if not self.is_valid(): -# return self.no_query_found() - -# # Check to see if a start_date was chosen. -# if self.cleaned_data['email_domain']: -# sqs = sqs.filter(email__icontains=self.cleaned_data.get('email_domain')) - -# return sqs - -# def clean_email_domain(self): -# email_domain = self.cleaned_data.get('email_domain') -# domain_regex = '^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$' -# if re.match(domain_regex, email_domain) is None: -# raise forms.ValidationError('Enter a valid domain.') -# return email_domain diff --git a/marketing/migrations/0001_initial.py b/marketing/migrations/0001_initial.py deleted file mode 100644 index c258b87..0000000 --- a/marketing/migrations/0001_initial.py +++ /dev/null @@ -1,390 +0,0 @@ -# Generated by Django 2.1.7 on 2019-02-25 13:21 - -from django.conf import settings -import django.core.validators -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ] - - operations = [ - migrations.CreateModel( - name="Campaign", - fields=[ - ( - "id", - models.AutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ("title", models.CharField(max_length=5000)), - ("created_on", models.DateTimeField(auto_now_add=True)), - ("schedule_date_time", models.DateTimeField(blank=True, null=True)), - ( - "reply_to_email", - models.EmailField(blank=True, max_length=254, null=True), - ), - ("subject", models.CharField(max_length=5000)), - ("html", models.TextField()), - ("html_processed", models.TextField(blank=True, default="")), - ( - "from_email", - models.EmailField(blank=True, max_length=254, null=True), - ), - ("from_name", models.EmailField(blank=True, max_length=254, null=True)), - ("sent", models.IntegerField(blank=True, default="0")), - ("opens", models.IntegerField(blank=True, default="0")), - ("opens_unique", models.IntegerField(blank=True, default="0")), - ("bounced", models.IntegerField(default="0")), - ( - "status", - models.CharField( - choices=[ - ("Scheduled", "Scheduled"), - ("Cancelled", "Cancelled"), - ("Sending", "Sending"), - ("Preparing", "Preparing"), - ("Sent", "Sent"), - ], - default="Preparing", - max_length=20, - ), - ), - ], - ), - migrations.CreateModel( - name="CampaignLinkClick", - fields=[ - ( - "id", - models.AutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ("ip_address", models.GenericIPAddressField()), - ("created_on", models.DateTimeField(auto_now_add=True)), - ( - "user_agent", - models.CharField(blank=True, max_length=2000, null=True), - ), - ( - "campaign", - models.ForeignKey( - on_delete=django.db.models.deletion.CASCADE, - to="marketing.Campaign", - ), - ), - ], - ), - migrations.CreateModel( - name="CampaignLog", - fields=[ - ( - "id", - models.AutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ("created_on", models.DateTimeField(auto_now_add=True)), - ( - "message_id", - models.CharField(blank=True, max_length=1000, null=True), - ), - ( - "campaign", - models.ForeignKey( - on_delete=django.db.models.deletion.CASCADE, - related_name="campaign_contacts", - to="marketing.Campaign", - ), - ), - ], - ), - migrations.CreateModel( - name="CampaignOpen", - fields=[ - ( - "id", - models.AutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ("ip_address", models.GenericIPAddressField()), - ("created_on", models.DateTimeField(auto_now_add=True)), - ( - "user_agent", - models.CharField(blank=True, max_length=2000, null=True), - ), - ( - "campaign", - models.ForeignKey( - on_delete=django.db.models.deletion.CASCADE, - to="marketing.Campaign", - ), - ), - ], - ), - migrations.CreateModel( - name="Contact", - fields=[ - ( - "id", - models.AutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ("created_on", models.DateTimeField(auto_now_add=True)), - ("name", models.CharField(max_length=500)), - ("email", models.EmailField(max_length=254)), - ( - "contact_number", - models.CharField( - blank=True, - max_length=20, - null=True, - validators=[ - django.core.validators.RegexValidator( - message="Phone number must be entered in the format: '+999999999'. Up to 20 digits allowed.", - regex="^\\+?1?\\d{9,15}$", - ) - ], - ), - ), - ("is_unsubscribed", models.BooleanField(default=False)), - ("is_bounced", models.BooleanField(default=False)), - ( - "company_name", - models.CharField(blank=True, max_length=500, null=True), - ), - ("last_name", models.CharField(blank=True, max_length=500, null=True)), - ("city", models.CharField(blank=True, max_length=500, null=True)), - ("state", models.CharField(blank=True, max_length=500, null=True)), - ("contry", models.CharField(blank=True, max_length=500, null=True)), - ], - ), - migrations.CreateModel( - name="ContactList", - fields=[ - ( - "id", - models.AutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ("created_on", models.DateTimeField(auto_now_add=True)), - ("name", models.CharField(max_length=500)), - ( - "created_by", - models.ForeignKey( - null=True, - on_delete=django.db.models.deletion.SET_NULL, - related_name="marketing_contactlist", - to=settings.AUTH_USER_MODEL, - ), - ), - ], - ), - migrations.CreateModel( - name="EmailTemplate", - fields=[ - ( - "id", - models.AutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ("created_on", models.DateTimeField(auto_now_add=True)), - ("title", models.CharField(max_length=5000)), - ("subject", models.CharField(max_length=5000)), - ("html", models.TextField()), - ( - "created_by", - models.ForeignKey( - null=True, - on_delete=django.db.models.deletion.SET_NULL, - related_name="marketing_emailtemplates", - to=settings.AUTH_USER_MODEL, - ), - ), - ], - ), - migrations.CreateModel( - name="Link", - fields=[ - ( - "id", - models.AutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ("original", models.URLField(max_length=2100)), - ("clicks", models.IntegerField(default="0")), - ("unique", models.IntegerField(default="0")), - ( - "campaign", - models.ForeignKey( - on_delete=django.db.models.deletion.CASCADE, - related_name="marketing_links", - to="marketing.Campaign", - ), - ), - ], - ), - migrations.CreateModel( - name="Tag", - fields=[ - ( - "id", - models.AutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ("name", models.CharField(max_length=500)), - ( - "color", - models.CharField( - default="#999999", max_length=20, verbose_name="color" - ), - ), - ( - "created_by", - models.ForeignKey( - null=True, - on_delete=django.db.models.deletion.SET_NULL, - related_name="marketing_tags", - to=settings.AUTH_USER_MODEL, - ), - ), - ], - ), - migrations.AddField( - model_name="contactlist", - name="tags", - field=models.ManyToManyField(to="marketing.Tag"), - ), - migrations.AddField( - model_name="contactlist", - name="visible_to", - field=models.ManyToManyField( - related_name="contact_lists_visible_to", to=settings.AUTH_USER_MODEL - ), - ), - migrations.AddField( - model_name="contact", - name="contact_list", - field=models.ManyToManyField( - related_name="contacts", to="marketing.ContactList" - ), - ), - migrations.AddField( - model_name="contact", - name="created_by", - field=models.ForeignKey( - null=True, - on_delete=django.db.models.deletion.SET_NULL, - related_name="marketing_contacts_created_by", - to=settings.AUTH_USER_MODEL, - ), - ), - migrations.AddField( - model_name="campaignopen", - name="contact", - field=models.ForeignKey( - blank=True, - null=True, - on_delete=django.db.models.deletion.CASCADE, - to="marketing.Contact", - ), - ), - migrations.AddField( - model_name="campaignlog", - name="contact", - field=models.ForeignKey( - null=True, - on_delete=django.db.models.deletion.SET_NULL, - related_name="marketing_campaign_logs", - to="marketing.Contact", - ), - ), - migrations.AddField( - model_name="campaignlinkclick", - name="contact", - field=models.ForeignKey( - blank=True, - null=True, - on_delete=django.db.models.deletion.CASCADE, - to="marketing.Contact", - ), - ), - migrations.AddField( - model_name="campaignlinkclick", - name="link", - field=models.ForeignKey( - blank=True, - null=True, - on_delete=django.db.models.deletion.CASCADE, - to="marketing.Link", - ), - ), - migrations.AddField( - model_name="campaign", - name="contact_lists", - field=models.ManyToManyField( - related_name="campaigns", to="marketing.ContactList" - ), - ), - migrations.AddField( - model_name="campaign", - name="created_by", - field=models.ForeignKey( - null=True, - on_delete=django.db.models.deletion.SET_NULL, - related_name="marketing_campaigns_created_by", - to=settings.AUTH_USER_MODEL, - ), - ), - migrations.AddField( - model_name="campaign", - name="email_template", - field=models.ForeignKey( - blank=True, - null=True, - on_delete=django.db.models.deletion.SET_NULL, - to="marketing.EmailTemplate", - ), - ), - ] diff --git a/marketing/migrations/0002_auto_20190307_1227.py b/marketing/migrations/0002_auto_20190307_1227.py deleted file mode 100644 index 980b8ef..0000000 --- a/marketing/migrations/0002_auto_20190307_1227.py +++ /dev/null @@ -1,42 +0,0 @@ -# Generated by Django 2.1.7 on 2019-03-07 06:57 - -from django.db import migrations, models -import django.utils.timezone - - -class Migration(migrations.Migration): - - dependencies = [ - ("marketing", "0001_initial"), - ] - - operations = [ - migrations.AddField( - model_name="campaign", - name="updated_on", - field=models.DateTimeField(auto_now=True), - ), - migrations.AddField( - model_name="contact", - name="updated_on", - field=models.DateTimeField(auto_now=True), - ), - migrations.AddField( - model_name="contactlist", - name="updated_on", - field=models.DateTimeField(auto_now=True), - ), - migrations.AddField( - model_name="emailtemplate", - name="updated_on", - field=models.DateTimeField(auto_now=True), - ), - migrations.AddField( - model_name="tag", - name="created_on", - field=models.DateTimeField( - auto_now_add=True, default=django.utils.timezone.now - ), - preserve_default=False, - ), - ] diff --git a/marketing/migrations/0003_failedcontact.py b/marketing/migrations/0003_failedcontact.py deleted file mode 100644 index f541556..0000000 --- a/marketing/migrations/0003_failedcontact.py +++ /dev/null @@ -1,71 +0,0 @@ -# Generated by Django 2.1.7 on 2019-03-07 12:20 - -from django.conf import settings -import django.core.validators -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ("marketing", "0002_auto_20190307_1227"), - ] - - operations = [ - migrations.CreateModel( - name="FailedContact", - fields=[ - ( - "id", - models.AutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ("created_on", models.DateTimeField(auto_now_add=True)), - ("name", models.CharField(blank=True, max_length=500, null=True)), - ("email", models.EmailField(blank=True, max_length=254, null=True)), - ( - "contact_number", - models.CharField( - blank=True, - max_length=20, - null=True, - validators=[ - django.core.validators.RegexValidator( - message="Phone number must be entered in the format: '+999999999'. Up to 20 digits allowed.", - regex="^\\+?1?\\d{9,15}$", - ) - ], - ), - ), - ( - "company_name", - models.CharField(blank=True, max_length=500, null=True), - ), - ("last_name", models.CharField(blank=True, max_length=500, null=True)), - ("city", models.CharField(blank=True, max_length=500, null=True)), - ("state", models.CharField(blank=True, max_length=500, null=True)), - ("contry", models.CharField(blank=True, max_length=500, null=True)), - ( - "contact_list", - models.ManyToManyField( - related_name="failed_contacts", to="marketing.ContactList" - ), - ), - ( - "created_by", - models.ForeignKey( - null=True, - on_delete=django.db.models.deletion.SET_NULL, - related_name="marketing_failed_contacts_created_by", - to=settings.AUTH_USER_MODEL, - ), - ), - ], - ), - ] diff --git a/marketing/migrations/0004_auto_20190315_1443.py b/marketing/migrations/0004_auto_20190315_1443.py deleted file mode 100644 index bedc779..0000000 --- a/marketing/migrations/0004_auto_20190315_1443.py +++ /dev/null @@ -1,44 +0,0 @@ -# Generated by Django 2.1.7 on 2019-03-15 09:13 - -import django.core.validators -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ("marketing", "0003_failedcontact"), - ] - - operations = [ - migrations.AlterField( - model_name="contact", - name="contact_number", - field=models.CharField( - blank=True, - max_length=20, - null=True, - validators=[ - django.core.validators.RegexValidator( - message="Phone number must be entered in the format: '+999999999'. Up to 20 digits allowed.", - regex="^\\+?1?\\d{9,15}$", - ) - ], - ), - ), - migrations.AlterField( - model_name="failedcontact", - name="contact_number", - field=models.CharField( - blank=True, - max_length=20, - null=True, - validators=[ - django.core.validators.RegexValidator( - message="Phone number must be entered in the format: '+999999999'. Up to 20 digits allowed.", - regex="^\\+?1?\\d{9,15}$", - ) - ], - ), - ), - ] diff --git a/marketing/migrations/0005_campaign_timezone.py b/marketing/migrations/0005_campaign_timezone.py deleted file mode 100644 index 0b1625b..0000000 --- a/marketing/migrations/0005_campaign_timezone.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.1.7 on 2019-03-18 07:00 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ("marketing", "0004_auto_20190315_1443"), - ] - - operations = [ - migrations.AddField( - model_name="campaign", - name="timezone", - field=models.CharField(default="UTC", max_length=100), - ), - ] diff --git a/marketing/migrations/0006_campaign_attachment.py b/marketing/migrations/0006_campaign_attachment.py deleted file mode 100644 index 9273c77..0000000 --- a/marketing/migrations/0006_campaign_attachment.py +++ /dev/null @@ -1,24 +0,0 @@ -# Generated by Django 2.1.7 on 2019-03-19 10:29 - -from django.db import migrations, models -import marketing.models - - -class Migration(migrations.Migration): - - dependencies = [ - ("marketing", "0005_campaign_timezone"), - ] - - operations = [ - migrations.AddField( - model_name="campaign", - name="attachment", - field=models.FileField( - blank=True, - max_length=1000, - null=True, - upload_to=marketing.models.get_campaign_attachment_path, - ), - ), - ] diff --git a/marketing/migrations/0007_auto_20190611_1226.py b/marketing/migrations/0007_auto_20190611_1226.py deleted file mode 100644 index 7b8a427..0000000 --- a/marketing/migrations/0007_auto_20190611_1226.py +++ /dev/null @@ -1,48 +0,0 @@ -# Generated by Django 2.1.7 on 2019-06-11 06:56 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ("marketing", "0006_campaign_attachment"), - ] - - operations = [ - migrations.CreateModel( - name="CampaignCompleted", - fields=[ - ( - "id", - models.AutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ("is_completed", models.BooleanField(default=False)), - ( - "campaign", - models.OneToOneField( - on_delete=django.db.models.deletion.CASCADE, - related_name="campaign_is_completed", - to="marketing.Campaign", - ), - ), - ], - ), - migrations.AlterField( - model_name="campaignopen", - name="contact", - field=models.ForeignKey( - blank=True, - null=True, - on_delete=django.db.models.deletion.CASCADE, - related_name="contact_campaign", - to="marketing.Contact", - ), - ), - ] diff --git a/marketing/migrations/0008_auto_20190612_1905.py b/marketing/migrations/0008_auto_20190612_1905.py deleted file mode 100644 index 1ab2ed7..0000000 --- a/marketing/migrations/0008_auto_20190612_1905.py +++ /dev/null @@ -1,55 +0,0 @@ -# Generated by Django 2.1.7 on 2019-06-12 13:35 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ("marketing", "0007_auto_20190611_1226"), - ] - - operations = [ - migrations.AlterModelOptions( - name="campaign", - options={"ordering": ("created_on",)}, - ), - migrations.AlterModelOptions( - name="contact", - options={"ordering": ["id"]}, - ), - migrations.AlterModelOptions( - name="contactlist", - options={"ordering": ("id",)}, - ), - migrations.AlterModelOptions( - name="emailtemplate", - options={"ordering": ["id"]}, - ), - migrations.AddField( - model_name="campaign", - name="tags", - field=models.ManyToManyField(to="marketing.Tag"), - ), - migrations.AlterField( - model_name="campaignopen", - name="campaign", - field=models.ForeignKey( - on_delete=django.db.models.deletion.CASCADE, - related_name="campaign_open", - to="marketing.Campaign", - ), - ), - migrations.AlterField( - model_name="campaignopen", - name="contact", - field=models.ForeignKey( - blank=True, - null=True, - on_delete=django.db.models.deletion.CASCADE, - related_name="contact_campaign_open", - to="marketing.Contact", - ), - ), - ] diff --git a/marketing/migrations/0009_auto_20190618_1144.py b/marketing/migrations/0009_auto_20190618_1144.py deleted file mode 100644 index d8cd39e..0000000 --- a/marketing/migrations/0009_auto_20190618_1144.py +++ /dev/null @@ -1,52 +0,0 @@ -# Generated by Django 2.1.7 on 2019-06-18 06:14 - -from django.db import migrations, models -import django.db.models.deletion -import django.db.models.expressions - - -class Migration(migrations.Migration): - - dependencies = [ - ("marketing", "0008_auto_20190612_1905"), - ] - - operations = [ - migrations.CreateModel( - name="ContactUnsubscribedCampaign", - fields=[ - ( - "id", - models.AutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ("is_unsubscribed", models.BooleanField(default=False)), - ], - ), - migrations.AlterModelOptions( - name="campaign", - options={"ordering": ("-created_on",)}, - ), - migrations.AddField( - model_name="contactunsubscribedcampaign", - name="campaigns", - field=models.ForeignKey( - on_delete=django.db.models.deletion.CASCADE, - related_name="campaign_is_unsubscribed", - to="marketing.Campaign", - ), - ), - migrations.AddField( - model_name="contactunsubscribedcampaign", - name="contacts", - field=models.ForeignKey( - on_delete=django.db.models.expressions.Case, - related_name="contact_is_unsubscribed", - to="marketing.Contact", - ), - ), - ] diff --git a/marketing/migrations/0010_auto_20190805_1038.py b/marketing/migrations/0010_auto_20190805_1038.py deleted file mode 100644 index e91cf13..0000000 --- a/marketing/migrations/0010_auto_20190805_1038.py +++ /dev/null @@ -1,69 +0,0 @@ -# Generated by Django 2.2.3 on 2019-08-05 05:08 - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ("marketing", "0009_auto_20190618_1144"), - ] - - operations = [ - migrations.AlterModelOptions( - name="contactlist", - options={"ordering": ("-created_on",)}, - ), - migrations.AlterModelOptions( - name="link", - options={"ordering": ("id",)}, - ), - migrations.AlterField( - model_name="campaignlinkclick", - name="campaign", - field=models.ForeignKey( - on_delete=django.db.models.deletion.CASCADE, - related_name="campaign_link_click", - to="marketing.Campaign", - ), - ), - migrations.AlterField( - model_name="campaignlog", - name="campaign", - field=models.ForeignKey( - on_delete=django.db.models.deletion.CASCADE, - related_name="campaign_log_contacts", - to="marketing.Campaign", - ), - ), - migrations.CreateModel( - name="ContactEmailCampaign", - fields=[ - ( - "id", - models.AutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ("name", models.CharField(max_length=500)), - ("email", models.EmailField(max_length=254)), - ("last_name", models.CharField(blank=True, max_length=500, null=True)), - ("created_on", models.DateTimeField(auto_now_add=True)), - ( - "created_by", - models.ForeignKey( - null=True, - on_delete=django.db.models.deletion.SET_NULL, - related_name="marketing_contacts_emails_campaign_created_by", - to=settings.AUTH_USER_MODEL, - ), - ), - ], - ), - ] diff --git a/marketing/migrations/0011_auto_20190904_1143.py b/marketing/migrations/0011_auto_20190904_1143.py deleted file mode 100644 index c70a87d..0000000 --- a/marketing/migrations/0011_auto_20190904_1143.py +++ /dev/null @@ -1,50 +0,0 @@ -# Generated by Django 2.2.4 on 2019-09-04 06:13 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ("marketing", "0010_auto_20190805_1038"), - ] - - operations = [ - migrations.AlterModelOptions( - name="contactemailcampaign", - options={"ordering": ("created_on",)}, - ), - migrations.CreateModel( - name="DuplicateContacts", - fields=[ - ( - "id", - models.AutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ( - "contact_list", - models.ForeignKey( - null=True, - on_delete=django.db.models.deletion.SET_NULL, - related_name="duplicate_contact_contact_list", - to="marketing.ContactList", - ), - ), - ( - "contacts", - models.ForeignKey( - null=True, - on_delete=django.db.models.deletion.SET_NULL, - related_name="duplicate_contact", - to="marketing.Contact", - ), - ), - ], - ), - ] diff --git a/marketing/migrations/0012_auto_20190909_1621.py b/marketing/migrations/0012_auto_20190909_1621.py deleted file mode 100644 index 447f3d3..0000000 --- a/marketing/migrations/0012_auto_20190909_1621.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 2.2.4 on 2019-09-09 10:51 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ("marketing", "0011_auto_20190904_1143"), - ] - - operations = [ - migrations.AlterModelOptions( - name="duplicatecontacts", - options={"ordering": ("id",)}, - ), - ] diff --git a/marketing/migrations/0013_blockeddomain_blockedemail.py b/marketing/migrations/0013_blockeddomain_blockedemail.py deleted file mode 100644 index abdc740..0000000 --- a/marketing/migrations/0013_blockeddomain_blockedemail.py +++ /dev/null @@ -1,72 +0,0 @@ -# Generated by Django 2.2.4 on 2019-09-12 10:22 - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ("marketing", "0012_auto_20190909_1621"), - ] - - operations = [ - migrations.CreateModel( - name="BlockedEmail", - fields=[ - ( - "id", - models.AutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ("email", models.EmailField(max_length=254)), - ("created_on", models.DateTimeField(auto_now_add=True)), - ( - "created_by", - models.ForeignKey( - blank=True, - null=True, - on_delete=django.db.models.deletion.SET_NULL, - to=settings.AUTH_USER_MODEL, - ), - ), - ], - options={ - "ordering": ("created_on",), - }, - ), - migrations.CreateModel( - name="BlockedDomain", - fields=[ - ( - "id", - models.AutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ("domain", models.CharField(max_length=200)), - ("created_on", models.DateTimeField(auto_now_add=True)), - ( - "created_by", - models.ForeignKey( - blank=True, - null=True, - on_delete=django.db.models.deletion.SET_NULL, - to=settings.AUTH_USER_MODEL, - ), - ), - ], - options={ - "ordering": ("created_on",), - }, - ), - ] diff --git a/marketing/migrations/0015_auto_20200912_0301.py b/marketing/migrations/0015_auto_20200912_0301.py deleted file mode 100644 index f28ed23..0000000 --- a/marketing/migrations/0015_auto_20200912_0301.py +++ /dev/null @@ -1,92 +0,0 @@ -# Generated by Django 3.1 on 2020-09-11 21:31 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ("common", "0022_auto_20200609_1203"), - ("marketing", "0014_emailtemplate_company"), - ] - - operations = [ - migrations.AddField( - model_name="blockeddomain", - name="company", - field=models.ForeignKey( - null=True, - on_delete=django.db.models.deletion.CASCADE, - to="common.company", - ), - ), - migrations.AddField( - model_name="blockedemail", - name="company", - field=models.ForeignKey( - null=True, - on_delete=django.db.models.deletion.CASCADE, - to="common.company", - ), - ), - migrations.AddField( - model_name="campaign", - name="company", - field=models.ForeignKey( - null=True, - on_delete=django.db.models.deletion.CASCADE, - related_name="marketing_campaigns_company", - to="common.company", - ), - ), - migrations.AddField( - model_name="contact", - name="company", - field=models.ForeignKey( - null=True, - on_delete=django.db.models.deletion.CASCADE, - related_name="marketing_contacts_company", - to="common.company", - ), - ), - migrations.AddField( - model_name="contactemailcampaign", - name="company", - field=models.ForeignKey( - null=True, - on_delete=django.db.models.deletion.CASCADE, - related_name="marketing_contacts_emails_campaign_company", - to="common.company", - ), - ), - migrations.AddField( - model_name="contactlist", - name="company", - field=models.ForeignKey( - null=True, - on_delete=django.db.models.deletion.CASCADE, - related_name="marketing_contactlist_company", - to="common.company", - ), - ), - migrations.AddField( - model_name="failedcontact", - name="company", - field=models.ForeignKey( - null=True, - on_delete=django.db.models.deletion.CASCADE, - related_name="marketing_failed_contacts_company", - to="common.company", - ), - ), - migrations.AddField( - model_name="tag", - name="company", - field=models.ForeignKey( - null=True, - on_delete=django.db.models.deletion.CASCADE, - to="common.company", - ), - ), - ] diff --git a/marketing/migrations/0016_auto_20201112_1614.py b/marketing/migrations/0016_auto_20201112_1614.py deleted file mode 100644 index 753fa15..0000000 --- a/marketing/migrations/0016_auto_20201112_1614.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 3.0 on 2020-11-12 10:44 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ("marketing", "0015_auto_20200912_0301"), - ] - - operations = [ - migrations.RenameField( - model_name="contact", - old_name="contry", - new_name="country", - ), - migrations.RenameField( - model_name="failedcontact", - old_name="contry", - new_name="country", - ), - ] diff --git a/marketing/migrations/__init__.py b/marketing/migrations/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/marketing/models.py b/marketing/models.py deleted file mode 100644 index d33e81d..0000000 --- a/marketing/models.py +++ /dev/null @@ -1,566 +0,0 @@ -import arrow -import os -from datetime import datetime, timedelta -from django.db import models -from django.utils.timesince import timesince -from django.utils.translation import ugettext_lazy as _ -from django.core.validators import RegexValidator -from django.dispatch import receiver -from django.db.models import Sum -from django.template.defaultfilters import slugify -from common.models import User, Company -from common.utils import convert_to_custom_timezone - - -class Tag(models.Model): - name = models.CharField(max_length=500) - color = models.CharField(max_length=20, default="#999999", verbose_name=_("color")) - created_by = models.ForeignKey( - User, related_name="marketing_tags", null=True, on_delete=models.SET_NULL - ) - created_on = models.DateTimeField(auto_now_add=True) - company = models.ForeignKey( - Company, - on_delete=models.CASCADE, - null=True, - ) - - @property - def created_by_user(self): - return self.created_by if self.created_by else None - - -class EmailTemplate(models.Model): - created_by = models.ForeignKey( - User, - related_name="marketing_emailtemplates", - null=True, - on_delete=models.SET_NULL, - ) - created_on = models.DateTimeField(auto_now_add=True) - updated_on = models.DateTimeField(auto_now=True) - title = models.CharField(max_length=5000) - subject = models.CharField(max_length=5000) - html = models.TextField() - company = models.ForeignKey( - Company, - related_name="marketing_emailtemplates_company", - on_delete=models.CASCADE, - null=True, - ) - - class Meta: - ordering = [ - "id", - ] - - @property - def created_by_user(self): - return self.created_by if self.created_by else None - - @property - def created_on_arrow(self): - return arrow.get(self.created_on).humanize() - - -class ContactList(models.Model): - created_by = models.ForeignKey( - User, related_name="marketing_contactlist", null=True, on_delete=models.SET_NULL - ) - created_on = models.DateTimeField(auto_now_add=True) - updated_on = models.DateTimeField(auto_now=True) - name = models.CharField(max_length=500) - tags = models.ManyToManyField(Tag) - # is_public = models.BooleanField(default=False) - visible_to = models.ManyToManyField(User, related_name="contact_lists_visible_to") - company = models.ForeignKey( - Company, - related_name="marketing_contactlist_company", - on_delete=models.CASCADE, - null=True, - ) - - class Meta: - ordering = ("-created_on",) - - @property - def created_by_user(self): - return self.created_by if self.created_by else None - - @property - def created_on_format(self): - return self.created_on.strftime("%b %d, %Y %I:%M %p") - - # @property - # def created_on_since(self): - # now = datetime.now() - # difference = now.replace(tzinfo=None) - \ - # self.created_on.replace(tzinfo=None) - - # if difference <= timedelta(minutes=1): - # return 'just now' - # return '%(time)s ago' % { - # 'time': timesince(self.created_on).split(', ')[0]} - - @property - def tags_data(self): - return self.tags.all() - - @property - def no_of_contacts(self): - return self.contacts.all().count() - - @property - def no_of_campaigns(self): - return self.campaigns.all().count() - - @property - def unsubscribe_contacts(self): - return self.contacts.filter(is_unsubscribed=True).count() - - @property - def bounced_contacts(self): - return self.contacts.filter(is_bounced=True).count() - - # @property - # def no_of_clicks(self): - # clicks = CampaignLog.objects.filter( - # contact__contact_list__in=[self]).aggregate(Sum( - # 'no_of_clicks'))['no_of_clicks__sum'] - # return clicks - - @property - def created_on_arrow(self): - return arrow.get(self.created_on).humanize() - - @property - def updated_on_arrow(self): - return arrow.get(self.updated_on).humanize() - - -class Contact(models.Model): - phone_regex = RegexValidator( - regex=r"^\+?1?\d{9,15}$", - message="Phone number must be entered in the format: '+999999999'. \ - Up to 20 digits allowed.", - ) - created_by = models.ForeignKey( - User, - related_name="marketing_contacts_created_by", - null=True, - on_delete=models.SET_NULL, - ) - created_on = models.DateTimeField(auto_now_add=True) - updated_on = models.DateTimeField(auto_now=True) - contact_list = models.ManyToManyField(ContactList, related_name="contacts") - name = models.CharField(max_length=500) - email = models.EmailField() - contact_number = models.CharField( - validators=[phone_regex], max_length=20, blank=True, null=True - ) - is_unsubscribed = models.BooleanField(default=False) - is_bounced = models.BooleanField(default=False) - company_name = models.CharField(max_length=500, null=True, blank=True) - last_name = models.CharField(max_length=500, null=True, blank=True) - city = models.CharField(max_length=500, null=True, blank=True) - state = models.CharField(max_length=500, null=True, blank=True) - country = models.CharField(max_length=500, null=True, blank=True) - company = models.ForeignKey( - Company, - related_name="marketing_contacts_company", - on_delete=models.CASCADE, - null=True, - ) - - def __str__(self): - return self.email - - @property - def created_on_arrow(self): - return arrow.get(self.created_on).humanize() - - class Meta: - ordering = [ - "id", - ] - - -class FailedContact(models.Model): - phone_regex = RegexValidator( - regex=r"^\+?1?\d{9,15}$", - message="Phone number must be entered in the format: '+999999999'.\ - Up to 20 digits allowed.", - ) - created_by = models.ForeignKey( - User, - related_name="marketing_failed_contacts_created_by", - null=True, - on_delete=models.SET_NULL, - ) - created_on = models.DateTimeField(auto_now_add=True) - contact_list = models.ManyToManyField(ContactList, related_name="failed_contacts") - name = models.CharField(max_length=500, null=True, blank=True) - email = models.EmailField(null=True, blank=True) - contact_number = models.CharField( - validators=[phone_regex], max_length=20, blank=True, null=True - ) - company_name = models.CharField(max_length=500, null=True, blank=True) - last_name = models.CharField(max_length=500, null=True, blank=True) - city = models.CharField(max_length=500, null=True, blank=True) - state = models.CharField(max_length=500, null=True, blank=True) - country = models.CharField(max_length=500, null=True, blank=True) - company = models.ForeignKey( - Company, - related_name="marketing_failed_contacts_company", - on_delete=models.CASCADE, - null=True, - ) - - def __str__(self): - return self.email - - @property - def created_on_arrow(self): - return arrow.get(self.created_on).humanize() - - -def get_campaign_attachment_path(self, filename): - file_split = filename.split(".") - file_extension = file_split[-1] - path = "%s_%s" % (file_split[0], str(datetime.now())) - return "campaigns/attachment/" + slugify(path) + "." + file_extension - - -class Campaign(models.Model): - STATUS_CHOICES = ( - ("Scheduled", "Scheduled"), - ("Cancelled", "Cancelled"), - ("Sending", "Sending"), - ("Preparing", "Preparing"), - ("Sent", "Sent"), - ) - - title = models.CharField(max_length=5000) - created_by = models.ForeignKey( - User, - related_name="marketing_campaigns_created_by", - null=True, - on_delete=models.SET_NULL, - ) - created_on = models.DateTimeField(auto_now_add=True) - updated_on = models.DateTimeField(auto_now=True) - contact_lists = models.ManyToManyField(ContactList, related_name="campaigns") - email_template = models.ForeignKey( - EmailTemplate, blank=True, null=True, on_delete=models.SET_NULL - ) - schedule_date_time = models.DateTimeField(blank=True, null=True) - timezone = models.CharField(max_length=100, default="UTC") - reply_to_email = models.EmailField(blank=True, null=True) - subject = models.CharField(max_length=5000) - html = models.TextField() - html_processed = models.TextField(default="", blank=True) - from_email = models.EmailField(blank=True, null=True) - from_name = models.EmailField(blank=True, null=True) - sent = models.IntegerField(default="0", blank=True) - opens = models.IntegerField(default="0", blank=True) - opens_unique = models.IntegerField(default="0", blank=True) - bounced = models.IntegerField(default="0") - tags = models.ManyToManyField(Tag) - status = models.CharField( - default="Preparing", choices=STATUS_CHOICES, max_length=20 - ) - attachment = models.FileField( - max_length=1000, upload_to=get_campaign_attachment_path, blank=True, null=True - ) - company = models.ForeignKey( - Company, - related_name="marketing_campaigns_company", - on_delete=models.CASCADE, - null=True, - ) - - class Meta: - ordering = ("-created_on",) - - # @property - # def no_of_unsubscribers(self): - # unsubscribers = self.campaign_contacts.filter( - # contact__is_unsubscribed=True).count() - # return unsubscribers - - # @property - # def no_of_bounces(self): - # bounces = self.campaign_contacts.filter( - # contact__is_bounced=True).count() - # return bounces - - @property - def no_of_clicks(self): - clicks = self.marketing_links.aggregate(Sum("clicks"))["clicks__sum"] - return clicks - - # @property - # def no_of_sent_emails(self): - # contacts = self.campaign_contacts.count() - # return contacts - - # @property - # def created_on_format(self): - # return self.created_on.strftime('%b %d, %Y %I:%M %p') - - @property - def sent_on_format(self): - if self.schedule_date_time: - c_schedule_date_time = convert_to_custom_timezone( - self.schedule_date_time, self.timezone - ) - return c_schedule_date_time.strftime("%b %d, %Y %I:%M %p") - else: - c_created_on = convert_to_custom_timezone(self.created_on, self.timezone) - return c_created_on.strftime("%b %d, %Y %I:%M %p") - - @property - def get_all_emails_count(self): - email_count = CampaignLog.objects.filter(campaign=self).count() - return email_count - # return self.contact_lists.exclude(contacts__email=None).values_list('contacts__email').count() - - @property - def get_all_email_bounces_count(self): - # return self.contact_lists.filter(contacts__is_bounced=True - # ).exclude(contacts__email=None).values_list('contacts__email').count() - email_count = CampaignLog.objects.filter( - campaign=self, contact__is_bounced=True - ).count() - return email_count - - @property - def get_all_emails_unsubscribed_count(self): - # return self.contact_lists.filter(contacts__is_unsubscribed=True - # ).exclude(contacts__email=None).values_list('contacts__email').count() - email_count = CampaignLog.objects.filter( - campaign=self, contact__is_unsubscribed=True - ).count() - return email_count - - @property - def get_all_emails_subscribed_count(self): - return ( - self.get_all_emails_count - - self.get_all_email_bounces_count - - self.get_all_emails_unsubscribed_count - ) - - @property - def get_all_emails_contacts_opened(self): - contact_ids = CampaignOpen.objects.filter(campaign=self).values_list( - "contact_id", flat=True - ) - # opened_contacts = Contact.objects.filter(id__in=contact_ids) - # return opened_contacts - return contact_ids.count() - - @property - def sent_on_arrow(self): - if self.schedule_date_time: - c_schedule_date_time = convert_to_custom_timezone( - self.schedule_date_time, self.timezone - ) - # return c_schedule_date_time.strftime('%b %d, %Y %I:%M %p') - return arrow.get(c_schedule_date_time).humanize() - else: - c_created_on = convert_to_custom_timezone(self.created_on, self.timezone) - # return c_created_on.strftime('%b %d, %Y %I:%M %p') - return arrow.get(self.created_on).humanize() - - -@receiver(models.signals.pre_delete, sender=Campaign) -def comment_attachments_delete(sender, instance, **kwargs): - attachment = instance.attachment - if attachment: - try: - if os.path.isfile(attachment.path): - os.remove(attachment.path) - except Exception: - return False - return True - - -class Link(models.Model): - campaign = models.ForeignKey( - Campaign, related_name="marketing_links", on_delete=models.CASCADE - ) - original = models.URLField(max_length=2100) - clicks = models.IntegerField(default="0") - unique = models.IntegerField(default="0") - - class Meta: - ordering = ("id",) - - -class CampaignLog(models.Model): - created_on = models.DateTimeField(auto_now_add=True) - campaign = models.ForeignKey( - Campaign, related_name="campaign_log_contacts", on_delete=models.CASCADE - ) - contact = models.ForeignKey( - Contact, - related_name="marketing_campaign_logs", - null=True, - on_delete=models.SET_NULL, - ) - message_id = models.CharField(max_length=1000, null=True, blank=True) - - -class CampaignLinkClick(models.Model): - campaign = models.ForeignKey( - Campaign, on_delete=models.CASCADE, related_name="campaign_link_click" - ) - link = models.ForeignKey(Link, blank=True, null=True, on_delete=models.CASCADE) - ip_address = models.GenericIPAddressField() - created_on = models.DateTimeField(auto_now_add=True) - user_agent = models.CharField(max_length=2000, blank=True, null=True) - contact = models.ForeignKey( - Contact, blank=True, null=True, on_delete=models.CASCADE - ) - - -class CampaignOpen(models.Model): - campaign = models.ForeignKey( - Campaign, on_delete=models.CASCADE, related_name="campaign_open" - ) - ip_address = models.GenericIPAddressField() - created_on = models.DateTimeField(auto_now_add=True) - user_agent = models.CharField(max_length=2000, blank=True, null=True) - contact = models.ForeignKey( - Contact, - blank=True, - null=True, - on_delete=models.CASCADE, - related_name="contact_campaign_open", - ) - - -class CampaignCompleted(models.Model): - """This Model Is Used To Check If The Scheduled Later Emails Have Been Sent - related name : campaign_is_completed - """ - - campaign = models.OneToOneField( - Campaign, on_delete=models.CASCADE, related_name="campaign_is_completed" - ) - is_completed = models.BooleanField(default=False) - - -class ContactUnsubscribedCampaign(models.Model): - """This Model Is Used To Check If The Contact has Unsubscribed To a Particular Campaign - related name : contact_is_unsubscribed - """ - - campaigns = models.ForeignKey( - Campaign, on_delete=models.CASCADE, related_name="campaign_is_unsubscribed" - ) - contacts = models.ForeignKey( - Contact, on_delete=models.Case, related_name="contact_is_unsubscribed" - ) - is_unsubscribed = models.BooleanField(default=False) - - -class ContactEmailCampaign(models.Model): - """ - send all campaign emails to this contact - """ - - name = models.CharField(max_length=500) - email = models.EmailField() - last_name = models.CharField(max_length=500, null=True, blank=True) - created_by = models.ForeignKey( - User, - related_name="marketing_contacts_emails_campaign_created_by", - null=True, - on_delete=models.SET_NULL, - ) - created_on = models.DateTimeField(auto_now_add=True) - company = models.ForeignKey( - Company, - related_name="marketing_contacts_emails_campaign_company", - on_delete=models.CASCADE, - null=True, - ) - - def created_on_arrow(self): - return arrow.get(self.created_on).humanize() - - class Meta: - ordering = ("created_on",) - - -class DuplicateContacts(models.Model): - """ - this model is used to store duplicate contacts - """ - - contacts = models.ForeignKey( - Contact, related_name="duplicate_contact", on_delete=models.SET_NULL, null=True - ) - contact_list = models.ForeignKey( - ContactList, - related_name="duplicate_contact_contact_list", - on_delete=models.SET_NULL, - null=True, - ) - - class Meta: - ordering = ("id",) - - -class BlockedDomain(models.Model): - """ - this model is used to block the domain - """ - - domain = models.CharField(max_length=200) - created_on = models.DateTimeField(auto_now_add=True) - created_by = models.ForeignKey( - User, on_delete=models.SET_NULL, null=True, blank=True - ) - company = models.ForeignKey( - Company, - on_delete=models.CASCADE, - null=True, - ) - - def __str__(self): - return self.domain - - def created_on_arrow(self): - return arrow.get(self.created_on).humanize() - - class Meta: - ordering = ("created_on",) - - -class BlockedEmail(models.Model): - """ - this model is used to block the email - """ - - email = models.EmailField() - created_on = models.DateTimeField(auto_now_add=True) - created_by = models.ForeignKey( - User, on_delete=models.SET_NULL, null=True, blank=True - ) - company = models.ForeignKey( - Company, - on_delete=models.CASCADE, - null=True, - ) - - def __str__(self): - return self.email - - def created_on_arrow(self): - return arrow.get(self.created_on).humanize() - - class Meta: - ordering = ("created_on",) diff --git a/marketing/search_backends.py b/marketing/search_backends.py deleted file mode 100644 index b93949e..0000000 --- a/marketing/search_backends.py +++ /dev/null @@ -1,20 +0,0 @@ -from django.conf import settings - -from haystack.backends.elasticsearch_backend import ( - ElasticsearchSearchBackend, - ElasticsearchSearchEngine, -) - - -class CustomElasticsearchSearchBackend(ElasticsearchSearchBackend): - def __init__(self, connection_alias, **connection_options): - super(CustomElasticsearchSearchBackend, self).__init__( - connection_alias, **connection_options - ) - - setattr(self, "DEFAULT_SETTINGS", settings.ELASTICSEARCH_INDEX_SETTINGS) - - -class CustomElasticsearchSearchEngine(ElasticsearchSearchEngine): - - backend = CustomElasticsearchSearchBackend diff --git a/marketing/search_indexes.py b/marketing/search_indexes.py deleted file mode 100644 index 78e7426..0000000 --- a/marketing/search_indexes.py +++ /dev/null @@ -1,114 +0,0 @@ -from haystack import indexes -from marketing.models import Contact, FailedContact - - -class MarketingContactIndex(indexes.SearchIndex, indexes.Indexable): - text = indexes.CharField( - document=True, use_template=True, template_name="search/contact_emails.txt" - ) - - id = indexes.CharField(model_attr="id") - email = indexes.EdgeNgramField(model_attr="email") - email_domain = indexes.EdgeNgramField() - name = indexes.CharField(model_attr="name") - company_name = indexes.CharField() - created_on = indexes.CharField(model_attr="created_on") - created_on_arrow = indexes.CharField(model_attr="created_on_arrow") - created_by = indexes.CharField() - created_by_id = indexes.CharField() - contact_lists = indexes.MultiValueField() - contact_lists_id = indexes.MultiValueField() - contact_lists_name = indexes.MultiValueField() - is_bounced = indexes.BooleanField() - - def get_model(self): - return Contact - - def prepare_email_domain(self, obj): - return obj.email.split("@")[-1] - - def prepare_contact_lists(self, obj): - return [ - [contact_list.id, contact_list.name if contact_list.name else ""] - for contact_list in obj.contact_list.all() - ] - - def prepare_contact_lists_id(self, obj): - return [ - contact_list.id for contact_list in obj.contact_list.all().order_by("id") - ] - - def prepare_contact_lists_name(self, obj): - return [ - contact_list.name for contact_list in obj.contact_list.all().order_by("id") - ] - - def prepare_company_name(self, obj): - return obj.company_name if obj.company_name else "" - - def prepare_created_by(self, obj): - return obj.created_by.email if obj.created_by else "" - - def prepare_created_by_id(self, obj): - return obj.created_by.id if obj.created_by else "" - - def prepare_is_bounced(self, obj): - return obj.is_bounced - - def index_queryset(self, using=None): - return self.get_model().objects.all() - - -class MarketingFailedContactIndex(indexes.SearchIndex, indexes.Indexable): - text = indexes.CharField( - document=True, - use_template=True, - template_name="search/failed_contact_emails.txt", - ) - - id = indexes.CharField(model_attr="id") - email = indexes.EdgeNgramField(model_attr="email") - email = indexes.EdgeNgramField() - name = indexes.CharField(model_attr="name") - company_name = indexes.CharField() - created_on = indexes.CharField(model_attr="created_on") - created_on_arrow = indexes.CharField(model_attr="created_on_arrow") - created_by = indexes.CharField() - created_by_id = indexes.CharField() - contact_lists = indexes.MultiValueField() - contact_lists_id = indexes.MultiValueField() - contact_lists_name = indexes.MultiValueField() - - def get_model(self): - return FailedContact - - def prepare_email_domain(self, obj): - return obj.email.split("@")[-1] - - def prepare_contact_lists(self, obj): - return [ - [contact_list.id, contact_list.name if contact_list.name else ""] - for contact_list in obj.contact_list.all() - ] - - def prepare_contact_lists_id(self, obj): - return [ - contact_list.id for contact_list in obj.contact_list.all().order_by("id") - ] - - def prepare_contact_lists_name(self, obj): - return [ - contact_list.name for contact_list in obj.contact_list.all().order_by("id") - ] - - def prepare_company_name(self, obj): - return obj.company_name if obj.company_name else "" - - def prepare_created_by(self, obj): - return obj.created_by.email if obj.created_by else "" - - def prepare_created_by_id(self, obj): - return obj.created_by.id if obj.created_by else "" - - def index_queryset(self, using=None): - return self.get_model().objects.all() diff --git a/marketing/serializer.py b/marketing/serializer.py deleted file mode 100644 index 4a84798..0000000 --- a/marketing/serializer.py +++ /dev/null @@ -1,121 +0,0 @@ -from rest_framework import serializers -from .models import ( - ContactEmailCampaign, - BlockedDomain, - BlockedEmail, -) -from common.serializer import UserSerializer, CompanySerializer -import re - - -class ContactEmailCampaignSerailizer(serializers.ModelSerializer): - created_by = UserSerializer() - company = CompanySerializer() - - def __init__(self, *args, **kwargs): - request_obj = kwargs.pop("request_obj", None) - super(ContactEmailCampaignSerailizer, self).__init__(*args, **kwargs) - self.fields["name"].required = False - self.fields["created_by"].required = False - self.fields["company"].required = False - - class Meta: - model = ContactEmailCampaign - fields = ( - "id", - "name", - "last_name", - "email", - "created_on", - "created_by", - "company", - ) - - -class BlockedDomainAddSerailizer(serializers.ModelSerializer): - created_by = UserSerializer() - company = CompanySerializer() - - def __init__(self, *args, **kwargs): - request_obj = kwargs.pop("request_obj", None) - super(BlockedDomainAddSerailizer, self).__init__(*args, **kwargs) - self.fields["created_by"].required = False - self.fields["company"].required = False - self.company = request_obj.company - - def validate_domain(self, domain): - domain_regex = "^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$" - if re.match(domain_regex, domain) is None: - raise serializers.ValidationError("Enter a valid domain.") - if self.instance: - if ( - BlockedDomain.objects.filter( - domain__iexact=domain, company=self.company - ) - .exclude(id=self.instance.id) - .exists() - ): - raise serializers.ValidationError( - "Domain already exists with this name" - ) - else: - if BlockedDomain.objects.filter( - domain__iexact=domain, company=self.company - ).exists(): - raise serializers.ValidationError( - "Domain already exists with this name" - ) - return domain - - class Meta: - model = BlockedDomain - fields = ("id", "domain", "created_on", "created_by", "company") - - -class BlockedEmailAddSerailizer(serializers.ModelSerializer): - created_by = UserSerializer() - company = CompanySerializer() - email = serializers.EmailField - - def __init__(self, *args, **kwargs): - request_obj = kwargs.pop("request_obj", None) - super(BlockedEmailAddSerailizer, self).__init__(*args, **kwargs) - self.fields["created_by"].required = False - self.fields["company"].required = False - self.company = request_obj.company - - def validate_email(self, email): - if self.instance: - if ( - BlockedEmail.objects.filter(email=email, company=self.company) - .exclude(id=self.instance.id) - .exists() - ): - raise serializers.ValidationError("Email already exists") - else: - if BlockedEmail.objects.filter(email=email, company=self.company).exists(): - raise serializers.ValidationError("email already exists") - return email - - class Meta: - model = BlockedEmail - fields = ("id", "email", "created_on", "created_by", "company") - - -class BlockedDomainSerailizer(serializers.ModelSerializer): - created_by = UserSerializer() - company = CompanySerializer() - - class Meta: - model = BlockedDomain - fields = ("id", "domain", "created_on", "created_by", "company") - - -class BlockedEmailSerailizer(serializers.ModelSerializer): - created_by = UserSerializer() - company = CompanySerializer() - email = serializers.EmailField - - class Meta: - model = BlockedEmail - fields = ("id", "email", "created_on", "created_by", "company") diff --git a/marketing/tasks.py b/marketing/tasks.py deleted file mode 100644 index 9fc4c6b..0000000 --- a/marketing/tasks.py +++ /dev/null @@ -1,407 +0,0 @@ -import datetime -import hashlib -from mimetypes import MimeTypes - -import pytz -import requests -from celery import Celery -from django.core.management import call_command -from django.conf import settings -from django.core.mail import EmailMessage -from django.shortcuts import reverse -from django.template import Context, Template - -from common.utils import convert_to_custom_timezone -from marketing.models import ( - BlockedDomain, - BlockedEmail, - Campaign, - CampaignCompleted, - CampaignLog, - Contact, - ContactEmailCampaign, - ContactList, - DuplicateContacts, - FailedContact, -) - -app = Celery("redis://") - - -@app.task -def campaign_sechedule(request): - pass - - -@app.task -def campaign_open(request): - pass - - -@app.task -def campaign_click(request): - pass - - -@app.task -def upload_csv_file(data, invalid_data, user, contact_lists, company): - for each in data: - contact = Contact.objects.filter(email=each["email"]).first() - if not contact: - contact = Contact.objects.create( - email=each["email"], - created_by_id=user, - name=each["first name"], - company_id=company, - ) - if each.get("company name", None): - contact.company_name = each["company name"] - if each.get("last name", None): - contact.last_name = each["last name"] - if each.get("city", None): - contact.city = each["city"] - if each.get("state", None): - contact.state = each["state"] - contact.save() - else: - if not DuplicateContacts.objects.filter( - contacts=contact, - contact_list=ContactList.objects.get(id=int(contact_lists[0])), - ).exists(): - DuplicateContacts.objects.create( - contacts=contact, - contact_list=ContactList.objects.get(id=int(contact_lists[0])), - ) - for contact_list in contact_lists: - contact.contact_list.add(ContactList.objects.get(id=int(contact_list))) - - for each in invalid_data: - contact = FailedContact.objects.filter(email=each["email"]).first() - if not contact: - contact = FailedContact.objects.create( - email=each["email"], - created_by_id=user, - name=each["first name"], - company_id=company, - ) - if each.get("company name", None): - contact.company_name = each["company name"] - if each.get("last name", None): - contact.last_name = each["last name"] - if each.get("city", None): - contact.city = each["city"] - if each.get("state", None): - contact.state = each["state"] - contact.save() - for contact_list in contact_lists: - contact.contact_list.add(ContactList.objects.get(id=int(contact_list))) - - -def send_campaign_mail( - subject, content, from_email, to_email, bcc, reply_to, attachments -): - msg = EmailMessage( - subject, - content, - from_email, - to_email, - bcc, - reply_to=reply_to, - ) - for attachment in attachments: - msg.attach(*attachment) - msg.content_subtype = "html" - res = msg.send() - print(res) - - -def get_campaign_message_id(campaign): - hash_ = hashlib.md5() - hash_.update( - str(str(campaign.id) + str(campaign.campaign.created_by.id)).encode("utf-8") - + str(datetime.datetime.now()).encode("utf-8") - ) - file_hash = hash_.hexdigest() - return file_hash - - -@app.task -def run_campaign(campaign, domain="demo.django-crm.io", protocol="https"): - blocked_domains = BlockedDomain.objects.values_list("domain", flat=True) - blocked_emails = BlockedEmail.objects.values_list("email", flat=True) - try: - campaign = Campaign.objects.get(id=campaign) - attachments = [] - if campaign.attachment: - file_path = campaign.attachment.path - file_name = file_path.split("/")[-1] - content = open(file_path, "rb").read() - mime = MimeTypes() - mime_type = mime.guess_type(file_path) - attachments.append((file_name, content, mime_type[0])) - subject = campaign.subject - - contacts = Contact.objects.filter( - contact_list__in=[each_list for each_list in campaign.contact_lists.all()] - ) - default_html = campaign.html_processed - for each_contact in contacts: - html = default_html - campaign_log = CampaignLog.objects.create( - contact=each_contact, campaign=campaign - ) - if campaign.reply_to_email: - reply_to_email = campaign.reply_to_email - else: - message_id = get_campaign_message_id(campaign_log) - campaign_log.message_id = message_id - campaign_log.save() - domain_name = "django-crm.com" - if campaign.from_email is not None: - from_email = campaign.from_email - else: - from_email = campaign.created_by.email - reply_to_email = ( - str(from_email) - + " <" - + str(message_id + "@" + domain_name + "") - + ">" - ) - if not (each_contact.is_bounced or each_contact.is_unsubscribed): - if (each_contact.email not in blocked_emails) and ( - each_contact.email.split("@")[-1] not in blocked_domains - ): - # domain_url = settings.URL_FOR_LINKS - domain_url = protocol + "://" + domain - img_src_url = domain_url + reverse( - "marketing:campaign_open", - kwargs={ - "campaign_log_id": campaign_log.id, - "email_id": each_contact.id, - }, - ) - # images can only be accessed over https - link = 'company_logo'.format( - img_src_url=img_src_url - ) - # link = 'company_logo' - - unsubscribe_from_campaign_url = reverse( - "marketing:unsubscribe_from_campaign", - kwargs={ - "contact_id": each_contact.id, - "campaign_id": campaign.id, - }, - ) - unsubscribe_from_campaign_html = ( - "

      Unsubscribe".format( - domain_url + unsubscribe_from_campaign_url - ) - ) - names_dict = { - "company_name": each_contact.company_name - if each_contact.company_name - else "", - "last_name": each_contact.last_name - if each_contact.last_name - else "", - "city": each_contact.city if each_contact.city else "", - "state": each_contact.state if each_contact.state else "", - "first_name": each_contact.name, - "email": each_contact.email, - "email_id": each_contact.id, - "name": each_contact.name + " " + each_contact.last_name - if each_contact.last_name - else "", - "unsubscribe_from_campaign_url": unsubscribe_from_campaign_url, - } - - html = Template(html).render(Context(names_dict)) - mail_html = html + link + unsubscribe_from_campaign_html - from_email = ( - str(campaign.from_name) + "<" + str(campaign.from_email) + ">" - ) - to_email = [each_contact.email] - send_campaign_mail( - subject, - mail_html, - from_email, - to_email, - [], - [reply_to_email], - attachments, - ) - except Exception as e: - print(e) - pass - - -@app.task -def run_all_campaigns(): - start_date = datetime.date.today() - campaigns = Campaign.objects.filter(schedule_date_time__date=start_date) - for each in campaigns: - run_campaign(each.id) - - -@app.task -def list_all_bounces_unsubscribes(): - bounces = requests.get( - "https://api.sendgrid.com/api/bounces.get.json?api_user=" - + settings.EMAIL_HOST_USER - + "&api_key=" - + settings.EMAIL_HOST_PASSWORD - ) - for each in bounces.json(): - if type(each) == dict: - contact = Contact.objects.filter(email=each.get("email")).first() - if contact: - contact.is_bounced = True - contact.save() - - bounces = requests.get( - "https://api.sendgrid.com/api/unsubscribes.get.json?api_user=" - + settings.EMAIL_HOST_USER - + "&api_key=" - + settings.EMAIL_HOST_PASSWORD - ) - for each in bounces.json(): - if type(each) == dict: - contact = Contact.objects.filter(email=each.get("email")).first() - if contact: - contact.is_unsubscribed = True - contact.save() - - -@app.task -def send_scheduled_campaigns(): - from datetime import datetime - - campaigns = Campaign.objects.filter(schedule_date_time__isnull=False) - for each in campaigns: - completed = CampaignCompleted.objects.filter(is_completed=True).values_list( - "campaign_id", flat=True - ) - - if each.id not in completed: - schedule_date_time = each.schedule_date_time - - sent_time = datetime.now().strftime("%Y-%m-%d %H:%M") - sent_time = datetime.strptime(sent_time, "%Y-%m-%d %H:%M") - local_tz = pytz.timezone(settings.TIME_ZONE) - sent_time = local_tz.localize(sent_time) - sent_time = convert_to_custom_timezone( - sent_time, each.timezone, to_utc=True - ) - - if str(each.schedule_date_time.date()) == str(sent_time.date()) and str( - schedule_date_time.hour - ) == str(sent_time.hour): - run_campaign.delay(each.id) - CampaignCompleted.objects.create(campaign=each, is_completed=True) - - -@app.task -def delete_multiple_contacts_tasks(contact_list_id, bounced=True): - """ this method is used to remove all contacts from a contact list based on bounced kwarg """ - contacts_list_obj = ContactList.objects.filter(id=contact_list_id).first() - if contacts_list_obj: - contacts_objs = contacts_list_obj.contacts.filter(is_bounced=bounced) - if contacts_objs: - for contact_obj in contacts_objs: - if contact_obj.contact_list.count() > 1: - contact_obj.contact_list.remove(contacts_list_obj) - else: - contact_obj.delete() - - -@app.task -def send_campaign_email_to_admin_contact( - campaign, domain="demo.django-crm.io", protocol="https" -): - try: - campaign = Campaign.objects.get(id=campaign) - attachments = [] - if campaign.attachment: - file_path = campaign.attachment.path - file_name = file_path.split("/")[-1] - content = open(file_path, "rb").read() - mime = MimeTypes() - mime_type = mime.guess_type(file_path) - attachments.append((file_name, content, mime_type[0])) - subject = campaign.subject - contacts = ContactEmailCampaign.objects.all() - default_html = campaign.html_processed - blocked_domains = BlockedDomain.objects.values_list("domain", flat=True) - blocked_emails = BlockedEmail.objects.values_list("email", flat=True) - for each_contact in contacts: - if (each_contact.email not in blocked_emails) and ( - each_contact.email.split("@")[-1] not in blocked_domains - ): - html = default_html - if campaign.reply_to_email: - reply_to_email = campaign.reply_to_email - else: - domain_name = "django-crm.com" - if campaign.from_email is not None: - from_email = campaign.from_email - else: - from_email = campaign.created_by.email - reply_to_email = ( - str(from_email) - + " <" - + str(settings.EMAIL_HOST_USER + "@" + domain_name + "") - + ">" - ) - - # domain_url = settings.URL_FOR_LINKS - domain_url = protocol + "://" + domain - # img_src_url = domain_url + reverse('marketing:campaign_open', kwargs={ - # 'campaign_log_id': campaign_log.id, 'email_id': each_contact.id}) - # # images can only be accessed over https - # link = 'company_logo'.format( - # img_src_url=img_src_url) - # link = 'company_logo' - - # unsubscribe_from_campaign_url = reverse( - # 'marketing:unsubscribe_from_campaign', kwargs={'contact_id': each_contact.id, - # 'campaign_id': campaign.id}) - # unsubscribe_from_campaign_html = "

      Unsubscribe".format( - # domain_url + unsubscribe_from_campaign_url) - - # names_dict = {'company_name': '', 'city': '', 'state': '', - # 'last_name': each_contact.last_name if each_contact.last_name else '', - # 'email': each_contact.email, 'email_id': each_contact.id, - # 'name': each_contact.name + ' ' + each_contact.last_name if each_contact.last_name else '', - # } - - # mail_html = html + link + unsubscribe_from_campaign_html - html = Template(html).render(Context({"email_id": each_contact.id})) - mail_html = html - from_email = ( - str(campaign.from_name) + "<" + str(campaign.from_email) + ">" - ) - to_email = [each_contact.email] - send_campaign_mail( - subject, - mail_html, - from_email, - to_email, - [], - [reply_to_email], - attachments, - ) - except Exception as e: - print(e) - pass - - -@app.task -def update_elastic_search_index(): - call_command("update_index --age=1", interactive=False) diff --git a/marketing/templates/add_blocked_domain.html b/marketing/templates/add_blocked_domain.html deleted file mode 100644 index b34af1f..0000000 --- a/marketing/templates/add_blocked_domain.html +++ /dev/null @@ -1,88 +0,0 @@ -{% extends 'sales/base.html' %} -{% load static %} -{% block content %} -{{ block.super }} - -
      -
      -
      -
      -
      -
      -
      -
      -
      - {% if block_domain_obj %}Edit{% else %}Create{% endif %} Block Domain -
      - -
      -
      -
      - * - -
      - -
      -
      -
      - - - -
      -
      -
      - -
      -
      -
      -
      - -
      -
      -
      -{% endblock %} -{% block js_block %} - - - -{% endblock js_block %} diff --git a/marketing/templates/add_blocked_email.html b/marketing/templates/add_blocked_email.html deleted file mode 100644 index a90c4ce..0000000 --- a/marketing/templates/add_blocked_email.html +++ /dev/null @@ -1,88 +0,0 @@ -{% extends 'sales/base.html' %} -{% load static %} -{% block content %} -{{ block.super }} - -
      -
      -
      -
      -
      -
      -
      -
      -
      - {% if block_email_obj %}Edit{% else %}Create{% endif %} Block Email -
      - -
      -
      -
      - - * - -
      - -
      -
      -
      - - -
      -
      -
      - -
      -
      -
      -
      - -
      -
      -
      -{% endblock %} -{% block js_block %} - - - -{% endblock js_block %} diff --git a/marketing/templates/add_email_for_campaign.html b/marketing/templates/add_email_for_campaign.html deleted file mode 100644 index eda2591..0000000 --- a/marketing/templates/add_email_for_campaign.html +++ /dev/null @@ -1,101 +0,0 @@ -{% extends 'sales/base.html' %} -{% load static %} -{% block breadcrumb %} - -{% endblock %} -{%block content%} -
      -
      -
      -
      -
      -
      - {% if edit_obj %} - Edit Email for Campaign - {% else %} - Add Email for Campaign - {% endif %} -
      -
      -
      -
      -
      - - - {{ form.name.errors }} -
      -
      -
      -
      -
      -
      - - - {{ form.website.errors }} -
      -
      -
      -
      -
      -
      - - - {{ form.email.errors }} -
      -
      -
      -
      -
      - - Cancel -
      -
      -
      -
      -
      -
      - -
      -
      -{% endblock %} -{% block js_block %} - - -{% endblock js_block %} diff --git a/marketing/templates/blocked_domain_list.html b/marketing/templates/blocked_domain_list.html deleted file mode 100644 index 18cc635..0000000 --- a/marketing/templates/blocked_domain_list.html +++ /dev/null @@ -1,177 +0,0 @@ -{% extends 'sales/base.html' %} -{% load static %} -{% load paginate %} -{% load thumbnail %} -{% block content %} - - -
      -
      -
      - Contacts - -
      -
      - - - -
      -
      -
      -
      -
      -
      -
      Filter Contacts
      -
      - -
      -
      - - -
      -
      - - - -
      -
      - - Clear -
      -
      -
      -
      -
      -
      -
      -
      -
      - - - - - -
      -
      -
      -
      - -
      -
      -
      -
      -
      - Blocked Domain - {% if show_pageitems %} - {% show_pageitems %}{% else %} - {{ blocked_domains|length }}{% endif %} - - - -
      -
      - - - {% if blocked_domains|length > 0 %} - - - - - - - - {% endif %} - - - {% if per_page %} - {% paginate per_page blocked_domains %} - {% else %} - {% paginate 10 blocked_domains %} - {% endif %} - {% for domain in blocked_domains %} - - - - - - - - {% endfor %} - -
      IDDomainCreated byCreated OnActions
      {{ forloop.counter }}{{ domain.domain }} - {% if domain.created_by %} - {% if domain.created_by.profile_pic %} - {% thumbnail domain.created_by.profile_pic "40x40" crop="center" as im %} - - {% endthumbnail %} - {% else %} - - {% endif %} - {% else %} - - {% endif %} - {{ domain.created_on_arrow }} - {% if request.user.role == 'ADMIN' or reques.user.is_superuser %} - - - {% endif %} -
      -
      - {%ifequal blocked_domains|length 0%} -
      No Domains Found
      - {%endifequal%} -
      - {% show_pages %} -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      - -
      - -{% endblock %} -{% block js_block %} - -{% endblock js_block %} \ No newline at end of file diff --git a/marketing/templates/blocked_email_list.html b/marketing/templates/blocked_email_list.html deleted file mode 100644 index a0b9d79..0000000 --- a/marketing/templates/blocked_email_list.html +++ /dev/null @@ -1,177 +0,0 @@ -{% extends 'sales/base.html' %} -{% load static %} -{% load paginate %} -{% load thumbnail %} -{% block content %} - - -
      -
      - -
      - - - -
      -
      -
      -
      -
      -
      -
      Filter Emails
      -
      - -
      -
      - - -
      -
      - - - -
      -
      - - Clear -
      -
      -
      -
      -
      -
      -
      -
      -
      - - - - - -
      -
      -
      -
      - -
      -
      -
      -
      -
      - Blocked Emails - {% if show_pageitems %} - {% show_pageitems %}{% else %} - {{ blocked_emails|length }}{% endif %} - - - -
      -
      - - - {% if blocked_emails|length > 0 %} - - - - - - - - {% endif %} - - - {% if per_page %} - {% paginate per_page blocked_emails %} - {% else %} - {% paginate 10 blocked_emails %} - {% endif %} - {% for email in blocked_emails %} - - - - - - - - {% endfor %} - -
      IDEmailCreated byCreated OnActions
      {{ forloop.counter }}{{ email.email }} - {% if email.created_by %} - {% if email.created_by.profile_pic %} - {% thumbnail email.created_by.profile_pic "40x40" crop="center" as im %} - - {% endthumbnail %} - {% else %} - - {% endif %} - {% else %} - - {% endif %} - {{ email.created_on_arrow }} - {% if request.user.role == 'ADMIN' or reques.user.is_superuser %} - - - {% endif %} -
      -
      - {%ifequal blocked_emails|length 0%} -
      No Email Found
      - {%endifequal%} -
      - {% show_pages %} -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      - -
      - -{% endblock %} -{% block js_block %} - -{% endblock js_block %} \ No newline at end of file diff --git a/marketing/templates/contact_detail.html b/marketing/templates/contact_detail.html deleted file mode 100644 index 043b1cf..0000000 --- a/marketing/templates/contact_detail.html +++ /dev/null @@ -1,120 +0,0 @@ -{% extends 'marketing/base.html' %} -{% load static %} -{% load paginate %} -{% block content %} -{{ block.super }} - -
      -
      -
      -
      -
      -
      -
      -
      -
      - Contact Detail -
      -
      -
      -
      -
      - -
      - {{contact_obj.email}} -
      -
      -
      -
      - -
      - {{contact_obj.company_name}} -
      -
      -
      -
      - -
      - {{contact_obj.name}} -
      -
      -
      -
      - -
      - {{contact_obj.last_name}} -
      -
      -
      -
      - -
      - {{contact_obj.city}} -
      -
      -
      -
      - -
      - {{contact_obj.state}} -
      -
      -
      - -
      -
      -
      -
      -
      -
      -
      -
      -
      -{% endblock %} -{% block js_block %} - -{% endblock js_block %} \ No newline at end of file diff --git a/marketing/templates/email_for_campaigns_list.html b/marketing/templates/email_for_campaigns_list.html deleted file mode 100644 index 7bbb665..0000000 --- a/marketing/templates/email_for_campaigns_list.html +++ /dev/null @@ -1,166 +0,0 @@ -{% extends 'sales/base.html' %} -{% load static %} -{% load paginate %} -{% load thumbnail %} -{% block extralinks %} - -{% endblock %} -{% block content %} - -
      - - - -
      - -
      -
      -
      -
      - -
      -
      -
      -
      -
      - Contacts - {% if show_pageitems %} - {% show_pageitems %}{% else %} - {{ contacts|length }}{% endif %} - - - -
      -
      - - - {% if contacts|length > 0 %} - - - - - - - - - {% endif %} - - - {% if per_page %} - {% paginate per_page contacts %} - {% else %} - {% paginate 10 contacts %} - {% endif %} - {% for contact in contacts %} - - - - - - - - - {% endfor %} - -
      ID NameEmailCreated byCreated OnActions
      {{ forloop.counter }}{{ contact.name }} - {{contact.email}} - - {% if contact.created_by %} - {% if contact.created_by.profile_pic %} - {% thumbnail contact.created_by.profile_pic "40x40" crop="center" as im %} - - {% endthumbnail %} - {% else %} - - {% endif %} - {% else %} - - {% endif %} - {{ contact.created_on_arrow }} - {% if request.user.role == 'ADMIN' or reques.user.is_superuser %} - - - {% endif %} -
      -
      - {%ifequal contacts|length 0%} -
      No Contacts Found
      - {%endifequal%} -
      - {% show_pages %} -
      -
      -
      -
      -
      -
      -
      -
      -
      - - - - - - -{% endblock %} -{% block js_block %} - -{% endblock js_block %} \ No newline at end of file diff --git a/marketing/templates/html_message_campaign.html b/marketing/templates/html_message_campaign.html deleted file mode 100644 index ab89d7e..0000000 --- a/marketing/templates/html_message_campaign.html +++ /dev/null @@ -1,14 +0,0 @@ -{% block body %} - -{% block content %} -{{html|safe}} - -{% endblock content %} - - -{% block unsubscribe_link %} - Unsubscribe -{% endblock unsubscribe_link %} - - -{% endblock body %} \ No newline at end of file diff --git a/marketing/templates/search/contact_emails.txt b/marketing/templates/search/contact_emails.txt deleted file mode 100644 index 1e0c55d..0000000 --- a/marketing/templates/search/contact_emails.txt +++ /dev/null @@ -1,19 +0,0 @@ -{{ object.id }} -{{ object.email }} -{{ object.name }} -{{ object.company_name }} -{{ object.created_on_arrow }} -{{ object.created_on }} -{{ object.created_by }} -{{ object.created_by_id }} -{{ object.email_domain }} -{{ object.is_bounced }} -{{ object.contact_lists_count }} - -{% for contact_list in object.contact_lists.all %} - {{ contact_list.id }} -{% endfor %} - -{% for contact_list in object.contact_lists.all %} - {{ contact_list.name }} -{% endfor %} diff --git a/marketing/templates/search/failed_contact_emails.txt b/marketing/templates/search/failed_contact_emails.txt deleted file mode 100644 index 0a4d7bd..0000000 --- a/marketing/templates/search/failed_contact_emails.txt +++ /dev/null @@ -1,18 +0,0 @@ -{{ object.id }} -{{ object.email }} -{{ object.name }} -{{ object.company_name }} -{{ object.created_on_arrow }} -{{ object.created_on }} -{{ object.created_by }} -{{ object.created_by_id }} -{{ object.email_domain }} -{{ object.contact_lists_count }} - -{% for contact_list in object.contact_lists.all %} - {{ contact_list.id }} -{% endfor %} - -{% for contact_list in object.contact_lists.all %} - {{ contact_list.name }} -{% endfor %} diff --git a/marketing/templates/search/search.html b/marketing/templates/search/search.html deleted file mode 100644 index bec36ce..0000000 --- a/marketing/templates/search/search.html +++ /dev/null @@ -1,162 +0,0 @@ -{% extends 'marketing/base.html' %} -{% load static %} -{% load paginate %} -{% block content %} -{{ block.super }} - -
      -
      - -
      -
      -
      -
      -
      -
      -
      Filters
      -
      -
      -
      - - -
      -
      - -
      -
      - - Clear -
      -
      -
      -
      -
      -
      -
      -
      -
      - -
      -
      -
      -
      -
      - Contacts - {{ page.object_list|length }} - - - - Add New Contact - List -
      -
      - - {% if page.object_list %} - - - - - - - - - - - - - {% endif %} - - - {% for contact in page.object_list %} - - - - - - - - - - - - {% empty %} - - - - {% endfor %} - -
      S. NoNameEmailCompanyCreated byCreated OnActions
      {{ forloop.counter }}{{ contact.name }} - {{ contact.email }}{{ contact.company_name }}{{ contact.created_by }}{{ contact.created_on_arrow }} - - - -
      No records found!
      -
      -
      -
      -
      -
      - {% if query %} - - {% if page.has_previous or page.has_next %} -
      - {% if page.has_previous %}{% endif %}« - Previous{% if page.has_previous %}{% endif %} - | - {% if page.has_next %}{% endif %}Next - »{% if page.has_next %}{% endif %} -
      - {% endif %} - - {% else %} - {# Show some example queries to run, maybe query syntax, something else? #} - {% endif %} -
      -
      -
      -
      -{% endblock %} - -{% block js_block %} - -{% endblock js_block %} \ No newline at end of file diff --git a/marketing/templates/search_contact_emails.html b/marketing/templates/search_contact_emails.html deleted file mode 100644 index 030ee90..0000000 --- a/marketing/templates/search_contact_emails.html +++ /dev/null @@ -1,642 +0,0 @@ -{% extends 'marketing/base.html' %} -{% load static %} -{% load paginate %} -{% block content %} -{{ block.super }} - -
      - -
      - -
      -
      -
      -
      -
      -
      -
      -
      Filters
      -
      - -
      -
      - - -
      -
      - -
      -
      - - -
      -
      -
      -
      - - -
      -
      - -
      -
      - - Clear -
      -
      -
      -
      -
      -
      -
      -
      -
      - - -
      -
      -
      -
      - -
      -
      -
      -
      -
      - Contacts - {% if show_pageitems %} - {% show_pageitems %}{% else %}{{contacts|length}}{% endif %} - - - - -
      -
      - - - - - - - - - - - - - - - - {% if per_page %} - {% paginate per_page contacts %} - {% else%} - {% paginate 10 contacts %} - {% endif %} - {% for contact in contacts %} - - - - - - - - - - - - {% empty %} - - - - {% endfor %} - -
      S. NoNameEmailCompanyCreated byCreated OnRelated Contact ListActions
      {{ forloop.counter }}{{ contact.name }}{{ contact.email }}{{ contact.company_name }}{{ contact.created_by }}{{ contact.created_on_arrow }} - {% for contact_list in contact.contact_list.all %} - {{contact_list.name}} - - {% empty %} - None - {% endfor %} - - - - -
      There are no records
      -
      -
      -
      - {% show_pages %} -
      -
      -
      -
      -
      -
      -
      - Bounced Contacts - {{bounced_contacts|length}} - - - - -
      -
      - - - - - - - - - - - - - - - {% if per_page %} - {% paginate per_page bounced_contacts %} - {% else%} - {% paginate 10 bounced_contacts %} - {% endif %} - {% for contact in bounced_contacts %} - - - - - - - - - - - - {% empty %} - - - - {% endfor %} - -
      S. NoNameEmailCompanyCreated byCreated OnRelated Contact ListActions
      {{ forloop.counter }}{{ contact.name }}{{ contact.email }}{{ contact.company_name }}{{ contact.created_by }}{{ contact.created_on_arrow }} - {% for contact_list in contact.contact_lists %} - {{contact_list.1}} - - {% empty %} - None - {% endfor %} - - - - -
      There are no records
      -
      -
      -
      -
        - {% show_pages %} -
      -
      -
      -
      -
      -
      -
      -
      - Failed Contacts - {{failed_contacts|length}} - - - - -
      -
      - - - - - - - - - - - - - - - {% if per_page %} - {% paginate per_page failed_contacts %} - {% else%} - {% paginate 10 failed_contacts %} - {% endif %} - {% for contact in failed_contacts %} - - - - - - - - - - - - {% empty %} - - - - {% endfor %} - -
      S. NoNameEmailCompanyCreated byCreated OnRelated Contact ListActions
      {{ forloop.counter }}{{ contact.name }}{{ contact.email }}{{ contact.company_name }}{{ contact.created_by }}{{ contact.created_on_arrow }} - {% for contact_list in contact.contact_lists %} - {{contact_list.1}} - - {% empty %} - None - {% endfor %} - - - - -
      There are no records
      -
      -
      -
      -
        - {% show_pages %} -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      - - - - - - - - - - -{% endblock %} - -{% block js_block %} - -{% endblock js_block %} \ No newline at end of file diff --git a/marketing/templates/unsubscribe_from_campaign_template.html b/marketing/templates/unsubscribe_from_campaign_template.html deleted file mode 100644 index 4cde732..0000000 --- a/marketing/templates/unsubscribe_from_campaign_template.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - CRM - - - - - - - -
      -
      -
      -
      -

      Unsubscribed Request

      -

      You have successfully unsubscribed from Campaign emails from - {{request.get_host}}.

      - - -
      - -
      -
      -
      -
      -
      - - - - - - \ No newline at end of file diff --git a/marketing/templatetags/__init__.py b/marketing/templatetags/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/marketing/templatetags/digg_paginator.py b/marketing/templatetags/digg_paginator.py deleted file mode 100644 index 684bfe9..0000000 --- a/marketing/templatetags/digg_paginator.py +++ /dev/null @@ -1,98 +0,0 @@ -from django import template - -register = template.Library() - -LEADING_PAGE_RANGE_DISPLAYED = TRAILING_PAGE_RANGE_DISPLAYED = 0 -LEADING_PAGE_RANGE = TRAILING_PAGE_RANGE = 0 -NUM_PAGES_OUTSIDE_RANGE = 0 -ADJACENT_PAGES = 2 - - -def digg_paginator(context): # pragma: no cover - """ - To be used in conjunction with the object_list generic view. - - Adds pagination context variables for use in displaying leading, adjacent and - trailing page links in addition to those created by the object_list generic - view. - """ - - paginator = context["paginator"] - page_obj = context["page_obj"] - pages = paginator.num_pages - page = page_obj.number - in_leading_range = in_trailing_range = False - pages_outside_leading_range = pages_outside_trailing_range = range(0) - if pages <= LEADING_PAGE_RANGE_DISPLAYED + NUM_PAGES_OUTSIDE_RANGE + 1: - in_leading_range = in_trailing_range = True - page_range = [n for n in range(1, pages + 1)] - elif page <= LEADING_PAGE_RANGE: - in_leading_range = True - page_range = [n for n in range(1, LEADING_PAGE_RANGE_DISPLAYED + 1)] - pages_outside_leading_range = [ - n + pages for n in range(0, -NUM_PAGES_OUTSIDE_RANGE, -1) - ] - elif page > pages - TRAILING_PAGE_RANGE: - in_trailing_range = True - page_range = [ - n - for n in range(pages - TRAILING_PAGE_RANGE_DISPLAYED + 1, pages + 1) - if n > 0 and n <= pages - ] - pages_outside_trailing_range = [ - n + 1 for n in range(0, NUM_PAGES_OUTSIDE_RANGE) - ] - else: - page_range = [ - n - for n in range(page - ADJACENT_PAGES, page + ADJACENT_PAGES + 1) - if n > 0 and n <= pages - ] - pages_outside_leading_range = [ - n + pages for n in range(0, -NUM_PAGES_OUTSIDE_RANGE, -1) - ] - pages_outside_trailing_range = [ - n + 1 for n in range(0, NUM_PAGES_OUTSIDE_RANGE) - ] - - # Now try to retain GET params, except for 'page' - # Add 'django.core.context_processors.request' to settings.TEMPLATE_CONTEXT_PROCESSORS beforehand - request = context["request"] - params = request.GET.copy() - # if 'page' in params: - # del(params['page']) - # get_params = params.urlencode() - - if "bounced_contacts_page" in params: - del params["bounced_contacts_page"] - get_params = params.urlencode() - - if page_obj.has_previous(): - previous_page = page_obj.previous_page_number() - else: - previous_page = 1 - - if page_obj.has_next(): - next_page = page_obj.next_page_number() - else: - next_page = pages - - return { - "pages": pages, - "bounced_contacts_page": page, - "previous": previous_page, - "next": next_page, - "has_previous": page_obj.has_previous(), - "has_next": page_obj.has_next(), - "page_range": page_range, - "in_leading_range": in_leading_range, - "in_trailing_range": in_trailing_range, - "pages_outside_leading_range": pages_outside_leading_range, - "pages_outside_trailing_range": pages_outside_trailing_range, - "get_params": get_params, - } - - -register.inclusion_tag("contact_list_digg_paginator.html", takes_context=True)( - digg_paginator -) diff --git a/marketing/tests.py b/marketing/tests.py deleted file mode 100644 index d4387ba..0000000 --- a/marketing/tests.py +++ /dev/null @@ -1,1602 +0,0 @@ -import os -from datetime import datetime, timedelta - -import openpyxl -import xlwt -from django.core.files.uploadedfile import SimpleUploadedFile -from django.core.management import call_command -from django.shortcuts import reverse -from django.test import Client, TestCase -from django.test.utils import override_settings - -from common.models import Company, User -from marketing.models import ( - Campaign, - CampaignLinkClick, - CampaignLog, - CampaignOpen, - Contact, - ContactEmailCampaign, - ContactList, - EmailTemplate, - FailedContact, - Link, - Tag, -) -from marketing.views import * - -# from haystack import connections - - -TEST_INDEX = { - "default": { - "ENGINE": "haystack.backends.elasticsearch_backend.ElasticsearchSearchEngine", - "URL": "http://127.0.0.1:9200/", - "TIMEOUT": 60 * 10, - "INDEX_NAME": "test_index", - }, -} - - -class TestMarketingModel(object): - def setUp(self): - self.client = Client() - self.company, _ = Company.objects.get_or_create( - name="test company", address="IN", sub_domain="test", country="IN" - ) - - self.user = User.objects.create( - username="john", - email="john@example.com", - role="ADMIN", - company=self.company, - ) - self.user.set_password("password") - self.user.save() - - self.user1 = User.objects.create( - username="janeMarketing", - email="janeMarketing@example.com", - role="USER", - has_marketing_access=True, - company=self.company, - ) - self.user1.set_password("password") - self.user1.save() - - self.client.login(username="john@example.com", password="password") - - self.tag_marketing = Tag.objects.create( - name="tag marketing", created_by=self.user - ) - self.tag_marketing_1 = Tag.objects.create(name="tag marketing _1") - - self.contact_list = ContactList.objects.create( - name="contacts_list by admin", created_by=self.user - ) - self.contact_list.tags.add(self.tag_marketing.id) - - self.contact_list_user = ContactList.objects.create( - name="contacts_list by user", created_by=self.user1 - ) - - self.contact_list_user_1 = ContactList.objects.create( - name="contacts_list by user 1", created_by=self.user1 - ) - - self.contact = Contact.objects.create( - name="john doe", email="johnDoe@email.com", created_by=self.user - ) - self.contact_1 = Contact.objects.create( - name="jane doe", email="janeDoe@email.com", is_bounced=True - ) - self.contact_1.contact_list.add(self.contact_list.id, self.contact_list_user.id) - self.contact_2 = Contact.objects.create( - name="joe doe", email="joeDoe@email.com" - ) - self.contact_3 = Contact.objects.create( - name="jill doe", email="jillDoe@email.com" - ) - self.contact_4 = Contact.objects.create( - name="jill Doe", email="jilldoe@email.com" - ) - self.contact_4.contact_list.add(self.contact_list.id) - self.contact_5 = Contact.objects.create( - name="jack Doe", email="jack doe@email.com", is_bounced=True - ) - self.contact_5.contact_list.add(self.contact_list.id) - self.contact_6 = Contact.objects.create( - name="contact 6", email="contact6@email.com" - ) - self.contact_6.contact_list.add(self.contact_list.id) - self.failed_contact = FailedContact.objects.create( - name="jill Doe", email="jilldoe@email.com" - ) - self.failed_contact.contact_list.add(self.contact_list.id) - - self.email_template = EmailTemplate.objects.create( - created_by=self.user, - title="email title", - subject="email subject", - html="email html body", - ) - - self.campaign = Campaign.objects.create( - title="campaign object", - created_by=self.user, - email_template=self.email_template, - reply_to_email="django@crm.io", - subject="subject of the campaign", - html="html content", - from_email="from@email.com", - from_name="from name", - ) - - self.campaign_scheduled_later = Campaign.objects.create( - title="campaign object", - created_by=self.user, - email_template=self.email_template, - reply_to_email="django@crm.io", - subject="subject of the campaign", - from_email="from@email.com", - from_name="from name", - timezone="Asia/Kolkata", - status="Scheduled", - schedule_date_time=(datetime.now() + timedelta(days=2)).strftime( - "%Y-%m-%d %H:%M" - ), - html='

      links

      ', - ) - - self.campaign.contact_lists.add(self.contact_list.id, self.contact_list_user.id) - self.campaign.tags.add(self.tag_marketing.id) - - self.link = Link.objects.create( - campaign=self.campaign, - original="https://example.com", - ) - - self.campaign_link_click = CampaignLinkClick.objects.create( - campaign=self.campaign, - link=self.link, - contact=self.contact, - ip_address="127.0.0.1", - ) - - self.contact_email_campaign = ContactEmailCampaign.objects.create( - name="conta@admin", email="contactEmail@admin.com" - ) - - self.contact_email_campaign_1 = ContactEmailCampaign.objects.create( - name="another@admin", email="contactEmailAnother@admin.com" - ) - - self.campaign_log = CampaignLog.objects.create( - campaign=self.campaign, contact=self.contact_1 - ) - # connections.reload('default') - - # def tearDown(self): - # call_command('clear_index', interactive=False, verbosity=0) - - -@override_settings(HAYSTACK_CONNECTIONS=TEST_INDEX) -class TestTemplates(TestMarketingModel, TestCase): - - # def setUp(self): - # super(TestTemplates, self).setUp() - # connections.reload('default') - - def test_templates(self): - url1 = reverse("marketing:dashboard") - url2 = reverse("marketing:contact_lists") - url4 = reverse("marketing:contacts_list") - url5 = reverse("marketing:contact_list_new") - url8 = reverse("marketing:email_template_list") - url9 = reverse("marketing:email_template_new") - url12 = reverse("marketing:campaign_list") - url13 = reverse("marketing:campaign_new") - resp1 = self.client.get(url1) - resp2 = self.client.get(url2) - # resp4 = self.client.get(url4) - resp5 = self.client.get(url5) - resp8 = self.client.get(url8) - resp9 = self.client.get(url9) - # resp12 = self.client.get(url12) - resp13 = self.client.get(url13) - self.assertEqual(resp1.status_code, 200) - self.assertEqual(resp2.status_code, 200) - # self.assertEqual(resp4.status_code, 200) - self.assertEqual(resp5.status_code, 200) - self.assertEqual(resp8.status_code, 200) - self.assertEqual(resp9.status_code, 200) - # self.assertEqual(resp12.status_code, 200) - self.assertEqual(resp13.status_code, 200) - - -class TestCreateContacts(TestMarketingModel, TestCase): - def test_contact_list_new(self): - data = [ - "company name,email,first name,last name,city,state\n", - "mp,admin@mp,Admin,MP,Hyderabad,Telangana\n", - "mp,hrmp.com,HR,MP,Hyderabad,Telangana\n", - "mp,contactus@mp.com,,MP,Hyderabad,Telangana\n", - "mp,test@mp.com,Test,MP,Hyderabad,Telangana\n", - "mp,hello@mp.com,Hello,MP,Hyderabad,Telangana\n", - ] - - with open("marketing/test_file.csv", "w") as fp: - fp.writelines(data) - - with open("marketing/test_file.csv") as fp: - response = self.client.post( - reverse("marketing:contact_list_new"), - {"name": "sample_test", "attachment": fp}, - ) - self.assertEqual(response.status_code, 200) - - os.remove("marketing/test_file.csv") - - -class TestViewContactList(TestMarketingModel, TestCase): - - # def test_view_contact_list(self): - # ## ContactList create object first !!! - # response = self.client.get('/m/cl/list/1/detail/') - # self.assertEqual(response.status_code, 200) - # self.assertTemplateUsed(response, 'marketing/lists/detail.html') - - def test_contact_list_pagination(self): - response = self.client.get(reverse("marketing:contact_lists") + "?page=1") - self.assertEqual(response.status_code, 200) - - response = self.client.get(reverse("marketing:contact_lists") + "?page=asdf") - self.assertEqual(response.status_code, 200) - - response = self.client.get(reverse("marketing:contact_lists") + "?page=") - self.assertEqual(response.status_code, 200) - - -class TestEmailTemplateList(TestMarketingModel, TestCase): - def test_email_template_list_pagination(self): - response = self.client.get(reverse("marketing:email_template_list") + "?page=1") - self.assertEqual(response.status_code, 200) - - response = self.client.get( - reverse("marketing:email_template_list") + "?page=asdf" - ) - self.assertEqual(response.status_code, 200) - - response = self.client.get(reverse("marketing:email_template_list") + "?page=") - self.assertEqual(response.status_code, 200) - - -class TestDasboardView(TestMarketingModel, TestCase): - def test_marketing_dashboard(self): - self.client.login(username="john@example.com", password="password") - response = self.client.get(reverse("marketing:dashboard")) - self.assertEqual(response.status_code, 200) - - self.client.login(username="janeMarketing@example.com", password="password") - response = self.client.get(reverse("marketing:dashboard")) - self.assertEqual(response.status_code, 200) - - -@override_settings(HAYSTACK_CONNECTIONS=TEST_INDEX) -class TestContactListsListPage(TestMarketingModel, TestCase): - - # def setUp(self): - # super(TestContactListsListPage, self).setUp() - # # connections.reload('default') - - def test_contact_lists_list_page(self): - self.client.login(username="john@example.com", password="password") - response = self.client.get(reverse("marketing:contact_lists")) - self.assertEqual(response.status_code, 200) - - self.client.login(username="janeMarketing@example.com", password="password") - response = self.client.get( - reverse("marketing:contact_lists") + "?tag={}".format(self.tag_marketing.id) - ) - self.assertEqual(response.status_code, 200) - - data = { - "contact_list_name": "name of contact list", - "created_by": self.user1.id, - "tag": self.tag_marketing.id, - } - response = self.client.post(reverse("marketing:contact_lists"), data) - self.assertEqual(response.status_code, 200) - - -@override_settings(HAYSTACK_CONNECTIONS=TEST_INDEX) -class TestContactsListPage(TestMarketingModel, TestCase): - - # def setUp(self): - # super(TestContactsListPage, self).setUp() - # connections.reload('default') - # connections = ConnectionHandler(TEST_INDEX ) - - def test_contacts_list_page(self): - # connections.reload('default') - self.client.login(username="john@example.com", password="password") - response = self.client.get(reverse("marketing:contacts_list")) - self.assertEqual(response.status_code, 200) - - self.client.login(username="janeMarketing@example.com", password="password") - response = self.client.get(reverse("marketing:contacts_list")) - self.assertEqual(response.status_code, 200) - - data = { - "contact_name": "name of contact", - "created_by": self.user1.id, - "contact_email": "contact@email.com", - "contact_list": self.contact_list.id, - } - response = self.client.post(reverse("marketing:contacts_list"), data) - self.assertEqual(response.status_code, 200) - - -class TestContactsCSVFileUploadView(TestMarketingModel, TestCase): - def test_contacts_csv_file_upload_view(self): - self.client.login(username="john@example.com", password="password") - response = self.client.get(reverse("marketing:contact_list_new")) - self.assertEqual(response.status_code, 200) - - file_content = [ - "company name,email,first name,last name,city,state\n", - "company_name_1,user1@email.com,first_name,last_name,Hyderabad,Telangana\n", - "company_name_2,user2@email.com,first_name,last_name,Hyderabad,Telangana\n", - "company_name_3,user3@email.com,first_name,last_name,Hyderabad,Telangana\n", - "company_name_4,user4@email.com,first_name,last_name,Hyderabad,Telangana\n", - ] - file_content = bytes("".join(file_content), "utf-8") - data = { - "contacts_file": SimpleUploadedFile("file name", file_content), - "name": "contact file name", - "tags": "tag1,tag2,tag marketing", - } - response = self.client.post(reverse("marketing:contact_list_new"), data) - self.assertEqual(201, response.status_code) - - # invalid emails - file_content = [ - "company name,email,first name,last name,city,state\n", - "company_name_1,user1@email.com,first_name,last_name,Hyderabad,Telangana\n", - "company_name_2,useremail.com,first_name,last_name,Hyderabad,Telangana\n", - "company_name_3,user3@email.com,first_name,last_name,Hyderabad,Telangana\n", - "company_name_4,user5@email,first_name,last_name,Hyderabad,Telangana\n", - ] - file_content = bytes("".join(file_content), "utf-8") - data = { - "contacts_file": SimpleUploadedFile("file name", file_content), - "name": "contact file name", - "tags": "tag1,tag2,tag marketing", - } - response = self.client.post(reverse("marketing:contact_list_new"), data) - self.assertEqual(200, response.status_code) - - # missing email header - file_content = [ - "company name,first name,last name,city,state\n", - "company_name_1,user1@email.com,first_name,last_name,Hyderabad,Telangana\n", - "company_name_2,user2@email.com,first_name,last_name,Hyderabad,Telangana\n", - "company_name_3,user3@email.com,first_name,last_name,Hyderabad,Telangana\n", - "company_name_4,user4@email.com,first_name,last_name,Hyderabad,Telangana\n", - ] - file_content = bytes("".join(file_content), "utf-8") - data = { - "contacts_file": SimpleUploadedFile("file name", file_content), - "name": "contact file name", - "tags": "tag1,tag2,tag marketing", - } - response = self.client.post(reverse("marketing:contact_list_new"), data) - self.assertEqual(200, response.status_code) - - # missing all required headers - file_content = [ - "company_name_1,user1@email.com,first_name,last_name,Hyderabad,Telangana\n", - "company_name_2,user2@email.com,first_name,last_name,Hyderabad,Telangana\n", - "company_name_3,user3@email.com,first_name,last_name,Hyderabad,Telangana\n", - "company_name_4,user4@email.com,first_name,last_name,Hyderabad,Telangana\n", - ] - file_content = bytes("".join(file_content), "utf-8") - data = { - "contacts_file": SimpleUploadedFile("file name", file_content), - "name": "contact file name", - "tags": "tag1,tag2,tag marketing", - } - response = self.client.post(reverse("marketing:contact_list_new"), data) - self.assertEqual(200, response.status_code) - - -class TestEditContactsCSVFileUploadView(TestMarketingModel, TestCase): - def test_edit_contacts_csv_file_upload_view(self): - self.client.login(username="janeMarketing@example.com", password="password") - response = self.client.get( - reverse("marketing:edit_contact_list", args=(self.contact_list.id,)) - ) - self.assertEqual(response.status_code, 200) - - self.client.login(username="john@example.com", password="password") - response = self.client.get( - reverse("marketing:edit_contact_list", args=(self.contact_list.id,)) - ) - self.assertEqual(response.status_code, 200) - - file_content = [ - "company name,email,first name,last name,city,state\n", - "company_name_1,user1@email.com,first_name,last_name,Hyderabad,Telangana\n", - "company_name_2,user2@email.com,first_name,last_name,Hyderabad,Telangana\n", - "company_name_3,user3@email.com,first_name,last_name,Hyderabad,Telangana\n", - "company_name_4,user4@email.com,first_name,last_name,Hyderabad,Telangana\n", - ] - file_content = bytes("".join(file_content), "utf-8") - data = { - "contacts_file": SimpleUploadedFile("file name", file_content), - "name": "contacts_list by admin", - "tags": "tag1,tag2,tag marketing", - } - response = self.client.post( - reverse("marketing:edit_contact_list", args=(self.contact_list.id,)), data - ) - self.assertEqual(200, response.status_code) - data = {**data, "name": ""} - response = self.client.post( - reverse("marketing:edit_contact_list", args=(self.contact_list.id,)), data - ) - self.assertEqual(200, response.status_code) - - -class TestEditContact(TestMarketingModel, TestCase): - def test_edit_contact(self): - self.client.login(username="janeMarketing@example.com", password="password") - response = self.client.get( - reverse("marketing:edit_contact", args=(self.contact.id,)) - ) - self.assertEqual(response.status_code, 403) - - self.client.login(username="john@example.com", password="password") - response = self.client.get( - reverse("marketing:edit_contact", args=(self.contact.id,)) - ) - self.assertEqual(response.status_code, 200) - - data = {"name": "John DOE", "email": self.contact.email} - - response = self.client.post( - reverse("marketing:edit_contact", args=(self.contact.id,)), data - ) - self.assertEqual(response.status_code, 200) - - data = { - "name": "John DOE", - "email": self.contact.email, - "from_url": self.contact_list.id, - } - - response = self.client.post( - reverse("marketing:edit_contact", args=(self.contact.id,)), data - ) - self.assertEqual(response.status_code, 200) - - data = { - "name": "John DOE", - "email": self.contact_4.email, - "from_url": self.contact_list.id, - } - - response = self.client.post( - reverse("marketing:edit_contact", args=(self.contact.id,)), data - ) - self.assertEqual(response.status_code, 200) - - data = {"name": "John DOE", "email": ""} - - response = self.client.post( - reverse("marketing:edit_contact", args=(self.contact.id,)) - + "?from_url={}".format( - self.contact_list.id, - ), - data, - ) - self.assertEqual(response.status_code, 200) - - data = { - "name": "JAne DOE", - "email": "janeDoe@mark.com", - "from_url": self.contact_list.id, - } - - response = self.client.post( - reverse("marketing:edit_contact", args=(self.contact_1.id,)), data - ) - self.assertEqual(response.status_code, 200) - - -class TestDeleteContact(TestMarketingModel, TestCase): - def test_delete_contact(self): - self.client.login(username="janeMarketing@example.com", password="password") - response = self.client.get( - reverse("marketing:delete_contact", args=(self.contact.id,)) - ) - self.assertEqual(response.status_code, 403) - - self.client.login(username="john@example.com", password="password") - response = self.client.get( - reverse("marketing:delete_contact", args=(self.contact_2.id,)) - ) - self.assertEqual(response.status_code, 302) - - response = self.client.get( - reverse("marketing:delete_contact", args=(self.contact_3.id,)) - + "?from_contact={}".format(self.contact_list.id) - ) - self.assertEqual(response.status_code, 302) - - response = self.client.get( - reverse("marketing:delete_contact", args=(self.contact_4.id,)) - + "?from_contact={}".format(self.contact_list_user.id) - ) - self.assertEqual(response.status_code, 302) - - -class TestContactListDetail(TestMarketingModel, TestCase): - def test_contact_list_detail(self): - self.client.login(username="janeMarketing@example.com", password="password") - response = self.client.get( - reverse("marketing:contact_list_detail", args=(self.contact_list.id,)) - ) - self.assertEqual(response.status_code, 403) - - self.client.login(username="john@example.com", password="password") - response = self.client.get( - reverse("marketing:contact_list_detail", args=(self.contact_list.id,)) - ) - self.assertEqual(response.status_code, 200) - - data = { - "name": "contact name", - "email": "contact@email.com", - "company_name": "company name", - } - - response = self.client.post( - reverse("marketing:contact_list_detail", args=(self.contact_list.id,)), data - ) - self.assertEqual(response.status_code, 200) - - response = self.client.post( - reverse("marketing:contact_list_detail", args=(self.contact_list.id,)) - + "?bounced_contacts_page=0", - data, - ) - self.assertEqual(response.status_code, 200) - - # failed contacts detail test - # response = self.client.get( - # reverse('marketing:failed_contact_list_detail', args=(self.contact_list.id,))) - # self.assertEqual(response.status_code, 200) - - def test_failed_contact_list_download_delete(self): - response = self.client.get( - reverse( - "marketing:failed_contact_list_download_delete", - args=(self.contact_list.id,), - ) - ) - self.assertEqual(response.status_code, 200) - - response = self.client.get( - reverse( - "marketing:failed_contact_list_download_delete", - args=(self.contact_list_user.id,), - ) - ) - self.assertEqual(response.status_code, 302) - - def test_email_template_list(self): - response = self.client.get(reverse("marketing:email_template_list")) - self.assertEqual(response.status_code, 200) - - self.client.login(username="john@example.com", password="password") - response = self.client.get( - reverse("marketing:contact_list_detail", args=(self.contact_list.id,)) - ) - - self.assertEqual(response.status_code, 200) - data = { - "template_name": "template name", - "created_by": self.user.id, - } - - response = self.client.post(reverse("marketing:email_template_list"), data) - self.assertEqual(response.status_code, 200) - - self.client.login(username="janeMarketing@example.com", password="password") - response = self.client.get(reverse("marketing:email_template_list")) - self.assertEqual(response.status_code, 200) - - def test_email_template_create(self): - data = { - "title": "", - "subject": "", - "html": "", - } - self.client.login(username="john@example.com", password="password") - response = self.client.post(reverse("marketing:email_template_new"), data) - self.assertEqual(response.status_code, 200) - - data = { - "title": "title", - "subject": "subject", - "html": "html", - } - - response = self.client.post(reverse("marketing:email_template_new"), data) - self.assertEqual(response.status_code, 201) - - def test_email_edit(self): - data = { - "title": "", - "subject": "", - "html": "", - } - - response = self.client.get( - reverse("marketing:email_template_edit", args=(self.email_template.id,)), - data, - ) - self.assertEqual(response.status_code, 200) - - response = self.client.post( - reverse("marketing:email_template_edit", args=(self.email_template.id,)), - data, - ) - self.assertEqual(response.status_code, 200) - - data = { - "title": "title", - "subject": "subject", - "html": "html", - } - - response = self.client.post( - reverse("marketing:email_template_edit", args=(self.email_template.id,)), - data, - ) - self.assertEqual(response.status_code, 201) - - self.client.login(username="janeMarketing@example.com", password="password") - - data = { - "title": "title", - "subject": "subject", - "html": "html", - } - - response = self.client.post( - reverse("marketing:email_template_edit", args=(self.email_template.id,)), - data, - ) - self.assertEqual(response.status_code, 403) - - self.client.login(username="john@example.com", password="password") - response = self.client.get( - reverse("marketing:email_template_edit", args=(self.email_template.id,)) - ) - self.assertEqual(response.status_code, 200) - - def test_email_detail(self): - self.client.logout() - self.client.login(username="janeMarketing@example.com", password="password") - response = self.client.get( - reverse("marketing:email_template_detail", args=(self.email_template.id,)) - ) - self.assertEqual(response.status_code, 403) - - self.client.login(username="john@example.com", password="password") - response = self.client.get( - reverse("marketing:email_template_detail", args=(self.email_template.id,)) - ) - self.assertEqual(response.status_code, 200) - - def test_email_delete(self): - self.client.logout() - self.client.login(username="janeMarketing@example.com", password="password") - response = self.client.get( - reverse("marketing:email_template_delete", args=(self.email_template.id,)) - ) - self.assertEqual(response.status_code, 403) - - self.client.login(username="john@example.com", password="password") - response = self.client.get( - reverse("marketing:email_template_delete", args=(self.email_template.id,)) - ) - self.assertEqual(response.status_code, 302) - - def test_campaign_list(self): - self.client.login(username="janeMarketing@example.com", password="password") - response = self.client.get( - reverse("marketing:campaign_list") + "?tag={}".format(self.tag_marketing.id) - ) - self.assertEqual(response.status_code, 200) - - data = { - "campaign_name": "name of the campaign", - "created_by": self.user.id, - } - - response = self.client.post(reverse("marketing:campaign_list"), data) - self.assertEqual(response.status_code, 200) - - def test_campaign_new(self): - self.client.login(username="john@example.com", password="password") - response = self.client.get(reverse("marketing:campaign_new")) - self.assertEqual(response.status_code, 200) - - self.client.login(username="janeMarketing@example.com", password="password") - response = self.client.get(reverse("marketing:campaign_new")) - self.assertEqual(response.status_code, 200) - - data = { - "title": "campaign title", - "email_template": self.email_template.id, - "contact_list": self.contact_list.id, - "subject": "campaign subject", - "from_name": "from name", - "from_email": "from@email.com", - "reply_to_email": "noreply@example.com", - "tags": "tag,marketing,tag marketing,new tag create", - "timezone": "Asia/Kolkata", - "html": '

      html body


      message body


      links



      ', - } - - self.client.login(username="john@example.com", password="password") - response = self.client.post(reverse("marketing:campaign_new"), data) - self.assertEqual(response.status_code, 201) - - data = { - "title": "campaign title", - "email_template": self.email_template.id, - "contact_list": self.contact_list.id, - "subject": "campaign subject", - "from_name": "from name", - "from_email": "from@email.com", - "reply_to_email": "noreply@example.com", - "tags": "tag,marketing,tag marketing,new tag create", - "timezone": "Asia/Kolkata", - "schedule_later": "true", - "schedule_date_time": (datetime.now() + timedelta(days=2)).strftime( - "%Y-%m-%d %H:%M" - ), - "html": '

      html body


      message body


      links



      ', - } - - self.client.login(username="john@example.com", password="password") - response = self.client.post(reverse("marketing:campaign_new"), data) - self.assertEqual(response.status_code, 200) - - data = { - "title": "campaign title new", - "email_template": self.email_template.id, - "contact_list": self.contact_list.id, - "subject": "campaign subject", - "from_name": "from name", - "from_email": "from@email.com", - "reply_to_email": "noreply@example.com", - "tags": "tag,marketing,tag marketing,new tag create", - "timezone": "Asia/Kolkata", - "schedule_later": "true", - "schedule_date_time": (datetime.now() + timedelta(days=2)).strftime( - "%Y-%m-%d %H:%M" - ), - "reply_to_crm": "true", - "reply_to_email": "django@crm.com", - "html": '

      html body


      message body


      links



      ', - } - - self.client.login(username="john@example.com", password="password") - response = self.client.post(reverse("marketing:campaign_new"), data) - self.assertEqual(response.status_code, 201) - - data = { - **data, - "title": "wrong schedule date time", - "schedule_date_time": (datetime.now() - timedelta(days=10)).strftime( - "%Y-%m-%d %H:%M" - ), - "contact_list": self.contact_list_user_1.id, - "html": "{{}} {{", - } - self.client.login(username="john@example.com", password="password") - response = self.client.post(reverse("marketing:campaign_new"), data) - self.assertEqual(response.status_code, 200) - - data = { - **data, - "title": "wrong schedule date time", - "schedule_date_time": (datetime.now() - timedelta(days=10)).strftime( - "%Y-%m-%d %H:%M" - ), - "contact_list": self.contact_list_user_1.id, - "html": "}}", - } - self.client.login(username="john@example.com", password="password") - response = self.client.post(reverse("marketing:campaign_new"), data) - self.assertEqual(response.status_code, 200) - - def test_campaign_detail(self): - self.client.login(username="janeMarketing@example.com", password="password") - response = self.client.get( - reverse("marketing:campaign_details", args=(self.campaign.id,)) - ) - self.assertEqual(response.status_code, 403) - - self.client.login(username="john@example.com", password="password") - response = self.client.get( - reverse("marketing:campaign_details", args=(self.campaign.id,)) - ) - self.assertEqual(response.status_code, 200) - - response = self.client.get( - reverse("marketing:campaign_details", args=(self.campaign.id,)) + "?page=1" - ) - self.assertEqual(response.status_code, 200) - - response = self.client.get( - reverse("marketing:campaign_details", args=(self.campaign.id,)) - + "?page=None" - ) - self.assertEqual(response.status_code, 200) - - response = self.client.get( - reverse("marketing:campaign_details", args=(self.campaign.id,)) + "?page=" - ) - self.assertEqual(response.status_code, 200) - - def test_campaign_delete(self): - self.client.login(username="janeMarketing@example.com", password="password") - response = self.client.get( - reverse("marketing:campaign_delete", args=(self.campaign.id,)) - ) - self.assertEqual(response.status_code, 403) - - self.client.login(username="john@example.com", password="password") - response = self.client.get( - reverse("marketing:campaign_delete", args=(self.campaign.id,)) - ) - self.assertEqual(response.status_code, 302) - - def test_demo_file_download(self): - response = self.client.get(reverse("marketing:demo_file_download")) - self.assertEqual(response.status_code, 200) - - def test_unsubscribe_from_campaign(self): - response = self.client.get( - reverse( - "marketing:unsubscribe_from_campaign", - kwargs={ - "contact_id": self.contact.id, - "campaign_id": self.campaign.id, - }, - ) - ) - self.assertEqual(response.status_code, 200) - - def test_contact_detail(self): - self.client.login(username="janeMarketing@example.com", password="password") - response = self.client.get( - reverse("marketing:contact_detail", args=(self.contact.id,)) - ) - self.assertEqual(response.status_code, 403) - - self.client.login(username="john@example.com", password="password") - response = self.client.get( - reverse("marketing:contact_detail", args=(self.contact.id,)) - ) - self.assertEqual(response.status_code, 200) - - def test_download_contacts_for_campaign(self): - self.client.login(username="janeMarketing@example.com", password="password") - response = self.client.get( - reverse( - "marketing:download_contacts_for_campaign", args=(self.campaign.id,) - ) - ) - self.assertEqual(response.status_code, 403) - - self.client.login(username="john@example.com", password="password") - response = self.client.get( - reverse( - "marketing:download_contacts_for_campaign", args=(self.campaign.id,) - ) - + "?is_bounced=true" - ) - self.assertEqual(response.status_code, 200) - - response = self.client.get( - reverse( - "marketing:download_contacts_for_campaign", args=(self.campaign.id,) - ) - + "?is_unsubscribed=true" - ) - self.assertEqual(response.status_code, 200) - - response = self.client.get( - reverse( - "marketing:download_contacts_for_campaign", args=(self.campaign.id,) - ) - + "?is_opened=true" - ) - self.assertEqual(response.status_code, 200) - - def test_create_campaign_from_template(self): - response = self.client.get( - reverse( - "marketing:create_campaign_from_template", - args=(self.email_template.id,), - ) - ) - self.assertEqual(response.status_code, 302) - - def test_download_link_clicked(self): - response = self.client.get( - reverse("marketing:download_links_clicked", args=(self.campaign.id,)) - ) - self.assertEqual(response.status_code, 200) - - def test_delete_multiple_contacts(self): - data = { - "selected_list[]": [self.contact.id, self.contact_1.id], - "from_contact": self.contact_list.id, - } - self.client.login(username="janeMarketing@example.com", password="password") - response = self.client.post(reverse("marketing:delete_multiple_contacts"), data) - self.assertEqual(response.status_code, 200) - - self.client.login(username="john@example.com", password="password") - response = self.client.post(reverse("marketing:delete_multiple_contacts"), data) - self.assertEqual(response.status_code, 200) - - def test_delete_all_contacts(self): - self.client.login(username="janeMarketing@example.com", password="password") - response = self.client.get( - reverse("marketing:delete_all_contacts", args=(self.contact_list.id,)) - ) - self.assertEqual(response.status_code, 403) - - self.client.login(username="john@example.com", password="password") - response = self.client.get( - reverse("marketing:delete_all_contacts", args=(self.contact_list.id,)) - ) - self.assertEqual(response.status_code, 302) - - self.client.login(username="john@example.com", password="password") - response = self.client.get( - reverse("marketing:delete_all_contacts", args=(self.contact_list.id,)) - + "?bounced=true" - ) - self.assertEqual(response.status_code, 302) - - def test_download_failed_contacts(self): - self.client.login(username="janeMarketing@example.com", password="password") - response = self.client.get( - reverse("marketing:download_failed_contacts", args=(self.contact_list.id,)) - ) - self.assertEqual(response.status_code, 403) - - self.client.login(username="john@example.com", password="password") - response = self.client.get( - reverse("marketing:download_failed_contacts", args=(self.contact_list.id,)) - ) - self.assertEqual(response.status_code, 200) - - response = self.client.get( - reverse( - "marketing:download_failed_contacts", - args=(self.contact_list_user_1.id,), - ) - ) - self.assertEqual(response.status_code, 200) - - def test_list_all_email_for_campaigns(self): - self.client.login(username="john@example.com", password="password") - response = self.client.get(reverse("marketing:list_all_emails_for_campaigns")) - self.assertEqual(response.status_code, 200) - - def test_add_email_for_campaigns(self): - self.client.login(username="john@example.com", password="password") - response = self.client.get(reverse("marketing:add_email_for_campaigns")) - self.assertEqual(response.status_code, 200) - - data = {} - - response = self.client.post(reverse("marketing:add_email_for_campaigns"), data) - self.assertEqual(response.status_code, 200) - - data = {"name": "admin name", "email": "admin@email.com"} - - response = self.client.post(reverse("marketing:add_email_for_campaigns"), data) - self.assertEqual(response.status_code, 200) - - def test_edit_email_for_campaigns(self): - self.client.login(username="john@example.com", password="password") - response = self.client.get( - reverse( - "marketing:edit_email_for_campaigns", - args=(self.contact_email_campaign.id,), - ) - ) - self.assertEqual(response.status_code, 200) - - data = {} - - response = self.client.post( - reverse( - "marketing:edit_email_for_campaigns", - args=(self.contact_email_campaign.id,), - ), - data, - ) - self.assertEqual(response.status_code, 200) - - data = {"name": "admin name", "email": "adminContact@email.com"} - - response = self.client.post( - reverse( - "marketing:edit_email_for_campaigns", - args=(self.contact_email_campaign.id,), - ), - data, - ) - self.assertEqual(response.status_code, 200) - - data = { - "name": "admin name", - "email": self.contact_email_campaign_1.email, - } - - response = self.client.post( - reverse( - "marketing:edit_email_for_campaigns", - args=(self.contact_email_campaign.id,), - ), - data, - ) - self.assertEqual(response.status_code, 200) - - def test_delete_email_for_campaigns(self): - self.client.login(username="john@example.com", password="password") - response = self.client.get( - reverse( - "marketing:delete_email_for_campaigns", - args=(self.contact_email_campaign.id,), - ) - ) - self.assertEqual(response.status_code, 302) - - -class TestContactListFileUploadForXlsxAndXls(TestMarketingModel, TestCase): - def test_contact_list_file_upload_for_xlsx(self): - self.client.login(username="john@example.com", password="password") - response = self.client.get(reverse("marketing:contact_list_new")) - self.assertEqual(response.status_code, 200) - - file_headers = [ - "company name", - "email", - "first name", - "last name", - "city", - "state", - ] - file_content = [ - [ - "company_name_1", - "user1@email.com", - "first_name", - "last_name", - "Hyderabad", - "Telangana", - ], - [ - "company_name_2", - "user2@email.com", - "first_name", - "last_name", - "Hyderabad", - "Telangana", - ], - [ - "company_name_3", - "user3@email.com", - "first_name", - "last_name", - "Hyderabad", - "Telangana", - ], - [ - "company_name_4", - "user4@email.com", - "first_name", - "last_name", - "Hyderabad", - "Telangana", - ], - ] - wb = openpyxl.workbook.Workbook() - dest_filename = "marketing/test_1.xlsx" - ws1 = wb.active - ws1.title = "test xlsx files" - ws1.append(file_headers) - for row in file_content: - ws1.append(row) - wb.save(filename=dest_filename) - with open(dest_filename, "rb") as fp: - data = {"name": "sample_test xlsx", "contacts_file": fp, "tags": ""} - response = self.client.post(reverse("marketing:contact_list_new"), data) - self.assertEqual(response.status_code, 201) - os.remove(dest_filename) - - # missing email header - file_headers = ["company name", "first name", "last name", "city", "state"] - file_content = [ - [ - "company_name_1", - "user1@email.com", - "first_name", - "last_name", - "Hyderabad", - "Telangana", - ], - [ - "company_name_2", - "user2@email.com", - "first_name", - "last_name", - "Hyderabad", - "Telangana", - ], - [ - "company_name_3", - "user3@email.com", - "first_name", - "last_name", - "Hyderabad", - "Telangana", - ], - [ - "company_name_4", - "user4@email.com", - "first_name", - "last_name", - "Hyderabad", - "Telangana", - ], - ] - - wb = openpyxl.workbook.Workbook() - dest_filename = "marketing/test_1.xlsx" - ws1 = wb.active - ws1.title = "test xlsx files" - ws1.append(file_headers) - for row in file_content: - ws1.append(row) - wb.save(filename=dest_filename) - with open(dest_filename, "rb") as fp: - data = {"name": "sample_test xlsx", "contacts_file": fp, "tags": ""} - response = self.client.post(reverse("marketing:contact_list_new"), data) - self.assertEqual(response.status_code, 200) - os.remove(dest_filename) - - # missing all headers - file_headers = [] - file_content = [ - [ - "company_name_1", - "user1@email.com", - "first_name", - "last_name", - "Hyderabad", - "Telangana", - ], - [ - "company_name_2", - "user2@email.com", - "first_name", - "last_name", - "Hyderabad", - "Telangana", - ], - [ - "company_name_3", - "user3@email.com", - "first_name", - "last_name", - "Hyderabad", - "Telangana", - ], - [ - "company_name_4", - "user4@email.com", - "first_name", - "last_name", - "Hyderabad", - "Telangana", - ], - ] - - wb = openpyxl.workbook.Workbook() - dest_filename = "marketing/test_1.xlsx" - ws1 = wb.active - ws1.title = "test xlsx files" - ws1.append(file_headers) - for row in file_content: - ws1.append(row) - wb.save(filename=dest_filename) - with open(dest_filename, "rb") as fp: - data = {"name": "sample_test xlsx", "contacts_file": fp, "tags": ""} - response = self.client.post(reverse("marketing:contact_list_new"), data) - self.assertEqual(response.status_code, 200) - os.remove(dest_filename) - - # invalid emails - file_headers = [ - "company name", - "email", - "first name", - "last name", - "city", - "state", - ] - file_content = [ - [ - "company_name_1", - "user1.com", - "first_name", - "last_name", - "Hyderabad", - "Telangana", - ], - [ - "company_name_3", - "user5@email", - "first_name", - "last_name", - "Hyderabad", - "Telangana", - ], - ] - wb = openpyxl.workbook.Workbook() - dest_filename = "marketing/test_1.xlsx" - ws1 = wb.active - ws1.title = "test xlsx files" - ws1.append(file_headers) - for row in file_content: - ws1.append(row) - wb.save(filename=dest_filename) - with open(dest_filename, "rb") as fp: - data = {"name": "sample_test xlsx", "contacts_file": fp, "tags": ""} - response = self.client.post(reverse("marketing:contact_list_new"), data) - self.assertEqual(response.status_code, 200) - - os.remove(dest_filename) - - def test_contact_list_file_upload_for_xls(self): - self.client.login(username="john@example.com", password="password") - response = self.client.get(reverse("marketing:contact_list_new")) - self.assertEqual(response.status_code, 200) - - file_headers = [ - "company name", - "email", - "first name", - "last name", - "city", - "state", - ] - file_content = [ - [ - "company_name_1", - "user1@email.com", - "first_name", - "last_name", - "Hyderabad", - "Telangana", - ], - [ - "company_name_2", - "user2@email.com", - "first_name", - "last_name", - "Hyderabad", - "Telangana", - ], - [ - "company_name_3", - "user3@email.com", - "first_name", - "last_name", - "Hyderabad", - "Telangana", - ], - [ - "company_name_4", - "user4@email.com", - "first_name", - "last_name", - "Hyderabad", - "Telangana", - ], - ] - - dest_filename = "test_1.xls" - wb = xlwt.Workbook() - ws = wb.add_sheet("test xls") - for count, row in enumerate(file_headers): - ws.write(0, count, row) - - col_location = 1 - for row in file_content: - for count_row_content, row_content in enumerate(row): - ws.write(col_location, count_row_content, row_content) - col_location = col_location + 1 - wb.save(dest_filename) - - with open(dest_filename, "rb") as fp: - data = {"name": "sample_test xls", "contacts_file": fp, "tags": ""} - response = self.client.post(reverse("marketing:contact_list_new"), data) - self.assertEqual(response.status_code, 201) - os.remove(dest_filename) - - # missing email headers - file_headers = ["company name", "first name", "last name", "city", "state"] - file_content = [ - [ - "company_name_1", - "user1@email.com", - "first_name", - "last_name", - "Hyderabad", - "Telangana", - ], - [ - "company_name_2", - "user2@email.com", - "first_name", - "last_name", - "Hyderabad", - "Telangana", - ], - [ - "company_name_3", - "user3@email.com", - "first_name", - "last_name", - "Hyderabad", - "Telangana", - ], - [ - "company_name_4", - "user4@email.com", - "first_name", - "last_name", - "Hyderabad", - "Telangana", - ], - ] - - dest_filename = "test_1.xls" - wb = xlwt.Workbook() - ws = wb.add_sheet("test xls") - for count, row in enumerate(file_headers): - ws.write(0, count, row) - - col_location = 1 - for row in file_content: - for count_row_content, row_content in enumerate(row): - ws.write(col_location, count_row_content, row_content) - col_location = col_location + 1 - wb.save(dest_filename) - - with open(dest_filename, "rb") as fp: - data = {"name": "sample_test xls", "contacts_file": fp, "tags": ""} - response = self.client.post(reverse("marketing:contact_list_new"), data) - self.assertEqual(response.status_code, 200) - os.remove(dest_filename) - - # missing headers - file_headers = [] - file_content = [ - [ - "company_name_1", - "user1@email.com", - "first_name", - "last_name", - "Hyderabad", - "Telangana", - ], - [ - "company_name_2", - "user2@email.com", - "first_name", - "last_name", - "Hyderabad", - "Telangana", - ], - [ - "company_name_3", - "user3@email.com", - "first_name", - "last_name", - "Hyderabad", - "Telangana", - ], - [ - "company_name_4", - "user4@email.com", - "first_name", - "last_name", - "Hyderabad", - "Telangana", - ], - ] - - dest_filename = "test_1.xls" - wb = xlwt.Workbook() - ws = wb.add_sheet("test xls") - for count, row in enumerate(file_headers): - ws.write(0, count, row) - - col_location = 1 - for row in file_content: - for count_row_content, row_content in enumerate(row): - ws.write(col_location, count_row_content, row_content) - col_location = col_location + 1 - wb.save(dest_filename) - - with open(dest_filename, "rb") as fp: - data = {"name": "sample_test xls", "contacts_file": fp, "tags": ""} - response = self.client.post(reverse("marketing:contact_list_new"), data) - self.assertEqual(response.status_code, 200) - os.remove(dest_filename) - - # invalid emails - file_headers = [ - "company name", - "email", - "first name", - "last name", - "city", - "state", - ] - file_content = [ - [ - "company_name_1", - "user5@email", - "first_name", - "last_name", - "Hyderabad", - "Telangana", - ], - [ - "company_name_2", - "user6.com", - "first_name", - "last_name", - "Hyderabad", - "Telangana", - ], - ] - - dest_filename = "test_1.xls" - wb = xlwt.Workbook() - ws = wb.add_sheet("test xls") - for count, row in enumerate(file_headers): - ws.write(0, count, row) - - col_location = 1 - for row in file_content: - for count_row_content, row_content in enumerate(row): - ws.write(col_location, count_row_content, row_content) - col_location = col_location + 1 - wb.save(dest_filename) - - with open(dest_filename, "rb") as fp: - data = {"name": "sample_test xls", "contacts_file": fp, "tags": ""} - response = self.client.post(reverse("marketing:contact_list_new"), data) - self.assertEqual(response.status_code, 200) - os.remove(dest_filename) - - -class TestCampaignLinkClick(TestMarketingModel, TestCase): - def test_campaign_link_click(self): - self.client.login(username="john@example.com", password="password") - response = self.client.get( - reverse( - "marketing:campaign_link_click", - kwargs={ - "link_id": self.link.id, - "email_id": self.contact_1.id, - }, - ) - ) - self.assertEqual(response.status_code, 302) - - response = self.client.get( - reverse( - "marketing:campaign_link_click", - kwargs={ - "link_id": self.link.id, - "email_id": self.contact_1.id, - }, - ) - ) - self.assertEqual(response.status_code, 302) - - response = self.client.get( - reverse( - "marketing:campaign_link_click", - kwargs={ - "link_id": self.link.id, - "email_id": self.contact_email_campaign.id, - }, - ) - ) - self.assertEqual(response.status_code, 302) - - def test_campaign_open(self): - self.client.login(username="john@example.com", password="password") - response = self.client.get( - reverse( - "marketing:campaign_open", - kwargs={ - "campaign_log_id": self.campaign.id, - "email_id": self.contact_1.id, - }, - ) - ) - self.assertEqual(response.status_code, 200) - - self.client.login(username="john@example.com", password="password") - response = self.client.get( - reverse( - "marketing:campaign_open", - kwargs={ - "campaign_log_id": self.campaign.id, - "email_id": self.contact_1.id, - }, - ) - ) - self.assertEqual(response.status_code, 200) - - -class TestMarketingModelMethods(TestMarketingModel, TestCase): - def test_marketing_model_methods(self): - self.assertEqual(self.tag_marketing.created_by, self.user) - self.assertEqual(self.tag_marketing_1.created_by, None) - self.assertEqual(self.email_template.created_by_user, self.user) - self.assertEqual(self.contact_list.created_by_user, self.user) - self.assertTrue(self.tag_marketing in self.contact_list.tags_data) - self.assertEqual(self.contact_list.no_of_contacts, 4) - self.assertEqual(self.contact_list.no_of_campaigns, 1) - self.assertEqual(self.contact_list.unsubscribe_contacts, 0) - # self.assertTrue( - # self.contact_list.created_on_arrow in ["just now", "seconds ago"] - # ) - self.assertEqual(str(self.contact), self.contact.email) - self.assertEqual(str(self.failed_contact), self.failed_contact.email) - self.assertEqual(self.campaign.no_of_clicks, 0) - self.assertEqual( - self.campaign.sent_on_format, - self.campaign.created_on.strftime("%b %d, %Y %I:%M %p"), - ) - self.assertEqual( - self.contact_list.created_on_format, - self.contact_list.created_on.strftime("%b %d, %Y %I:%M %p"), - ) - # self.assertTrue(self.campaign.sent_on_arrow in ["just now", "seconds ago"]) - # self.assertEqual(self.campaign_scheduled_later.sent_on_format, - # datetime.strptime(self.campaign_scheduled_later.schedule_date_time, '%Y-%m-%d %H:%M' - # ).strftime('%b %d, %Y %I:%M %p')) diff --git a/marketing/tests_celery_tasks.py b/marketing/tests_celery_tasks.py deleted file mode 100644 index bca450d..0000000 --- a/marketing/tests_celery_tasks.py +++ /dev/null @@ -1,124 +0,0 @@ -from datetime import datetime, timedelta - -from django.test import TestCase -from django.test.utils import override_settings - -from marketing.tasks import ( - delete_multiple_contacts_tasks, - list_all_bounces_unsubscribes, - run_all_campaigns, - run_campaign, - send_campaign_email_to_admin_contact, - send_scheduled_campaigns, - upload_csv_file, -) -from marketing.tests import TestMarketingModel - - -class TestCeleryTasks(TestMarketingModel, TestCase): - @override_settings( - CELERY_EAGER_PROPAGATES_EXCEPTIONS=True, - CELERY_ALWAYS_EAGER=True, - BROKER_BACKEND="memory", - ) - def test_celery_tasks(self): - task = run_campaign.apply( - (self.campaign.id,), - ) - self.assertEqual("SUCCESS", task.state) - - self.campaign.reply_to_email = None - self.campaign.save() - - task = run_campaign.apply( - (self.campaign.id,), - ) - self.assertEqual("SUCCESS", task.state) - - self.campaign.schedule_date_time = datetime.now() - self.campaign.save() - - task = run_all_campaigns.apply() - self.assertEqual("SUCCESS", task.state) - - task = list_all_bounces_unsubscribes.apply() - self.assertEqual("SUCCESS", task.state) - - task = send_scheduled_campaigns.apply() - self.assertEqual("SUCCESS", task.state) - - task = delete_multiple_contacts_tasks.apply( - (self.contact_list.id,), - ) - self.assertEqual("SUCCESS", task.state) - - task = send_campaign_email_to_admin_contact.apply( - (self.campaign.id,), - ) - self.assertEqual("SUCCESS", task.state) - - valid_rows = [ - { - "company name": "company_name_1", - "email": "user1@email.com", - "first name": "first_name", - "last name": "last_name", - "city": "Hyderabad", - "state": "Telangana", - }, - { - "company name": "company_name_2", - "email": "user2@email.com", - "first name": "first_name", - "last name": "last_name", - "city": "Hyderabad", - "state": "Telangana", - }, - { - "company name": "company_name_3", - "email": "user3@email.com", - "first name": "first_name", - "last name": "last_name", - "city": "Hyderabad", - "state": "Telangana", - }, - { - "company name": "company_name_4", - "email": "user4@email.com", - "first name": "first_name", - "last name": "last_name", - "city": "Hyderabad", - "state": "Telangana", - }, - ] - - invalid_rows = [ - { - "company name": "company_name_1", - "email": "useremail.com", - "first name": "first_name", - "last name": "last_name", - "city": "Hyderabad", - "state": "Telangana", - }, - { - "company name": "company_name_2", - "email": "user2@email", - "first name": "first_name", - "last name": "last_name", - "city": "Hyderabad", - "state": "Telangana", - }, - ] - task = upload_csv_file.apply( - ( - valid_rows, - invalid_rows, - self.user.id, - [ - self.contact_list.id, - ], - self.company.id, - ), - ) - self.assertEqual("SUCCESS", task.state) diff --git a/marketing/urls.py b/marketing/urls.py deleted file mode 100644 index 9f8b671..0000000 --- a/marketing/urls.py +++ /dev/null @@ -1,196 +0,0 @@ -from django.urls import path, include -from .views import ( - dashboard, - contact_lists, - contacts_list, - contact_list_new, - contact_list_detail, - edit_contact, - email_template_list, - email_template_new, - email_template_edit, - email_template_delete, - email_template_detail, - campaign_list, - campaign_new, - campaign_details, - campaign_delete, - edit_contact_list, - failed_contact_list_download_delete, - campaign_link_click, - campaign_open, - demo_file_download, - delete_contact, - unsubscribe_from_campaign, - contact_detail, - download_contacts_for_campaign, - create_campaign_from_template, - download_links_clicked, - delete_multiple_contacts, - download_failed_contacts, - delete_all_contacts, - add_email_for_campaigns, - list_all_emails_for_campaigns, - edit_email_for_campaigns, - delete_email_for_campaigns, - add_blocked_domain, - blocked_domain_list, - edit_blocked_domain, - delete_blocked_domain, - add_blocked_email, - blocked_email_list, - edit_blocked_email, - delete_blocked_email, - contacts_list_elastic_search, - # MarketingContactEmailSearch, - # contacts_list_new - # delete_contact_list - # campaign_edit - # edit_failed_contact - # delete_failed_contact - # failed_contact_list_detail -) - -app_name = "marketing" - -urlpatterns = [ - path("", dashboard, name="dashboard"), - path("contact-list/", contact_lists, name="contact_lists"), - path("contacts//edit/", edit_contact, name="edit_contact"), - path("contacts//delete/", delete_contact, name="delete_contact"), - path("contacts/", contacts_list_elastic_search, name="contacts_list"), - path("contact-list/create/", contact_list_new, name="contact_list_new"), - # path('cl/list/cnew/', contacts_list_new, name='contacts_list_new'), - path( - "contact-list//detail/", contact_list_detail, name="contact_list_detail" - ), - # path('contact-list//failed/', failed_contact_list_detail, name='failed_contact_list_detail'), - # path('contact-list//failed/edit/', edit_failed_contact, name='edit_failed_contact'), - # path('contact-list//failed/delete/', delete_failed_contact, name='delete_failed_contact'), - path( - "contact-list//failed/download/", - failed_contact_list_download_delete, - name="failed_contact_list_download_delete", - ), - path("contact-list//edit/", edit_contact_list, name="edit_contact_list"), - # path('cl/list//delete/', delete_contact_list, name='delete_contact_list'), - path("email-templates/", email_template_list, name="email_template_list"), - path("email-templates/create/", email_template_new, name="email_template_new"), - path( - "email-templates//edit/", - email_template_edit, - name="email_template_edit", - ), - path( - "email-templates//detail/", - email_template_detail, - name="email_template_detail", - ), - path( - "email-templates//delete/", - email_template_delete, - name="email_template_delete", - ), - path("campaigns/", campaign_list, name="campaign_list"), - path("campaigns/create/", campaign_new, name="campaign_new"), - # path('cm//edit/', campaign_edit, name='campaign_edit'), - path("campaigns//details/", campaign_details, name="campaign_details"), - path("campaigns//delete/", campaign_delete, name="campaign_delete"), - path( - "cm/link//e//", - campaign_link_click, - name="campaign_link_click", - ), - path( - "cm/track-email//contact//", - campaign_open, - name="campaign_open", - ), - path( - "demo-file-download-for-contacts-list/", - demo_file_download, - name="demo_file_download", - ), - path( - "unsubscribe-from-campaign///", - unsubscribe_from_campaign, - name="unsubscribe_from_campaign", - ), - path("contacts//view/", contact_detail, name="contact_detail"), - path( - "download-contacts-for-campaign//", - download_contacts_for_campaign, - name="download_contacts_for_campaign", - ), - path( - "create-campaign-from-template//", - create_campaign_from_template, - name="create_campaign_from_template", - ), - path( - "download-links-clicked//", - download_links_clicked, - name="download_links_clicked", - ), - path( - "delete_multiple_contacts/", - delete_multiple_contacts, - name="delete_multiple_contacts", - ), - path( - "download-failed-contacts//", - download_failed_contacts, - name="download_failed_contacts", - ), - path( - "delete_all_contacts//", - delete_all_contacts, - name="delete_all_contacts", - ), - path( - "add-email-for-campaigns/", - add_email_for_campaigns, - name="add_email_for_campaigns", - ), - path( - "list-all-emails-for-campaigns/", - list_all_emails_for_campaigns, - name="list_all_emails_for_campaigns", - ), - path( - "edit-email-for-campaigns//", - edit_email_for_campaigns, - name="edit_email_for_campaigns", - ), - path( - "delete-email-for-campaigns//", - delete_email_for_campaigns, - name="delete_email_for_campaigns", - ), - path("add-blocked-domain/", add_blocked_domain, name="add_blocked_domain"), - path("blocked-domain-list/", blocked_domain_list, name="blocked_domain_list"), - path( - "edit-blocked-domain//", - edit_blocked_domain, - name="edit_blocked_domain", - ), - path( - "delete-blocked-domain//", - delete_blocked_domain, - name="delete_blocked_domain", - ), - path("add-blocked-email/", add_blocked_email, name="add_blocked_email"), - path("blocked-email-list/", blocked_email_list, name="blocked_email_list"), - path( - "edit-blocked-email//", - edit_blocked_email, - name="edit_blocked_email", - ), - path( - "delete-blocked-email//", - delete_blocked_email, - name="delete_blocked_email", - ), - # path('search-marketing-contact-emails/', include('haystack.urls')), - # path('elastic-search/', contacts_list_elastic_search), -] diff --git a/marketing/views.py b/marketing/views.py deleted file mode 100644 index a95ad1d..0000000 --- a/marketing/views.py +++ /dev/null @@ -1,1737 +0,0 @@ -import csv -import json -from datetime import datetime as ddatetime - -import lxml -import lxml.html -import pytz -from django.conf import settings -from django.contrib.auth.decorators import login_required -from django.core.exceptions import PermissionDenied -from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator -from django.db.models import Q -from django.http.response import HttpResponse, HttpResponseRedirect, JsonResponse -from django.shortcuts import get_object_or_404, redirect, render -from django.urls import reverse, reverse_lazy -from lxml.cssselect import CSSSelector - -from common import status -from common.utils import convert_to_custom_timezone -from common.models import User -from marketing.forms import ( - ContactForm, - ContactListForm, - EmailTemplateForm, - SendCampaignForm, - EmailCampaignForm, - BlockedDomainsForm, - BlockedEmailForm, -) -from marketing.models import ( - Campaign, - CampaignLinkClick, - CampaignLog, - CampaignOpen, - Contact, - ContactList, - EmailTemplate, - Link, - Tag, - FailedContact, - ContactUnsubscribedCampaign, - ContactEmailCampaign, - BlockedDomain, - BlockedEmail, -) -from marketing.tasks import ( - run_campaign, - upload_csv_file, - delete_multiple_contacts_tasks, - send_campaign_email_to_admin_contact, - update_elastic_search_index, -) -from common.access_decorators_mixins import ( - marketing_access_required, - MarketingAccessRequiredMixin, - admin_login_required, -) - -# from haystack.generic_views import SearchView -# from haystack.query import SearchQuerySet - -TIMEZONE_CHOICES = [(tz, tz) for tz in pytz.common_timezones] - - -# def get_exact_match(query, m2m_field, ids): -# # query = tasks_list.annotate(count=Count(m2m_field))\ -# # .filter(count=len(ids)) -# query = query -# for _id in ids: -# query = query.filter(**{m2m_field: _id}) -# return query - - -@login_required(login_url="/login") -@marketing_access_required -def dashboard(request): - if request.user.role == "ADMIN" or request.user.is_superuser: - email_templates = EmailTemplate.objects.filter(company=request.company) - contacts = Contact.objects.filter(company=request.company) - campaign = Campaign.objects.filter(company=request.company) - contacts_list = ContactList.objects.filter(company=request.company) - else: - email_templates = EmailTemplate.objects.filter(created_by=request.user) - contacts = Contact.objects.filter(created_by=request.user) - campaign = Campaign.objects.filter(created_by=request.user) - contacts_list = ContactList.objects.filter(created_by=request.user) - - # x_axis_titles = [ - # campaign_obj.title for campaign_obj in campaign[:5]] - x_axis_titles = [ - campaign_obj.title[0:10] + "..." - if len(campaign_obj.title) > 15 - else campaign_obj.title - for campaign_obj in campaign[:5] - ] - y_axis_bounces = [ - campaign_obj.get_all_email_bounces_count for campaign_obj in campaign[:5] - ] - y_axis_unsubscribed = [ - campaign_obj.get_all_emails_unsubscribed_count for campaign_obj in campaign[:5] - ] - y_axis_subscribed = [ - campaign_obj.get_all_emails_subscribed_count for campaign_obj in campaign[:5] - ] - y_axis_opened = [ - campaign_obj.get_all_emails_contacts_opened for campaign_obj in campaign[:5] - ] - - context = { - "email_templates": email_templates, - "contacts": contacts, - "campaigns": campaign, - "contacts_list": contacts_list, - "y_axis_subscribed": y_axis_subscribed, - "y_axis_unsubscribed": y_axis_unsubscribed, - "y_axis_bounces": y_axis_bounces, - "y_axis_opened": y_axis_opened, - "x_axis_titles": x_axis_titles, - } - return render(request, "marketing/dashboard.html", context) - - -@login_required(login_url="/login") -@marketing_access_required -def contact_lists(request): - tags = Tag.objects.filter(company=request.company) - if request.user.role == "ADMIN": - queryset = ContactList.objects.filter(company=request.company).order_by( - "-created_on" - ) - else: - queryset = ContactList.objects.filter( - Q(created_by=request.user) | Q(visible_to=request.user) - ).order_by("-created_on") - - users = User.objects.filter(id__in=queryset.values_list("created_by_id", flat=True)) - if request.GET.get("tag"): - queryset = queryset.filter(tags=request.GET.get("tag")) - search = False - if request.method == "POST": - post_tags = request.POST.getlist("tag") - - if request.POST.get("contact_list_name"): - queryset = queryset.filter( - name__icontains=request.POST.get("contact_list_name") - ) - - if request.POST.get("created_by"): - queryset = queryset.filter(created_by=request.POST.get("created_by")) - - if request.POST.get("tag"): - queryset = queryset.filter(tags__id__in=post_tags) - request_tags = request.POST.getlist("tag") - if ( - request.POST.get("contact_list_name") - or request.POST.get("created_by") - or request.POST.get("created_by") - ): - search = True # for filter form to show in contactlist - - data = { - "contact_lists": queryset, - "tags": tags, - "users": users, - "request_tags": request.POST.getlist("tag"), - "search": search, - } - return render(request, "marketing/lists/index.html", data) - - -@login_required(login_url="/login") -@marketing_access_required -def contacts_list(request): - if request.user.role == "ADMIN": - contacts = Contact.objects.filter(company=request.company) - contact_lists = ContactList.objects.filter(company=request.company) - else: - contact_ids = request.user.marketing_contactlist.all().values_list( - "contacts", flat=True - ) - contacts = Contact.objects.filter(id__in=contact_ids) - contact_lists = ContactList.objects.filter(created_by=request.user) - # contacts = Contact.objects.filter(created_by=request.user) - users = User.objects.filter(id__in=contacts.values_list("created_by_id", flat=True)) - - if request.method == "GET": - context = {"contacts": contacts, "users": users, "contact_lists": contact_lists} - return render(request, "marketing/lists/all.html", context) - - if request.method == "POST": - data = request.POST - if data.get("contact_name"): - contacts = contacts.filter(name__icontains=data.get("contact_name")) - - if data.get("contact_email"): - contacts = contacts.filter(email__icontains=data.get("contact_email")) - - if data.get("created_by"): - contacts = contacts.filter(created_by=data.get("created_by")) - - if data.get("contact_list"): - contacts = contacts.filter(contact_list=data.get("contact_list")) - - context = { - "contacts": contacts, - "users": User.objects.filter(company=request.company), - "contact_lists": contact_lists, - } - return render(request, "marketing/lists/all.html", context) - - -@login_required(login_url="/login") -@marketing_access_required -def contact_list_new(request): - data = {} - if request.method == "POST": - form = ContactListForm(request.POST, request.FILES) - if form.is_valid(): - instance = form.save(commit=False) - instance.created_by = request.user - instance.company = request.company - instance.save() - tags = request.POST["tags"].split(",") if request.POST["tags"] else [] - for each in tags: - tag, _ = Tag.objects.get_or_create( - name=each, created_by=request.user, company=request.company - ) - instance.tags.add(tag) - if request.FILES.get("contacts_file"): - upload_csv_file.delay( - form.validated_rows, - form.invalid_rows, - request.user.id, - [instance.id], - request.company.id, - ) - - return JsonResponse( - {"error": False, "data": form.data}, status=status.HTTP_201_CREATED - ) - else: - # return JsonResponse({'error': True, 'errors': form.errors}, - # status=status.HTTP_400_BAD_REQUEST) - return JsonResponse( - {"error": True, "errors": form.errors}, status=status.HTTP_200_OK - ) - else: - return render(request, "marketing/lists/new.html", data) - - -@login_required(login_url="/login") -@marketing_access_required -def edit_contact_list(request, pk): - user = request.user - contact_list = get_object_or_404(ContactList, pk=pk) - if request.method == "GET": - # contact_lists = ContactList.objects.filter(company=request.company) - if user.is_superuser or request.user.role == "ADMIN": - contact_lists = ContactList.objects.filter(company=request.company) - else: - contact_lists = ContactList.objects.filter(created_by=request.user) - - data = {"contact_list": contact_list, "contact_lists": contact_lists} - return render(request, "marketing/lists/new.html", data) - else: - form = ContactListForm(request.POST, request.FILES, instance=contact_list) - if form.is_valid(): - instance = form.save() - instance.tags.clear() - tags = request.POST["tags"].split(",") if request.POST["tags"] else [] - for each in tags: - tag, _ = Tag.objects.get_or_create( - name=each, created_by=request.user, company=request.company - ) - instance.tags.add(tag) - if request.FILES.get("contacts_file"): - upload_csv_file.delay( - form.validated_rows, - form.invalid_rows, - request.user.id, - [instance.id], - request.company.id, - ) - - return JsonResponse( - {"error": False, "data": form.data}, status=status.HTTP_200_OK - ) - return JsonResponse( - {"error": True, "errors": form.errors}, status=status.HTTP_200_OK - ) - - -# @login_required(login_url='/login') -# @marketing_access_required -# def view_contact_list(request, pk): -# contact_list = get_object_or_404(ContactList, pk=pk) -# contacts = Contact.objects.filter(contact_list__in=[contact_list]) -# if request.POST and request.POST.get("search"): -# contacts = contacts.filter( -# Q(name__icontains=request.POST['search']) | -# Q(email__icontains=request.POST['search'])) - -# per_page = request.GET.get("per_page", 10) -# paginator = Paginator(contacts.order_by('id'), per_page) -# page = request.GET.get('page', 1) -# try: -# contacts = paginator.page(page) -# except PageNotAnInteger: -# contacts = paginator.page(1) -# except EmptyPage: -# contacts = paginator.page(paginator.num_pages) - -# data = {'contact_list': contact_list, "contacts": contacts} -# template_name = "marketing/lists/all.html" -# return render(request, template_name, data) - - -# @login_required(login_url='/login') -# @marketing_access_required -# def delete_contact_list(request, pk): -# contact_list_obj = get_object_or_404(ContactList, pk=pk) -# if not (request.user.role == 'ADMIN' or request.user.is_superuser or contact_list_obj.created_by == request.user): -# raise PermissionDenied - -# contact_list_obj.delete() -# redirect_to = reverse('marketing:contact_lists') -# return HttpResponseRedirect(redirect_to) - - -# @login_required(login_url='/login') -# @marketing_access_required -# def contacts_list_new(request): -# if request.POST: -# form = ContactForm(request.POST) -# if form.is_valid(): -# instance = form.save(commit=False) -# instance.created_by = request.user -# instance.save() -# for each in json.loads(request.POST['contact_list']): -# instance.contact_list.add(ContactList.objects.get(id=each)) -# # return JsonResponse(form.data, status=status.HTTP_201_CREATED) -# return reverse('marketing:contact_list') -# else: -# data = {'error': True, 'errors': form.errors} -# else: -# if (request.user.is_superuser): -# queryset = ContactList.objects.all() -# else: -# queryset = ContactList.objects.filter(created_by=request.user) -# data = {"contact_list": queryset} -# return render(request, 'marketing/lists/cnew.html', data) - - -@login_required(login_url="/login") -@marketing_access_required -def edit_contact(request, pk): - url_redirect_to = None - contact_obj = get_object_or_404(Contact, pk=pk) - if not ( - request.user.role == "ADMIN" - or request.user.is_superuser - or contact_obj.created_by == request.user - or ( - contact_obj.id - in request.user.marketing_contactlist.all().values_list( - "contacts", flat=True - ) - ) - ): - raise PermissionDenied - if request.method == "GET": - form = ContactForm(instance=contact_obj) - return render(request, "marketing/lists/edit_contact.html", {"form": form}) - - if request.method == "POST": - form = ContactForm(request.POST, instance=contact_obj) - if form.is_valid(): - if form.has_changed(): - if contact_obj.contact_list.count() > 1: - contact_list_obj = ContactList.objects.filter( - id=request.POST.get("from_url") - ).first() - if contact_list_obj: - contact_obj.contact_list.remove(contact_list_obj) - updated_contact = ContactForm(request.POST) - if updated_contact.is_valid(): - updated_contact_obj = updated_contact.save() - updated_contact_obj.created_by = request.user - updated_contact_obj.company = request.company - updated_contact_obj.save() - updated_contact_obj.contact_list.add(contact_list_obj) - else: - contact = form.save(commit=False) - if form.is_valid(): - contact.save() - form.save_m2m() - else: - contact = form.save(commit=False) - if form.is_valid(): - contact.save() - form.save_m2m() - if request.POST.get("from_url"): - return JsonResponse( - { - "error": False, - "success_url": reverse( - "marketing:contact_list_detail", - args=(request.POST.get("from_url"),), - ), - } - ) - return JsonResponse( - {"error": False, "success_url": reverse("marketing:contacts_list")} - ) - else: - return JsonResponse( - { - "error": True, - "errors": form.errors, - } - ) - - -@login_required(login_url="/login") -@marketing_access_required -def delete_contact(request, pk): - contact_obj = get_object_or_404(Contact, pk=pk) - - if not ( - request.user.role == "ADMIN" - or request.user.is_superuser - or contact_obj.created_by == request.user - or ( - contact_obj.id - in request.user.marketing_contactlist.all().values_list( - "contacts", flat=True - ) - ) - ): - raise PermissionDenied - if request.GET.get("from_contact"): - if contact_obj.contact_list.count() == 1: - contact_obj.delete() - # update_elastic_search_index.delay() - return redirect( - reverse( - "marketing:contact_list_detail", - args=(request.GET.get("from_contact"),), - ) - ) - else: - contact_list_obj = get_object_or_404( - ContactList, pk=request.GET.get("from_contact") - ) - contact_obj.contact_list.remove(contact_list_obj) - # update_elastic_search_index.delay() - return redirect( - reverse( - "marketing:contact_list_detail", - args=(request.GET.get("from_contact"),), - ) - ) - else: - contact_obj.delete() - # update_elastic_search_index.delay() - return redirect("marketing:contacts_list") - - -@login_required(login_url="/login") -@marketing_access_required -def contact_list_detail(request, pk): - contact_list = get_object_or_404(ContactList, pk=pk) - if not ( - request.user.role == "ADMIN" - or request.user.is_superuser - or contact_list.created_by == request.user - ): - raise PermissionDenied - contacts_list = contact_list.contacts.filter(is_bounced=False) - contacts_list_count = contact_list.contacts.filter(is_bounced=False).count() - bounced_contacts_list = contact_list.contacts.filter(is_bounced=True) - bounced_contacts_list_count = contact_list.contacts.filter(is_bounced=True).count() - duplicate_contacts = contact_list.duplicate_contact_contact_list.all() - if request.POST: - if request.POST.get("name"): - contacts_list = contacts_list.filter( - name__icontains=request.POST.get("name") - ) - if request.POST.get("email"): - contacts_list = contacts_list.filter( - email__icontains=request.POST.get("email") - ) - if request.POST.get("company_name"): - contacts_list = contacts_list.filter( - company_name=request.POST.get("company_name") - ) - - if request.POST.get("name"): - bounced_contacts_list = bounced_contacts_list.filter( - name__icontains=request.POST.get("name") - ) - if request.POST.get("email"): - bounced_contacts_list = bounced_contacts_list.filter( - email__icontains=request.POST.get("email") - ) - if request.POST.get("company_name"): - bounced_contacts_list = bounced_contacts_list.filter( - company_name=request.POST.get("company_name") - ) - - page = request.GET.get("bounced_contacts_page", 1) - paginator = Paginator(bounced_contacts_list, 10) - try: - bounced_contacts_list = paginator.page(page) - except: - bounced_contacts_list = paginator.page(paginator.num_pages) - - data = { - "contact_list": contact_list, - "contacts_list": contacts_list, - "bounced_contacts_list": bounced_contacts_list, - "bounced_contacts_list_count": bounced_contacts_list_count, - "contacts_list_count": contacts_list_count, - "duplicate_contacts": duplicate_contacts, - # these two are added for digg pagintor - "paginator": paginator, - "page_obj": bounced_contacts_list, - } - return render(request, "marketing/lists/detail.html", data) - - -# @login_required(login_url='/login') -# @marketing_access_required -# def failed_contact_list_detail(request, pk): -# contact_list = get_object_or_404(ContactList, pk=pk) -# failed_contacts_list = contact_list.failed_contacts.all() -# data = {'contact_list': contact_list, -# "failed_contacts_list": failed_contacts_list} -# return render(request, 'marketing/lists/failed_detail.html', data) - - -@login_required(login_url="/login") -@marketing_access_required -def failed_contact_list_download_delete(request, pk): - contact_list = get_object_or_404(ContactList, pk=pk) - failed_contacts_list = contact_list.failed_contacts.all() - if failed_contacts_list.count() > 0: - response = HttpResponse(content_type="text/csv") - response["Content-Disposition"] = 'attachment; filename="failed_contacts.csv"' - writer = csv.writer(response) - writer.writerow( - ["company name", "email", "first name", "last name", "city", "state"] - ) - - for contact in failed_contacts_list: - writer.writerow( - [ - contact.company_name, - contact.email, - contact.name, - contact.last_name, - contact.city, - contact.state, - ] - ) - failed_contacts_list.delete() - return response - else: - return HttpResponseRedirect( - reverse("marketing:contact_list_detail", kwargs={"pk": pk}) - ) - - -@login_required(login_url="/login") -@marketing_access_required -def email_template_list(request): - # users = User.objects.all() - if request.user.role == "ADMIN" or request.user.is_superuser: - queryset = EmailTemplate.objects.filter(company=request.company).order_by( - "-created_on" - ) - else: - queryset = EmailTemplate.objects.filter(created_by=request.user).order_by( - "-created_on" - ) - users = User.objects.filter(id__in=queryset.values_list("created_by_id", flat=True)) - search = False - if request.method == "POST": - if request.POST.get("template_name"): - queryset = queryset.filter( - title__icontains=request.POST.get("template_name") - ) - - if request.POST.get("created_by"): - queryset = queryset.filter(created_by=request.POST.get("created_by")) - if request.POST.get("template_name") or request.POST.get("created_by"): - search = True - data = {"email_templates": queryset, "users": users, "search": search} - return render(request, "marketing/email_template/index.html", data) - - -@login_required(login_url="/login") -@marketing_access_required -def email_template_new(request): - if request.POST: - form = EmailTemplateForm(request.POST) - if form.is_valid(): - instance = form.save(commit=False) - instance.created_by = request.user - instance.company = request.user.company - instance.save() - return JsonResponse( - {"error": False, "data": form.data}, status=status.HTTP_201_CREATED - ) - else: - return JsonResponse( - {"error": True, "errors": form.errors}, status=status.HTTP_200_OK - ) - else: - return render(request, "marketing/email_template/new.html") - - -@login_required(login_url="/login") -@marketing_access_required -def email_template_edit(request, pk): - email_template = get_object_or_404(EmailTemplate, pk=pk) - - if not ( - request.user.role == "ADMIN" - or request.user.is_superuser - or request.user == email_template.created_by - ): - raise PermissionDenied - - if request.method == "GET": - data = {"email_template": email_template} - return render(request, "marketing/email_template/new.html", data) - else: - form = EmailTemplateForm(request.POST, instance=email_template) - if form.is_valid(): - instance = form.save(commit=False) - # instance.created_by = request.user - instance.save() - return JsonResponse( - {"error": False, "data": form.data}, status=status.HTTP_201_CREATED - ) - return JsonResponse( - {"error": True, "errors": form.errors}, status=status.HTTP_200_OK - ) - - -@login_required(login_url="/login") -@marketing_access_required -def email_template_detail(request, pk): - queryset = get_object_or_404(EmailTemplate, id=pk) - if not ( - request.user.role == "ADMIN" - or request.user.is_superuser - or request.user == queryset.created_by - ): - raise PermissionDenied - data = {"email_template": queryset} - return render(request, "marketing/email_template/details.html", data) - - -@login_required(login_url="/login") -@marketing_access_required -def email_template_delete(request, pk): - email_template_obj = get_object_or_404(EmailTemplate, pk=pk) - if not ( - request.user.role == "ADMIN" - or request.user.is_superuser - or request.user == email_template_obj.created_by - ): - raise PermissionDenied - email_template_obj.delete() - redirect_to = reverse("marketing:email_template_list") - return HttpResponseRedirect(redirect_to) - - -@login_required(login_url="/login") -@marketing_access_required -def campaign_list(request): - # users = User.objects.all() - if request.user.role == "ADMIN": - queryset = Campaign.objects.filter(company=request.company) - else: - queryset = Campaign.objects.filter(created_by=request.user) - users = User.objects.filter(id__in=queryset.values_list("created_by_id", flat=True)) - if request.GET.get("tag"): - queryset = queryset.filter(tags=request.GET.get("tag")) - search = False - if request.method == "POST": - if request.POST.get("campaign_name"): - queryset = queryset.filter( - title__icontains=request.POST.get("campaign_name") - ) - - if request.POST.get("created_by"): - queryset = queryset.filter(created_by=request.POST.get("created_by")) - # shows the filter form in marketing-Campaigns after any search is requested - if request.POST.get("campaign_name") or request.POST.get("created_by"): - search = True - data = {"campaigns_list": queryset, "search": search, "users": users} - return render(request, "marketing/campaign/index.html", data) - - -@login_required(login_url="/login") -@marketing_access_required -def campaign_new(request): - if request.method == "GET": - if request.user.role == "ADMIN" or request.user.is_superuser: - email_templates = EmailTemplate.objects.filter(company=request.company) - else: - email_templates = EmailTemplate.objects.filter(created_by=request.user) - if request.user.role == "ADMIN" or request.user.is_superuser: - contact_lists = ContactList.objects.filter(company=request.company) - else: - contact_lists = ContactList.objects.filter(created_by=request.user) - # if request.GET.get('contact_list'): - # contacts = Contact.objects.filter( - # contact_list__id__in=json.loads(request.GET.get('contact_list'))).distinct() - - data = { - "contact_lists": contact_lists, - "email_templates": email_templates, - "timezones": TIMEZONE_CHOICES, - "settings_timezone": settings.TIME_ZONE, - } - # return JsonResponse(data, status=status.HTTP_200_OK) - return render(request, "marketing/campaign/new.html", data) - else: - form = SendCampaignForm( - request.POST, - request.FILES, - contacts_list=request.POST.getlist("contact_list"), - ) - if form.is_valid(): - instance = form.save(commit=False) - instance.created_by = request.user - instance.company = request.company - if request.POST.get("from_email"): - instance.from_email = request.POST["from_email"] - if request.POST.get("from_name"): - instance.from_name = request.POST["from_name"] - if request.POST.get("reply_to_crm") == "true": - instance.reply_to_email = settings.MARKETING_REPLY_EMAIL - else: - if request.POST.get("reply_to_email"): - instance.reply_to_email = request.POST["reply_to_email"] - # if request.FILES.get('attachment'): - # instance.attachment = request.FILES.get('attachment') - instance.save() - for each in request.POST.getlist("contact_list"): - instance.contact_lists.add(ContactList.objects.get(id=each)) - # contacts = Contact.objects.filter(contact_list__in=json.loads(request.POST['contact_list'])).distinct() - # for each_contact in contacts: - # instance.contacts.add(each_contact) - instance.original_contact_count = ( - instance.contact_lists.exclude(contacts__email=None) - .values_list("contacts__email") - .count() - ) - instance.save() - tags = request.POST["tags"].split(",") if request.POST["tags"] else [] - for each in tags: - tag, _ = Tag.objects.get_or_create( - name=each, created_by=request.user, company=request.company - ) - instance.tags.add(tag) - - camp = instance - - html = camp.html - dom = lxml.html.document_fromstring(html) - selAnchor = CSSSelector("a") - links = selAnchor(dom) - llist = [] - # Extract links and unique links - for e in links: - llist.append(e.get("href")) - - # get unique link - links = set(llist) - - # Replace Links with new One - # domain_url = '%s://%s' % (request.scheme, request.META['HTTP_HOST']) - domain_url = request.scheme + "://" + request.get_host() - if Link.objects.filter(campaign_id=camp.id): - Link.objects.filter(campaign_id=camp.id).delete() - for l in links: - link = Link.objects.create(campaign_id=camp.id, original=l) - html = html.replace( - 'href="' + l + '"', - 'href="' - + domain_url - + "/marketing/cm/link/" - + str(link.id) - + '/e/{{email_id}}"', - ) - - camp.html_processed = html - camp.sent_status = "scheduled" - camp.save() - - if request.POST.get("schedule_later", None) == "true": - schedule_date_time = request.POST.get("schedule_date_time", "") - user_timezone = request.POST.get("timezone", "") - if user_timezone and schedule_date_time: - start_time_object = ddatetime.strptime( - schedule_date_time, "%Y-%m-%d %H:%M" - ) - schedule_date_time = convert_to_custom_timezone( - start_time_object, user_timezone, to_utc=True - ) - instance.schedule_date_time = schedule_date_time - instance.timezone = user_timezone - instance.save() - send_campaign_email_to_admin_contact.delay( - instance.id, domain=request.get_host(), protocol=request.scheme - ) - else: - run_campaign.delay( - instance.id, domain=request.get_host(), protocol=request.scheme - ) - send_campaign_email_to_admin_contact.delay( - instance.id, domain=request.get_host(), protocol=request.scheme - ) - return JsonResponse( - {"error": False, "data": form.data}, status=status.HTTP_201_CREATED - ) - return JsonResponse( - {"error": True, "errors": form.errors}, status=status.HTTP_200_OK - ) - - -# @login_required(login_url='/login') -# @marketing_access_required -# def campaign_edit(request): -# return render(request, 'marketing/campaign/edit.html') - - -@login_required(login_url="/login") -@marketing_access_required -def campaign_details(request, pk): - campaign = get_object_or_404(Campaign, pk=pk) - if not ( - request.user.role == "ADMIN" - or request.user.is_superuser - or request.user == campaign.created_by - ): - raise PermissionDenied - contact_lists = campaign.contact_lists.all() - if request.user.role == "ADMIN" or request.user.is_superuser: - contact_lists = contact_lists.filter(company=request.company) - else: - # contact_lists = contact_lists.filter( - # is_public=True, created_by=request.user) - contact_lists = contact_lists.filter(created_by=request.user) - - contacts = Contact.objects.filter(contact_list__in=contact_lists) - contact_list_ids = campaign.contact_lists.all().values_list("id", flat=True) - - contacts = Contact.objects.filter(contact_list__id__in=contact_list_ids) - - all_contacts = contacts - bounced_contacts = contacts.filter(is_bounced=True).distinct() - unsubscribe_contacts = contacts.filter(is_unsubscribed=True).distinct() - # unsubscribe_contacts_ids = ContactUnsubscribedCampaign.objects.filter( - # campaigns=campaign, is_unsubscribed=True).values_list('contacts_id', flat=True) - # unsubscribe_contacts = Contact.objects.filter( - # id__in=unsubscribe_contacts_ids) - # read_contacts = campaign.marketing_links.filter(Q(clicks__gt=0)).distinct() - contact_ids = CampaignOpen.objects.filter(campaign=campaign).values_list( - "contact_id", flat=True - ) - read_contacts = Contact.objects.filter(id__in=contact_ids) - sent_contacts = contacts.exclude(Q(is_bounced=True) | Q(is_unsubscribed=True)) - # if request.POST: - # contacts = contacts.filter(Q(name__icontains=request.POST['search'])) - - tab = request.GET.get("tab", "contacts") - per_page = request.GET.get("per_page", 10) - page = request.GET.get("page", 1) - - # contacts_paginator = Paginator(contacts.order_by('id'), per_page) - # if (tab == "contacts"): - # page = page - # else: - # page = 1 - # try: - # contacts = contacts_paginator.page(page) - # except PageNotAnInteger: - # contacts = contacts_paginator.page(1) - # except EmptyPage: - # contacts = contacts_paginator.page(contacts_paginator.num_pages) - - # unsubscribe_contacts_paginator = Paginator( - # unsubscribe_contacts.order_by('id'), per_page) - # if (tab == "unsubscribe_contacts"): - # page = page - # else: - # page = 1 - - # try: - # unsubscribe_contacts = unsubscribe_contacts_paginator.page(page) - # except PageNotAnInteger: - # unsubscribe_contacts = unsubscribe_contacts_paginator.page(1) - # except EmptyPage: - # unsubscribe_contacts = unsubscribe_contacts_paginator.page( - # unsubscribe_contacts_paginator.num_pages) - - # bounced_contacts_paginator = Paginator( - # bounced_contacts.order_by('id'), per_page) - # if (tab == "bounced_contacts"): - # page = page - # else: - # page = 1 - - # try: - # bounced_contacts = bounced_contacts_paginator.page(page) - # except PageNotAnInteger: - # bounced_contacts = bounced_contacts_paginator.page(1) - # except EmptyPage: - # bounced_contacts = bounced_contacts_paginator.page( - # bounced_contacts_paginator.num_pages) - - # sent_contacts_paginator = Paginator(sent_contacts.order_by('id'), per_page) - # if (tab == "sent_contacts"): - # page = page - # else: - # page = 1 - - # try: - # sent_contacts = sent_contacts_paginator.page(page) - # except PageNotAnInteger: - # sent_contacts = sent_contacts_paginator.page(1) - # except EmptyPage: - # sent_contacts = sent_contacts_paginator.page( - # sent_contacts_paginator.num_pages) - - # all_contacts_paginator = Paginator(all_contacts.order_by('id'), per_page) - # if (tab == "all_contacts"): - # page = page - # else: - # page = 1 - - # try: - # all_contacts = all_contacts_paginator.page(page) - # except PageNotAnInteger: - # all_contacts = all_contacts_paginator.page(1) - # except EmptyPage: - # all_contacts = all_contacts_paginator.page( - # all_contacts_paginator.num_pages) - - # read_contacts_paginator = Paginator(read_contacts.order_by('id'), per_page) - # if (tab == "read_contacts"): - # page = page - # else: - # page = 1 - - # try: - # read_contacts = read_contacts_paginator.page(page) - # except PageNotAnInteger: - # read_contacts = read_contacts_paginator.page(1) - # except EmptyPage: - # read_contacts = read_contacts_paginator.page( - # read_contacts_paginator.num_pages) - - data = { - "contact_lists": contact_lists, - "campaign": campaign, - "contacts": contacts, - "unsubscribe_contacts": unsubscribe_contacts, - "bounced_contacts": bounced_contacts, - "read_contacts": read_contacts, - "sent_contacts": sent_contacts, - "all_contacts": all_contacts, - "tab": tab, - } - - return render(request, "marketing/campaign/details.html", data) - - -@login_required(login_url="/login") -@marketing_access_required -def campaign_delete(request, pk): - campaign = get_object_or_404(Campaign, pk=pk) - if not ( - request.user.role == "ADMIN" - or request.user.is_superuser - or request.user == campaign.created_by - ): - raise PermissionDenied - campaign.delete() - redirect_url = reverse("marketing:campaign_list") - return redirect(redirect_url) - - -def campaign_link_click(request, link_id, email_id): - x_forwarded_for = request.META.get("HTTP_X_FORWARDED_FOR") - - if x_forwarded_for: - ipaddress = x_forwarded_for.split(",")[-1].strip() - else: - ipaddress = request.META.get("REMOTE_ADDR") - - link = Link.objects.filter(id=link_id).first() - contact = Contact.objects.filter(id=email_id).first() - if link and contact: - campaign_link_click = CampaignLinkClick.objects.filter( - link=link, campaign=link.campaign, contact=contact - ).first() - if not campaign_link_click: - campaign_link_click = CampaignLinkClick.objects.create( - link=link, campaign=link.campaign, contact=contact, ip_address=ipaddress - ) - link.unique += 1 - else: - campaign_link_click.ip_address = ipaddress - link.clicks += 1 - link.save() - campaign_link_click.save() - url = link.original - else: - # url = settings.URL_FOR_LINKS - url = link.original - return redirect(url) - - -def campaign_open(request, campaign_log_id, email_id): # pragma: no cover - x_forwarded_for = request.META.get("HTTP_X_FORWARDED_FOR") - - if x_forwarded_for: - ipaddress = x_forwarded_for.split(",")[-1].strip() - else: - ipaddress = request.META.get("REMOTE_ADDR") - - campaign_log = CampaignLog.objects.filter(id=campaign_log_id).first() - contact = Contact.objects.filter(id=email_id).first() - image_data = open("static/images/company.png", "rb").read() - if campaign_log and contact: - campaign_open = CampaignOpen.objects.filter( - campaign=campaign_log.campaign, contact=contact - ).first() - if not campaign_open: - campaign_open = CampaignOpen.objects.create( - campaign=campaign_log.campaign, contact=contact, ip_address=ipaddress - ) - campaign_log.campaign.opens_unique += 1 - else: - campaign_open.ip_address = ipaddress - campaign_log.campaign.opens += 1 - campaign_log.campaign.status = "Sent" - campaign_log.campaign.save() - campaign_open.save() - return HttpResponse(image_data, content_type="image/png") - - -def demo_file_download(request): - sample_data = [ - "company name,email,first name,last name,city,state\n", - "company_name_1,user1@email.com,first_name,last_name,Hyderabad,Telangana\n", - "company_name_2,user2@email.com,first_name,last_name,Hyderabad,Telangana\n", - "company_name_3,user3@email.com,first_name,last_name,Hyderabad,Telangana\n", - "company_name_4,user4@email.com,first_name,last_name,Hyderabad,Telangana\n", - ] - response = HttpResponse(sample_data, content_type="text/plain") - response["Content-Disposition"] = "attachment; filename={}".format( - "sample_data.csv" - ) - return response - - -def unsubscribe_from_campaign(request, contact_id, campaign_id): - contact_obj = get_object_or_404(Contact, pk=contact_id) - contact_obj.is_unsubscribed = True - contact_obj.save() - campaign_obj = Campaign.objects.filter(id=campaign_id).first() - # campaign_obj = get_object_or_404(Campaign, pk=campaign_id) - if campaign_obj: - ContactUnsubscribedCampaign.objects.create( - campaigns=campaign_obj, contacts=contact_obj, is_unsubscribed=True - ) - return render(request, "unsubscribe_from_campaign_template.html") - - -@login_required -@marketing_access_required -def contact_detail(request, contact_id): - contact_obj = get_object_or_404(Contact, pk=contact_id) - if not ( - request.user.role == "ADMIN" - or request.user.is_superuser - or contact_obj.created_by == request.user - or ( - contact_obj.id - in request.user.marketing_contactlist.all().values_list( - "contacts", flat=True - ) - ) - ): - # the above query is for: a contact may be common to multiple contact lists, so query from - # a contact list can be created by multiple users - raise PermissionDenied - if request.method == "GET": - return render(request, "contact_detail.html", {"contact_obj": contact_obj}) - - -# @login_required(login_url='/login') -# @marketing_access_required -# def edit_failed_contact(request, pk): -# contact_obj = get_object_or_404(FailedContact, pk=pk) -# if not (request.user.role == 'ADMIN' or request.user.is_superuser or contact_obj.created_by == request.user): -# raise PermissionDenied -# if request.method == 'GET': -# form = ContactForm(instance=contact_obj) -# return render(request, 'marketing/lists/edit_contact.html', {'form': form}) - -# if request.method == 'POST': -# form = ContactForm(request.POST, instance=contact_obj) -# if form.is_valid(): -# contact = form.save(commit=False) -# contact.save() -# form.save_m2m() -# return JsonResponse({'error': False, 'success_url': reverse('marketing:contacts_list')}) -# else: -# return JsonResponse({'error': True, 'errors': form.errors, }) - - -# @login_required(login_url='/login') -# @marketing_access_required -# def delete_failed_contact(request, pk): -# contact_obj = get_object_or_404(FailedContact, pk=pk) -# if not (request.user.role == 'ADMIN' or request.user.is_superuser or contact_obj.created_by == request.user): -# raise PermissionDenied -# if request.method == 'GET': -# contact_obj.delete() -# return redirect('marketing:contacts_list') - - -@login_required -@marketing_access_required -def download_contacts_for_campaign(request, compaign_id): - campaign_obj = get_object_or_404(Campaign, pk=compaign_id) - if not ( - request.user.role == "ADMIN" - or request.user.is_superuser - or campaign_obj.created_by == request.user - ): - raise PermissionDenied - if request.method == "GET": - if request.GET.get("is_bounced") == "true": - contact_ids = campaign_obj.campaign_log_contacts.filter( - contact__is_bounced=True - ).values_list("contact__id", flat=True) - contacts = Contact.objects.filter(id__in=contact_ids).values( - "company_name", "email", "name", "last_name", "city", "state" - ) - - if request.GET.get("is_unsubscribed") == "true": - - # unsubscribe_contacts_ids = ContactUnsubscribedCampaign.objects.filter( - # campaigns=campaign_obj, is_unsubscribed=True).values_list('contacts_id', flat=True) - contact_ids = campaign_obj.campaign_log_contacts.filter( - contact__is_unsubscribed=True - ).values_list("contact__id", flat=True) - contacts = Contact.objects.filter(id__in=contact_ids).values( - "company_name", "email", "name", "last_name", "city", "state" - ) - - if request.GET.get("is_opened") == "true": - contact_ids = CampaignOpen.objects.filter( - campaign=campaign_obj - ).values_list("contact_id", flat=True) - contacts = Contact.objects.filter(id__in=contact_ids).values( - "company_name", "email", "name", "last_name", "city", "state" - ) - - data = [ - "company name,email,first name,last name,city,state\n", - ] - for contact in contacts: - data.append( - str(contact.get("company_name")) - + "," - + str(contact.get("email")) - + "," - + str(contact.get("name")) - + "," - + str(contact.get("last_name")) - + "," - + str(contact.get("city")) - + "," - + str(contact.get("state")) - + "\n" - ) - response = HttpResponse(data, content_type="text/plain") - response["Content-Disposition"] = "attachment; filename={}".format( - "data_downloads.csv" - ) - return response - - -@login_required -@marketing_access_required -def create_campaign_from_template(request, template_id): - email_template_obj = get_object_or_404(EmailTemplate, pk=template_id) - if request.method == "GET": - url_location = reverse("marketing:campaign_new") - url_query_params = "?email_template={}".format(template_id) - url = url_location + url_query_params - return HttpResponseRedirect(url) - - -def download_links_clicked(request, campaign_id): - campaign_obj = get_object_or_404(Campaign, pk=campaign_id) - campaign_link_click_objects = campaign_obj.campaign_link_click.all().select_related( - "link", "campaign", "contact" - ) - csv_row_headers = [ - "email", - "company", - "first name", - "last name", - "city", - "state", - "original link", - "unique clicks", - "total clicks", - "campaign title", - ] - data = [] - data.append(",".join(csv_row_headers) + "\n") - if campaign_link_click_objects: - for campaign_link_click_object in campaign_link_click_objects: - data.append( - str(campaign_link_click_object.contact.email) - + "," - + str(campaign_link_click_object.contact.company_name) - + "," - + str(campaign_link_click_object.contact.name) - + "," - + str(campaign_link_click_object.contact.last_name) - + "," - + str(campaign_link_click_object.contact.city) - + "," - + str(campaign_link_click_object.contact.state) - + "," - + str(campaign_link_click_object.link.original) - + "," - + str(campaign_link_click_object.link.unique) - + "," - + str(campaign_link_click_object.link.clicks) - + "," - + str(campaign_link_click_object.link.campaign.title) - + "\n" - ) - response = HttpResponse(data, content_type="text/plain") - response["Content-Disposition"] = "attachment; filename={}".format( - "data_downloads.csv" - ) - return response - - -@login_required(login_url="/login") -@marketing_access_required -def delete_multiple_contacts(request): - contacts_list = Contact.objects.filter( - id__in=request.POST.getlist("selected_list[]") - ) - shared_contact_lists = request.user.marketing_contactlist.all().values_list( - "contacts", flat=True - ) - cannot_be_deleted = [] - error = False - for contact_obj in contacts_list: - if not ( - request.user.role == "ADMIN" - or request.user.is_superuser - or contact_obj.created_by == request.user - or (contact_obj.id in shared_contact_lists) - ): - cannot_be_deleted.append(contact_obj.email) - error = True - if len(cannot_be_deleted) == 0: - error = False - for contact_obj in contacts_list: - if request.POST.get("from_contact"): - if contact_obj.contact_list.count() == 1: - contact_obj.delete() - else: - if request.POST.get("duplicate_contacts", None) == "true": - contact_list_obj = get_object_or_404( - ContactList, pk=request.POST.get("from_contact") - ) - contact_obj.contact_list.remove(contact_list_obj) - - contact_list_duplicates = ( - contact_list_obj.duplicate_contact_contact_list.all() - ) - contacts_list_ids = contacts_list.values_list("id", flat=True) - contact_list_duplicates.filter( - contacts__id__in=contacts_list_ids - ).delete() - else: - contact_list_obj = get_object_or_404( - ContactList, pk=request.POST.get("from_contact") - ) - contact_obj.contact_list.remove(contact_list_obj) - - return JsonResponse({"error": False, "refresh": True}) - else: - message = "You don't have permission to delete {}".format( - ", ".join(cannot_be_deleted) - ) - return JsonResponse({"error": True, "message": message}) - - -@login_required(login_url="/login") -@marketing_access_required -def delete_all_contacts(request, contact_list_id): - - contacts_list_obj = get_object_or_404(ContactList, pk=contact_list_id) - if not ( - request.user.role == "ADMIN" - or request.user.is_superuser - or contacts_list_obj.created_by == request.user - ): - raise PermissionDenied - if request.GET.get("bounced", "") == "true": - bounced = True - else: - bounced = False - if request.GET.get("duplicate_contacts", "") == "true": - contact_list_duplicates = contacts_list_obj.duplicate_contact_contact_list.all() - if contact_list_duplicates: - for dup_contact_obj in contact_list_duplicates: - if dup_contact_obj.contacts.contact_list.count() > 1: - contact = dup_contact_obj.contacts - contact.contact_list.remove(contacts_list_obj) - dup_contact_obj.delete() - # dup_contact_obj.contacts.contact_list.remove(contacts_list_obj) - # else: - # dup_contact_obj.contacts.delete() - else: - contacts_objs = contacts_list_obj.contacts.filter(is_bounced=bounced) - if contacts_objs: - for contact_obj in contacts_objs: - if contact_obj.contact_list.count() > 1: - contact_obj.contact_list.remove(contacts_list_obj) - else: - contact_obj.delete() - - # delete_multiple_contacts_tasks.delay(contact_list_id, bounced) - redirect_to = reverse("marketing:contact_list_detail", args=(contact_list_id,)) - return HttpResponseRedirect(redirect_to) - - -@login_required -@marketing_access_required -def download_failed_contacts(request, contact_list_id): - - contact_list_obj = get_object_or_404(ContactList, pk=contact_list_id) - if not ( - request.user.role == "ADMIN" - or request.user.is_superuser - or contact_list_obj.created_by == request.user - ): - raise PermissionDenied - - failed_contacts = contact_list_obj.failed_contacts.values( - "company_name", "email", "name", "last_name", "city", "state" - ) - if failed_contacts: - data = [ - "company name,email,first name,last name,city,state\n", - ] - for contact in failed_contacts: - data.append( - str(contact.get("company_name")) - + "," - + str(contact.get("email")) - + "," - + str(contact.get("name")) - + "," - + str(contact.get("last_name")) - + "," - + str(contact.get("city")) - + "," - + str(contact.get("state")) - + "\n" - ) - response = HttpResponse(data, content_type="text/plain") - response["Content-Disposition"] = "attachment; filename={}".format( - "failed_contacts.csv" - ) - return response - - else: - return HttpResponse("No Data") - - -@login_required -@admin_login_required -def list_all_emails_for_campaigns(request): - context = {} - if request.method == "GET": - queryset = ContactEmailCampaign.objects.filter(company=request.company) - context["contacts"] = queryset - return render(request, "email_for_campaigns_list.html", context) - - -@login_required -@admin_login_required -def add_email_for_campaigns(request): - context = {} - if request.method == "GET": - form = EmailCampaignForm() - context["form"] = form - return render(request, "add_email_for_campaign.html", context) - if request.method == "POST": - form = EmailCampaignForm(request.POST) - if form.is_valid(): - obj = form.save(commit=False) - obj.created_by = request.user - obj.company = request.company - obj.save() - return JsonResponse( - {"error": False, "success_url": reverse("common:api_settings")} - ) - else: - return JsonResponse({"error": True, "errors": form.errors}) - - -@login_required -@admin_login_required -def edit_email_for_campaigns(request, pk): - edit_contact_obj = get_object_or_404(ContactEmailCampaign, pk=pk) - context = {} - if request.method == "GET": - form = EmailCampaignForm(instance=edit_contact_obj) - context["form"] = form - context["edit_obj"] = edit_contact_obj - return render(request, "add_email_for_campaign.html", context) - if request.method == "POST": - form = EmailCampaignForm(request.POST, instance=edit_contact_obj) - if form.is_valid(): - obj = form.save(commit=False) - obj.save() - return JsonResponse( - {"error": False, "success_url": reverse("common:api_settings")} - ) - else: - return JsonResponse({"error": True, "errors": form.errors}) - - -@login_required -@admin_login_required -def delete_email_for_campaigns(request, pk): - contact_obj = get_object_or_404(ContactEmailCampaign, pk=pk) - context = {} - if request.method == "GET": - contact_obj.delete() - return HttpResponseRedirect(reverse("common:api_settings")) - - -# the below views should be in settings page - - -@login_required -@admin_login_required -def add_blocked_domain(request): - if request.method == "GET": - form = BlockedDomainsForm() - return render(request, "add_blocked_domain.html", {"form": form}) - if request.method == "POST": - form = BlockedDomainsForm(request.POST) - if form.is_valid(): - domain = form.save(commit=False) - domain.created_by = request.user - domain.company = request.company - domain.save() - return JsonResponse( - {"error": False, "success_url": reverse("common:api_settings")} - ) - else: - return JsonResponse({"error": True, "errors": form.errors}) - - -@login_required -@admin_login_required -def blocked_domain_list(request): - if request.method == "GET": - blocked_domains = BlockedDomain.objects.all() - return render( - request, "blocked_domain_list.html", {"blocked_domains": blocked_domains} - ) - if request.method == "POST": - blocked_domains = BlockedDomain.objects.all() - if request.POST.get("domain", ""): - blocked_domains = blocked_domains.filter( - domain__icontains=request.POST.get("domain", "") - ) - if request.POST.get("created_by", ""): - blocked_domains = blocked_domains.filter( - created_by_id=request.POST.get("created_by", "") - ) - return render( - request, "blocked_domain_list.html", {"blocked_domains": blocked_domains} - ) - - -@login_required -@admin_login_required -def edit_blocked_domain(request, blocked_domain_id): - block_domain_obj = get_object_or_404(BlockedDomain, pk=blocked_domain_id) - if request.method == "GET": - form = BlockedDomainsForm(instance=block_domain_obj) - return render( - request, - "add_blocked_domain.html", - {"form": form, "block_domain_obj": block_domain_obj}, - ) - if request.method == "POST": - form = BlockedDomainsForm(request.POST, instance=block_domain_obj) - if form.is_valid(): - form.save() - return JsonResponse( - {"error": False, "success_url": reverse("common:api_settings")} - ) - else: - return JsonResponse({"error": True, "errors": form.errors}) - - -@login_required -@admin_login_required -def delete_blocked_domain(request, blocked_domain_id): - block_domain_obj = get_object_or_404(BlockedDomain, pk=blocked_domain_id) - block_domain_obj.delete() - return redirect(reverse("common:api_settings") + "?blocked_domains") - - -@login_required -@admin_login_required -def add_blocked_email(request): - if request.method == "GET": - form = BlockedEmailForm() - return render(request, "add_blocked_email.html", {"form": form}) - if request.method == "POST": - form = BlockedEmailForm(request.POST) - if form.is_valid(): - email = form.save(commit=False) - email.created_by = request.user - email.company = request.company - email.save() - return JsonResponse( - {"error": False, "success_url": reverse("common:api_settings")} - ) - else: - return JsonResponse({"error": True, "errors": form.errors}) - - -@login_required -@admin_login_required -def blocked_email_list(request): - if request.method == "GET": - blocked_emails = BlockedEmail.objects.all() - return render( - request, "blocked_email_list.html", {"blocked_emails": blocked_emails} - ) - if request.method == "POST": - blocked_emails = BlockedEmail.objects.all() - if request.POST.get("email", ""): - blocked_emails = blocked_emails.filter( - email__icontains=request.POST.get("email", "") - ) - if request.POST.get("created_by", ""): - blocked_emails = blocked_emails.filter( - created_by_id=request.POST.get("created_by", "") - ) - return render( - request, "blocked_email_list.html", {"blocked_emails": blocked_emails} - ) - - -@login_required -@admin_login_required -def edit_blocked_email(request, blocked_email_id): - block_email_obj = get_object_or_404(BlockedEmail, pk=blocked_email_id) - if request.method == "GET": - form = BlockedEmailForm(instance=block_email_obj) - return render( - request, - "add_blocked_email.html", - {"form": form, "block_email_obj": block_email_obj}, - ) - if request.method == "POST": - form = BlockedEmailForm(request.POST, instance=block_email_obj) - if form.is_valid(): - form.save() - return JsonResponse( - {"error": False, "success_url": reverse("common:api_settings")} - ) - else: - return JsonResponse({"error": True, "errors": form.errors}) - - -@login_required -@admin_login_required -def delete_blocked_email(request, blocked_email_id): - block_email_obj = get_object_or_404(BlockedEmail, pk=blocked_email_id) - block_email_obj.delete() - return redirect(reverse("common:api_settings") + "?blocked_emails") - - -@login_required(login_url="/login") -@marketing_access_required -def contacts_list_elastic_search(request): - search = False - if request.user.role == "ADMIN": - contacts = Contact.objects.filter(is_bounced=False, company=request.company) - # contacts = SearchQuerySet().filter(is_bounced='false').models(Contact) - # bounced_contacts = SearchQuerySet().filter(is_bounced='true').models(Contact) - # failed_contacts = SearchQuerySet().models(FailedContact).filter() - bounced_contacts = Contact.objects.filter( - is_bounced=True, company=request.company - ) - failed_contacts = FailedContact.objects.filter( - company=request.company - ).order_by("id") - contact_lists = ContactList.objects.filter(company=request.company) - else: - contact_ids = request.user.marketing_contactlist.all().values_list( - "contacts", flat=True - ) - # contacts = SearchQuerySet().filter(is_bounced='false', id__in=contact_ids).models(Contact) - # bounced_contacts = SearchQuerySet().filter(is_bounced='true', id__in=contact_ids).models(Contact) - # failed_contacts = SearchQuerySet().models(FailedContact).filter(created_by_id=str(request.user.id)) - contacts = Contact.objects.filter(id__in=contact_ids).exclude(is_bounced=True) - bounced_contacts = Contact.objects.filter(id__in=contact_ids, is_bounced=True) - failed_contacts = FailedContact.objects.filter( - created_by=request.user - ).order_by("id") - contact_lists = ContactList.objects.filter(created_by=request.user) - # contacts = Contact.objects.filter(created_by=request.user) - - users = User.objects.filter( - id__in=[ - _id for _id in contacts.values_list("created_by_id", flat=True) if _id != "" - ] - ) - - if request.method == "GET": - context = { - "contacts": contacts, - "users": users, - "contact_lists": contact_lists, - "bounced_contacts": bounced_contacts, - "failed_contacts": failed_contacts, - "search": search, - } - return render(request, "search_contact_emails.html", context) - - if request.method == "POST": - data = request.POST - if data.get("name"): - contacts = contacts.filter(name__icontains=data.get("name")) - bounced_contacts = bounced_contacts.filter(name__icontains=data.get("name")) - failed_contacts = failed_contacts.filter(name__icontains=data.get("name")) - if data.get("email"): - contacts = contacts.filter(email__icontains=data.get("email")) - bounced_contacts = bounced_contacts.filter( - email__icontains=data.get("email") - ) - failed_contacts = failed_contacts.filter(email__icontains=data.get("email")) - - # if data.get('domain_name'): - # contacts = contacts.filter(email_domain__icontains=data.get('domain_name')) - # bounced_contacts = bounced_contacts.filter(email_domain__icontains=data.get('domain_name')) - # failed_contacts = failed_contacts.filter(email_domain__icontains=data.get('domain_name')) - - if data.get("created_by"): - contacts = contacts.filter(created_by_id=data.get("created_by")) - bounced_contacts = bounced_contacts.filter( - created_by_id=data.get("created_by") - ) - failed_contacts = failed_contacts.filter( - created_by_id=data.get("created_by") - ) - - if data.get("contact_list"): - contacts = contacts.filter(contact_list__id=data.get("contact_list")) - bounced_contacts = bounced_contacts.filter( - contact_list__id=data.get("contact_list") - ) - failed_contacts = failed_contacts.filter( - contact_list__id=data.get("contact_list") - ) - - # shows filter form in marketing-contact if any search - if ( - data.get("name") - or data.get("email") - or data.get("created_by") - or data.get("contact_list") - ): - search = True - context = { - "contacts": contacts, - "users": users, - "contact_lists": contact_lists, - "bounced_contacts": bounced_contacts, - "failed_contacts": failed_contacts, - "search": search, - } - return render(request, "search_contact_emails.html", context) - - -# class MarketingContactEmailSearch(SearchView): -# form_class = MarketingContactEmailSearchForm - -# def get_query(self): -# if self.form.is_valid(): -# return self.form.cleaned_data["email_domain"] - -# return "" - -# # def get_queryset(self): -# # # queryset = super(MarketingContactEmailSearch, self).get_queryset() -# # queryset = SearchQuerySet().models(Contact).filter( -# # email__icontains=self.request.GET.get('email_domain', None)) -# # return queryset - -# # def get_context_data(self, *args, **kwargs): -# # context = super(MarketingContactEmailSearch, self).get_context_data(*args, **kwargs) -# # return context diff --git a/opportunity/api_views.py b/opportunity/api_views.py index dde2c9d..f023488 100644 --- a/opportunity/api_views.py +++ b/opportunity/api_views.py @@ -37,11 +37,13 @@ from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.permissions import IsAuthenticated +from rest_framework.pagination import LimitOffsetPagination from drf_yasg.utils import swagger_auto_schema import json +from crm import settings -class OpportunityListView(APIView): +class OpportunityListView(APIView, LimitOffsetPagination): authentication_classes = (JSONWebTokenAuthentication,) permission_classes = (IsAuthenticated,) @@ -53,9 +55,9 @@ def get_context_data(self, **kwargs): if len(self.request.data) == 0 else self.request.data ) - queryset = self.model.objects.filter(company=self.request.company) - accounts = Account.objects.filter(company=self.request.company) - contacts = Contact.objects.filter(company=self.request.company) + queryset = self.model.objects.all() + accounts = Account.objects.all() + contacts = Contact.objects.all() if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: queryset = queryset.filter( Q(created_by=self.request.user) | Q(assigned_to=self.request.user) @@ -94,33 +96,34 @@ def get_context_data(self, **kwargs): or params.get("tags") ): search = True - context["search"] = search - opportunities = OpportunitySerializer(queryset, many=True).data + results_opportunities = self.paginate_queryset( + queryset.distinct(), self.request, view=self + ) + opportunities = OpportunitySerializer(results_opportunities, many=True).data + context["per_page"] = 10 + context.update( + { + "opportunities_count": self.count, + "next": self.get_next_link(), + "previous": self.get_previous_link(), + "page_number": int(self.offset / 10) + 1, + } + ) context["opportunities"] = opportunities context["users"] = UserSerializer( - User.objects.filter(is_active=True, company=self.request.company).order_by( - "email" - ), + User.objects.filter(is_active=True).order_by("email"), many=True, ).data - tag_ids = list( - set( - Opportunity.objects.filter(company=self.request.company).values_list( - "tags", flat=True - ) - ) - ) + tag_ids = list(set(Opportunity.objects.all().values_list("tags", flat=True))) context["tags"] = TagsSerializer( Tags.objects.filter(id__in=tag_ids), many=True ).data context["accounts_list"] = AccountSerializer(accounts, many=True).data context["contacts_list"] = ContactSerializer(contacts, many=True).data if self.request.user == "ADMIN": - context["teams_list"] = TeamsSerializer( - Teams.objects.filter(company=self.request.company), many=True - ).data + context["teams_list"] = TeamsSerializer(Teams.objects.all(), many=True).data context["stage"] = STAGES context["lead_source"] = SOURCES context["currency"] = CURRENCY_CODES @@ -146,28 +149,24 @@ def post(self, request, *args, **kwargs): if serializer.is_valid(): opportunity_obj = serializer.save( created_by=request.user, - company=request.company, closed_on=params.get("due_date"), ) if params.get("contacts"): contacts = json.loads(params.get("contacts")) for contact in contacts: - obj_contact = Contact.objects.filter( - id=contact, company=request.company - ) + obj_contact = Contact.objects.filter(id=contact) if obj_contact: opportunity_obj.contacts.add(contact) else: opportunity_obj.delete() data["contacts"] = "Please enter valid contact" - return Response({"error": True, "errors": data}) + return Response( + {"error": True, "errors": data}, + status=status.HTTP_400_BAD_REQUEST, + ) if params.get("tags"): tags = json.loads(params.get("tags")) - # for t in tags: - # tag,_ = Tags.objects.get_or_create(slug=t.lower()) - # opportunity_obj.tags.add(tag) - for tag in tags: obj_tag = Tags.objects.filter(slug=tag.lower()) if obj_tag: @@ -185,26 +184,30 @@ def post(self, request, *args, **kwargs): if params.get("teams"): teams = json.loads(params.get("teams")) for team in teams: - obj_team = Teams.objects.filter( - id=team, company=request.company - ) + obj_team = Teams.objects.filter(id=team) if obj_team: opportunity_obj.teams.add(team) else: opportunity_obj.delete() data["team"] = "Please enter valid Team" - return Response({"error": True, "errors": data}) + return Response( + {"error": True, "errors": data}, + status=status.HTTP_400_BAD_REQUEST, + ) if params.get("assigned_to"): assinged_to_users_ids = json.loads(params.get("assigned_to")) for user_id in assinged_to_users_ids: - user = User.objects.filter(id=user_id, company=request.company) + user = User.objects.filter(id=user_id) if user: opportunity_obj.assigned_to.add(user_id) else: opportunity_obj.delete() data["assigned_to"] = "Please enter valid user" - return Response({"error": True, "errors": data}) + return Response( + {"error": True, "errors": data}, + status=status.HTTP_400_BAD_REQUEST, + ) if self.request.FILES.get("opportunity_attachment"): attachment = Attachments() @@ -220,16 +223,16 @@ def post(self, request, *args, **kwargs): opportunity_obj.assigned_to.all().values_list("id", flat=True) ) - current_site = get_current_site(request) recipients = assigned_to_list send_email_to_assigned_user.delay( recipients, opportunity_obj.id, - domain=current_site.domain, + domain=settings.Domain, protocol=self.request.scheme, ) return Response( - {"error": False, "message": "Opportunity Created Successfully"} + {"error": False, "message": "Opportunity Created Successfully"}, + status=status.HTTP_200_OK, ) return Response( @@ -254,11 +257,6 @@ def put(self, request, pk, format=None): params = request.query_params if len(request.data) == 0 else request.data opportunity_object = self.get_object(pk=pk) data = {} - if opportunity_object.company != request.company: - return Response( - {"error": True, "errors": "User company doesnot match with header...."}, - status=status.HTTP_404_NOT_FOUND, - ) if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: if not ( (self.request.user == opportunity_object.created_by) @@ -269,7 +267,7 @@ def put(self, request, pk, format=None): "error": True, "errors": "You do not have Permission to perform this action", }, - status=status.HTTP_401_UNAUTHORIZED, + status=status.HTTP_403_FORBIDDEN, ) serializer = OpportunityCreateSerializer( @@ -288,20 +286,18 @@ def put(self, request, pk, format=None): if params.get("contacts"): contacts = json.loads(params.get("contacts")) for contact in contacts: - obj_contact = Contact.objects.filter( - id=contact, company=request.company - ) + obj_contact = Contact.objects.filter(id=contact) if obj_contact: opportunity_object.contacts.add(contact) else: data["contacts"] = "Please enter valid Contact" - return Response({"error": True, "errors": data}) + return Response( + {"error": True, "errors": data}, + status=status.HTTP_400_BAD_REQUEST, + ) opportunity_object.tags.clear() if params.get("tags"): tags = json.loads(params.get("tags")) - # for t in tags: - # tag,_ = Tags.objects.get_or_create(name=t.lower()) - # opportunity_object.tags.add(tag) for tag in tags: obj_tag = Tags.objects.filter(slug=tag.lower()) if obj_tag: @@ -320,25 +316,29 @@ def put(self, request, pk, format=None): if params.get("teams"): teams = json.loads(params.get("teams")) for team in teams: - obj_team = Teams.objects.filter( - id=team, company=request.company - ) + obj_team = Teams.objects.filter(id=team) if obj_team: opportunity_object.teams.add(team) else: data["team"] = "Please enter valid Team" - return Response({"error": True, "errors": data}) + return Response( + {"error": True, "errors": data}, + status=status.HTTP_400_BAD_REQUEST, + ) opportunity_object.assigned_to.clear() if params.get("assigned_to"): assinged_to_users_ids = json.loads(params.get("assigned_to")) for user_id in assinged_to_users_ids: - user = User.objects.filter(id=user_id, company=request.company) + user = User.objects.filter(id=user_id) if user: opportunity_object.assigned_to.add(user_id) else: data["assigned_to"] = "Please enter valid User" - return Response({"error": True, "errors": data}) + return Response( + {"error": True, "errors": data}, + status=status.HTTP_400_BAD_REQUEST, + ) if self.request.FILES.get("opportunity_attachment"): attachment = Attachments() @@ -353,12 +353,11 @@ def put(self, request, pk, format=None): assigned_to_list = list( opportunity_object.assigned_to.all().values_list("id", flat=True) ) - current_site = get_current_site(self.request) recipients = list(set(assigned_to_list) - set(previous_assigned_to_users)) send_email_to_assigned_user.delay( recipients, opportunity_object.id, - domain=current_site.domain, + domain=settings.Domain, protocol=self.request.scheme, ) return Response( @@ -372,21 +371,17 @@ def put(self, request, pk, format=None): @swagger_auto_schema( tags=["Opportunities"], - manual_parameters=swagger_params.opportunity_delete_params, ) def delete(self, request, pk, format=None): self.object = self.get_object(pk) - if self.object.company != request.company: - return Response( - {"error": True, "errors": "User company doesnot match with header...."} - ) if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: if self.request.user != self.object.created_by: return Response( { "error": True, "errors": "You do not have Permission to perform this action", - } + }, + status=status.HTTP_403_FORBIDDEN, ) self.object.delete() return Response( @@ -396,15 +391,9 @@ def delete(self, request, pk, format=None): @swagger_auto_schema( tags=["Opportunities"], - manual_parameters=swagger_params.opportunity_delete_params, ) def get(self, request, pk, format=None): self.opportunity = self.get_object(pk=pk) - if self.opportunity.company != request.company: - return Response( - {"error": True, "errors": "User company doesnot match with header...."}, - status=status.HTTP_404_NOT_FOUND, - ) context = {} context["opportunity_obj"] = OpportunitySerializer(self.opportunity).data if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: @@ -416,7 +405,8 @@ def get(self, request, pk, format=None): { "error": True, "errors": "You don't have Permission to perform this action", - } + }, + status=status.HTTP_403_FORBIDDEN, ) comment_permission = ( @@ -433,7 +423,6 @@ def get(self, request, pk, format=None): users_mention = list( User.objects.filter( is_active=True, - company=self.request.company, ).values("username") ) elif self.request.user != self.opportunity.created_by: @@ -458,7 +447,6 @@ def get(self, request, pk, format=None): "users": UserSerializer( User.objects.filter( is_active=True, - company=self.request.company, ).order_by("email"), many=True, ).data, @@ -483,11 +471,6 @@ def post(self, request, pk, **kwargs): ) context = {} self.opportunity_obj = Opportunity.objects.get(pk=pk) - if self.opportunity_obj.company != request.company: - return Response( - {"error": True, "errors": "User company doesnot match with header...."} - ) - comment_serializer = CommentSerializer(data=params) if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: if not ( @@ -499,7 +482,7 @@ def post(self, request, pk, **kwargs): "error": True, "errors": "You don't have Permission to perform this action", }, - status=status.HTTP_401_UNAUTHORIZED, + status=status.HTTP_403_FORBIDDEN, ) if comment_serializer.is_valid(): if params.get("comment"): @@ -571,12 +554,12 @@ def put(self, request, pk, format=None): { "error": True, "errors": "You don't have permission to perform this action.", - } + }, + status=status.HTTP_403_FORBIDDEN, ) @swagger_auto_schema( tags=["Opportunities"], - manual_parameters=swagger_params.opportunity_delete_params, ) def delete(self, request, pk, format=None): self.object = self.get_object(pk) @@ -595,7 +578,8 @@ def delete(self, request, pk, format=None): { "error": True, "errors": "You do not have permission to perform this action", - } + }, + status=status.HTTP_403_FORBIDDEN, ) @@ -606,7 +590,6 @@ class OpportunityAttachmentView(APIView): @swagger_auto_schema( tags=["Opportunities"], - manual_parameters=swagger_params.opportunity_delete_params, ) def delete(self, request, pk, format=None): self.object = self.model.objects.get(pk=pk) @@ -625,5 +608,6 @@ def delete(self, request, pk, format=None): { "error": True, "errors": "You don't have permission to perform this action.", - } + }, + status=status.HTTP_403_FORBIDDEN, ) diff --git a/opportunity/forms.py b/opportunity/forms.py deleted file mode 100644 index 58c02bf..0000000 --- a/opportunity/forms.py +++ /dev/null @@ -1,71 +0,0 @@ -from django import forms -from opportunity.models import Opportunity -from common.models import Comment, Attachments -from teams.models import Teams - - -class OpportunityForm(forms.ModelForm): - probability = forms.IntegerField(max_value=100, required=False) - teams_queryset = [] - teams = forms.MultipleChoiceField(choices=teams_queryset) - - def __init__(self, *args, **kwargs): - assigned_users = kwargs.pop("assigned_to", []) - opp_accounts = kwargs.pop("account", []) - opp_contacts = kwargs.pop("contacts", []) - request_obj = kwargs.pop("request_obj", []) - super(OpportunityForm, self).__init__(*args, **kwargs) - for field in self.fields.values(): - field.widget.attrs = {"class": "form-control"} - self.fields["description"].widget.attrs.update({"rows": "8"}) - if assigned_users: - self.fields["assigned_to"].queryset = assigned_users - self.fields["assigned_to"].required = False - self.fields["account"].queryset = opp_accounts - self.fields["contacts"].queryset = opp_contacts - self.fields["contacts"].required = False - for key, value in self.fields.items(): - value.widget.attrs["placeholder"] = value.label - - self.fields["closed_on"].widget.attrs.update({"placeholder": "Due Date"}) - - self.fields["probability"].widget.attrs.update({"placeholder": "Probability"}) - self.fields["teams"].choices = [ - (team.get("id"), team.get("name")) - for team in Teams.objects.filter(company=request_obj.company).values( - "id", "name" - ) - ] - self.fields["teams"].required = False - - class Meta: - model = Opportunity - fields = ( - "name", - "amount", - "account", - "contacts", - "assigned_to", - "currency", - "probability", - "closed_on", - "lead_source", - "description", - "stage", - ) - - -class OpportunityCommentForm(forms.ModelForm): - comment = forms.CharField(max_length=255, required=True) - - class Meta: - model = Comment - fields = ("comment", "opportunity", "commented_by") - - -class OpportunityAttachmentForm(forms.ModelForm): - attachment = forms.FileField(max_length=1001, required=True) - - class Meta: - model = Attachments - fields = ("attachment", "opportunity") diff --git a/opportunity/migrations/0006_remove_opportunity_company.py b/opportunity/migrations/0006_remove_opportunity_company.py new file mode 100644 index 0000000..7802c8e --- /dev/null +++ b/opportunity/migrations/0006_remove_opportunity_company.py @@ -0,0 +1,17 @@ +# Generated by Django 3.1.7 on 2021-03-24 08:02 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("opportunity", "0005_opportunity_company"), + ] + + operations = [ + migrations.RemoveField( + model_name="opportunity", + name="company", + ), + ] diff --git a/opportunity/models.py b/opportunity/models.py index 83954a5..dc0884b 100644 --- a/opportunity/models.py +++ b/opportunity/models.py @@ -5,7 +5,7 @@ from accounts.models import Account, Tags from contacts.models import Contact -from common.models import User, Company +from common.models import User from common.utils import STAGES, SOURCES, CURRENCY_CODES from teams.models import Teams @@ -48,9 +48,6 @@ class Opportunity(models.Model): is_active = models.BooleanField(default=False) tags = models.ManyToManyField(Tags, blank=True) teams = models.ManyToManyField(Teams, related_name="oppurtunity_teams") - company = models.ForeignKey( - Company, on_delete=models.SET_NULL, null=True, blank=True - ) class Meta: ordering = ["-created_on"] diff --git a/opportunity/serializer.py b/opportunity/serializer.py index d6a229f..e82719f 100644 --- a/opportunity/serializer.py +++ b/opportunity/serializer.py @@ -3,7 +3,7 @@ from accounts.serializer import AccountSerializer from contacts.serializer import ContactSerializer from teams.serializer import TeamsSerializer -from common.serializer import UserSerializer, CompanySerializer, AttachmentsSerializer +from common.serializer import UserSerializer, AttachmentsSerializer from accounts.models import Tags @@ -17,7 +17,6 @@ class OpportunitySerializer(serializers.ModelSerializer): account = AccountSerializer() closed_by = UserSerializer() created_by = UserSerializer() - company = CompanySerializer() tags = TagsSerializer(read_only=True, many=True) assigned_to = UserSerializer(read_only=True, many=True) contacts = ContactSerializer(read_only=True, many=True) @@ -46,7 +45,6 @@ class Meta: "tags", "opportunity_attachment", "teams", - "company", "created_on_arrow", "account", # "get_team_users", @@ -64,12 +62,10 @@ def __init__(self, *args, **kwargs): request_obj = kwargs.pop("request_obj", None) super(OpportunityCreateSerializer, self).__init__(*args, **kwargs) - self.company = request_obj.company - def validate_name(self, name): if self.instance: if ( - Opportunity.objects.filter(name__iexact=name, company=self.company) + Opportunity.objects.filter(name__iexact=name) .exclude(id=self.instance.id) .exists() ): @@ -78,9 +74,7 @@ def validate_name(self, name): ) else: - if Opportunity.objects.filter( - name__iexact=name, company=self.company - ).exists(): + if Opportunity.objects.filter(name__iexact=name).exists(): raise serializers.ValidationError( "Opportunity already exists with this name" ) @@ -101,7 +95,6 @@ class Meta: "created_by", "created_on", "is_active", - "company", "created_on_arrow", # "get_team_users", # "get_team_and_assigned_users", diff --git a/opportunity/swagger_params.py b/opportunity/swagger_params.py index cabc99c..bad0ccd 100644 --- a/opportunity/swagger_params.py +++ b/opportunity/swagger_params.py @@ -1,11 +1,6 @@ from drf_yasg import openapi -company_params_in_header = openapi.Parameter( - "company", openapi.IN_HEADER, required=True, type=openapi.TYPE_STRING -) - opportunity_list_get_params = [ - company_params_in_header, openapi.Parameter("name", openapi.IN_QUERY, type=openapi.TYPE_STRING), openapi.Parameter("account", openapi.IN_QUERY, type=openapi.TYPE_STRING), openapi.Parameter("stage", openapi.IN_QUERY, type=openapi.TYPE_STRING), @@ -14,7 +9,6 @@ ] opportunity_detail_get_params = [ - company_params_in_header, openapi.Parameter( "opportunity_attachment", openapi.IN_QUERY, @@ -23,12 +17,7 @@ openapi.Parameter("comment", openapi.IN_QUERY, type=openapi.TYPE_STRING), ] -opportunity_delete_params = [ - company_params_in_header, -] - opportunity_create_post_params = [ - company_params_in_header, openapi.Parameter( "name", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING ), @@ -54,6 +43,5 @@ ] opportunity_comment_edit_params = [ - company_params_in_header, openapi.Parameter("comment", openapi.IN_QUERY, type=openapi.TYPE_STRING), ] diff --git a/opportunity/tasks.py b/opportunity/tasks.py index 0974a10..8b0d039 100644 --- a/opportunity/tasks.py +++ b/opportunity/tasks.py @@ -7,7 +7,6 @@ from accounts.models import User from opportunity.models import Opportunity -from marketing.models import BlockedDomain, BlockedEmail app = Celery("redis://") @@ -19,31 +18,21 @@ def send_email_to_assigned_user( """ Send Mail To Users When they are assigned to a opportunity """ opportunity = Opportunity.objects.get(id=opportunity_id) created_by = opportunity.created_by - blocked_domains = BlockedDomain.objects.values_list("domain", flat=True) - blocked_emails = BlockedEmail.objects.values_list("email", flat=True) for user in recipients: recipients_list = [] user = User.objects.filter(id=user, is_active=True).first() if user: - if (user.email not in blocked_emails) and ( - user.email.split("@")[-1] not in blocked_domains - ): - recipients_list.append(user.email) - context = {} - context["url"] = ( - protocol - + "://" - + domain - + reverse("opportunity:opp_view", args=(opportunity.id,)) - ) - context["user"] = user - context["opportunity"] = opportunity - context["created_by"] = created_by - subject = "Assigned an opportunity for you." - html_content = render_to_string( - "assigned_to/opportunity_assigned.html", context=context - ) + recipients_list.append(user.email) + context = {} + context["url"] = protocol + "://" + domain + context["user"] = user + context["opportunity"] = opportunity + context["created_by"] = created_by + subject = "Assigned an opportunity for you." + html_content = render_to_string( + "assigned_to/opportunity_assigned.html", context=context + ) - msg = EmailMessage(subject, html_content, to=recipients_list) - msg.content_subtype = "html" - msg.send() + msg = EmailMessage(subject, html_content, to=recipients_list) + msg.content_subtype = "html" + msg.send() diff --git a/opportunity/templates/create_opportunity.html b/opportunity/templates/create_opportunity.html deleted file mode 100644 index c5c6831..0000000 --- a/opportunity/templates/create_opportunity.html +++ /dev/null @@ -1,666 +0,0 @@ -{% extends 'sales/base.html' %} -{% load static %} -{% block breadcrumb %} - -{% endblock %} -{% block content %} - - - - - -
      -
      -
      -
      -
      -
      - {% if opportunity_obj %}EDIT{% else %}CREATE{% endif %} OPPORTUNITY -
      -
      -
      -
      -
      - - {{ opportunity_form.name }} - {{opportunity_form.name.errors}} -
      -
      -
      -
      - - {% if account %} - - {% else %} - {{opportunity_form.account}} - {% endif %} - {{opportunity_form.account.errors}} -
      -
      -
      -
      - - {{ opportunity_form.amount }} - {{opportunity_form.amount.errors}} -
      -
      -
      -
      - - - {{opportunity_form.currency.errors}} -
      -
      -
      -
      - - {{ opportunity_form.stage }} - {{opportunity_form.stage.errors}} -
      -
      -
      -
      -
      -
      - - {{ opportunity_form.lead_source }} - {{opportunity_form.lead_source.errors}} -
      -
      -
      -
      - - {{ opportunity_form.probability }} - {{opportunity_form.probability.errors}} -
      -
      - {% if request.user.is_superuser or request.user.role == 'ADMIN' %} -
      -
      - - - {{ opportunity_form.teams.errors }} -
      -
      - -
      -
      - - -
      -
      - - {% endif %} -
      -
      - - -
      -
      -
      -
      - - {{ opportunity_form.contacts }} - {{opportunity_form.contacts.errors}} -
      -
      -
      -
      - -
      - {{ opportunity_form.closed_on }} - - - -
      - {{opportunity_form.closed_on.errors}} -
      -
      -
      -
      -
      -
      - -
      -
      -
      -
      -
      - - {{ opportunity_form.description }} - {{opportunity_form.description.errors}} -
      -
      -
      - - - {% if opportunity_obj.opportunity_attachment.count %} - {% for attachment in opportunity_obj.opportunity_attachment.all %} -
      - {{ attachment.file_name }} - {% if not attachment.created_by.role == 'ADMIN' or attachment.created_by.role == request.user.role %} - X - {% endif %} -
      - {% endfor %} - {% endif %} - -
      -
      -
      -
      -
      - - {% if request.GET.view_account %} - - {% endif %} - -
      - -
      - - {% if not opportunity_obj %} - - {% endif %} - Cancel -
      -
      -
      -
      -
      -
      - -
      - 0% -
      -
      -
      -{% endblock %} -{% block js_block %} - - -{% endblock js_block %} \ No newline at end of file diff --git a/opportunity/templates/opp_contacts.html b/opportunity/templates/opp_contacts.html deleted file mode 100644 index 9889011..0000000 --- a/opportunity/templates/opp_contacts.html +++ /dev/null @@ -1,5 +0,0 @@ - \ No newline at end of file diff --git a/opportunity/templates/opportunities_list.html b/opportunity/templates/opportunities_list.html deleted file mode 100644 index c23f8ce..0000000 --- a/opportunity/templates/opportunities_list.html +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - {% ifequal opportunities|length 0 %} - - - - {% endifequal %} - {% for opportunity in opportunities %} - - - - - {% endfor %} - -
      - - Name - - - - - Stage - -
      - NO OPPORTUNITIES FOUND!! -
      - - {{ opportunity.name }} - - - {{ opportunity.stage }} -
      diff --git a/opportunity/templates/opportunity.html b/opportunity/templates/opportunity.html deleted file mode 100644 index 8bae1a5..0000000 --- a/opportunity/templates/opportunity.html +++ /dev/null @@ -1,412 +0,0 @@ -{% extends "sales/base.html" %} -{% load static %} -{% load paginate %} -{% load thumbnail %} -{% block extralinks %} - -{% endblock %} -{% block content %} - -
      - - - -
      -
      -
      -
      -
      -
      -
      Filters
      -
      -
      -
      - - -
      -
      -
      -
      - - -
      -
      -
      -
      - - -
      -
      -
      -
      - - -
      -
      -
      -
      - - -
      -
      -
      -
      - - Clear -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      - -
      -
      - Opportunities - {% if show_pageitems %} {% show_pageitems %}{% else %} - {{ opportunity_list|length }}{% endif %} - - - - -
      -
      - - - {% if opportunity_list|length > 0 %} - - - - - - - - - - - - - - {% endif %} - - - {% if per_page %} - {% paginate per_page opportunity_list %} - {% else %} - {% paginate 10 opportunity_list %} - {% endif %} - {% for opportunity in opportunity_list %} - - - - - - - - - - - - - {% endfor %} - -
      S.NoNameAssigned ToTagsAccountStageCreated OnLead SourceActions
      {{ forloop.counter }}{{ opportunity.name }} - {% with opportunity_users=opportunity.get_team_and_assigned_users %} - {% for user in opportunity_users %} - {% if user.profile_pic %} - {% thumbnail user.profile_pic "40x40" crop="center" as im %} - - - - {% endthumbnail %} - {% else %} - - - - {% endif %} - {% empty %} - None - {% endfor %} - {% endwith %} - - {% with tags=opportunity.tags.all %} - {% if tags %} - {% for tag in tags %} - {{ tag.name }} - {% endfor %} - {% else %} - No Tags - {% endif %} - {% endwith %} - - {% if opportunity.account %} - {{ opportunity.account }} - {% else %} - No Related Account - {% endif %} - {% if opportunity.stage %}{{ opportunity.stage }}{% else %}Not Specified {% endif %}{{opportunity.created_on_arrow}}{% if opportunity.lead_source %}{{ opportunity.lead_source }}{% else %}Not Specified{% endif %} - - - - {% if request.user == opportunity.created_by or request.user.role == "ADMIN" or request.user.is_superuser %} - - {% endif %} -
      -
      - {% ifequal opportunity_list|length 0 %} -
      No Opportunity Records Found
      - {% endifequal %} -
      - {% show_pages %} -
      -
      - -
      -
      -
      -
      - - -
      - - -{% for opportunity_record in opportunity_list %} - -
    • {{ contact }}
    • - {% endfor %} - - - {% endif %} - -
      - {% if opportunity_record.amount %} -
      - -
      - {{ opportunity_record.currency }} {{ opportunity_record.amount }}
      -
      - {% endif %} -
      - -
      -
      - {% if opportunity_record.stage %} -
      - -
      - {{ opportunity_record.stage }} -
      -
      - {% endif %} -
      -
      - {% if opportunity_record.lead_source %} -
      - -
      - {{ opportunity_record.lead_source }}
      -
      - {% endif %} -
      -
      - {% if opportunity_record.probability %} -
      - -
      - {{opportunity_record.probability}} %
      -
      - {% endif %} -
      -
      - {% if opportunity_record.closed_on %} -
      - -
      - {{opportunity_record.closed_on|date}}
      -
      - {% endif %} -
      -
      -
      - {% if opportunity_record.tags.all %} -
      -
      - - -
      -
      - {% endif %} -
      -
      - {% if opportunity_record.description %} -
      -
      - -
      - {{opportunity_record.description}}
      -
      -
      - {% endif %} -
      - Created by {{ opportunity_record.created_by }} created on - {{ opportunity_record.created_on_arrow }} -
      -
      - - - - - - - - - - - - - - -{% endfor %} - -{% endblock %} -{% block js_block %} - -{% endblock js_block %} \ No newline at end of file diff --git a/opportunity/templates/opportunity_comments.html b/opportunity/templates/opportunity_comments.html deleted file mode 100644 index ac484d6..0000000 --- a/opportunity/templates/opportunity_comments.html +++ /dev/null @@ -1,17 +0,0 @@ -{% for comment in comments %} -
    • -
      -
      - - -
      -
      -
      {{comment.comment_person}} Commented
      -
      {{comment.comment}}
      -
      {{comment.comment_time}}
      - {% endfor %} \ No newline at end of file diff --git a/opportunity/templates/view_opportunity.html b/opportunity/templates/view_opportunity.html deleted file mode 100644 index fdd2584..0000000 --- a/opportunity/templates/view_opportunity.html +++ /dev/null @@ -1,509 +0,0 @@ -{% extends 'sales/base.html' %} -{% load static %} -{% load thumbnail %} -{% block breadcrumb %} -{% block extralinks %} - - -{% endblock extralinks %} - - - -{% endblock%} -{% block content%} - -
      -
      -
      -
      -
      -
      -
      - OVERVIEW - - - -
      -
      -
      -
      -
      -
      - -
      {{ opportunity_record.name }} -
      -
      -
      -
      -
      - -
      - {{ opportunity_record.account }}
      -
      -
      -
      - {% if opportunity_record.contacts.all %} -
      - -
      - {% for contact in opportunity_record.contacts.all %} -
    • {{ contact }}
    • - {% endfor %} - - - {% endif %} - -
      - {% if opportunity_record.amount %} -
      - -
      - {{ opportunity_record.currency }} {{ opportunity_record.amount }}
      -
      - {% endif %} -
      - -
      -
      - {% if opportunity_record.stage %} -
      - -
      {{ opportunity_record.stage }} -
      -
      - {% endif %} -
      -
      - {% if opportunity_record.lead_source %} -
      - -
      - {{ opportunity_record.lead_source }}
      -
      - {% endif %} -
      -
      - {% if opportunity_record.probability %} -
      - -
      - {{opportunity_record.probability}} %
      -
      - {% endif %} -
      -
      - {% if opportunity_record.closed_on %} -
      - -
      - {{opportunity_record.closed_on|date}}
      -
      - {% endif %} -
      -
      -
      -
      - {% if opportunity_record.description %} -
      - -
      - {{opportunity_record.description}}
      -
      - {% endif %} -
      - {% if opportunity_record.tags.all %} -
      -
      - - -
      -
      - {% endif %} -
      -
      -
      - Created by {{ opportunity_record.created_by }} created on - {{ opportunity_record.created_on_arrow }} -
      -
      - - - -
      -
      -
      -
      Attachments
      -
      -
      -
      -
      -
      - -
      - -
      -
      -
      - -
      -
      - -
      -
        - {% for attachment in attachments %} -
      • - {% if request.user.is_superuser or request.user.role == 'ADMIN' or request.user == attachment.created_by %} -
        -
        - -
        -
        - {% endif %} - -
        - {% if attachment.attachment %} - {% if 'image' in attachment.file_type %} - {% thumbnail attachment.attachment "80x80" crop="center" as im %} - - {% endthumbnail %} - {% endif %} - {% endif %} -
          {{attachment.file_name}} Download
        -
        - -
        -
         Uploaded by : {{ attachment.created_by }}
        -
        {{ attachment.created_on_arrow }}
        -
        -
      • - {% endfor %} -
      -
      -
      -
      - - -
      -
      -
      Comments
      -
      -
      -
      -
      -
      - -
      - -
      -
      -
      - -
      -
      - -
      -
        - {% for comment in comments %} -
      • - {% if request.user.is_superuser or request.user.role == 'ADMIN' or request.user == comment.commented_by %} -
        -
        - - -
        -
        - {% endif %} -
        -
        {{ comment.comment }}
        -
        -
        -
        {{ comment.commented_by }}
        -
        {{ comment.commented_on_arrow }}
        -
        -
      • - {% endfor %} -
      -
      -
      - -
      - -
      - - -
      - -
      - Processing File... -
      -
      - - - -{% endblock %} - -{% block js_block %} - - - - - - -{% endblock js_block %} \ No newline at end of file diff --git a/opportunity/tests.py b/opportunity/tests.py deleted file mode 100644 index 60eebf3..0000000 --- a/opportunity/tests.py +++ /dev/null @@ -1,754 +0,0 @@ -from django.core.files.uploadedfile import SimpleUploadedFile -from django.shortcuts import reverse -from django.test import TestCase -from django.utils.encoding import force_text - -from accounts.models import Account, Tags -from cases.models import Case -from common.models import Address, Attachments, Comment, User, Company -from contacts.models import Contact -from opportunity.models import Opportunity -from teams.models import Teams - -# Create your tests here. - - -class OpportunityModel(object): - def setUp(self): - self.company, _ = Company.objects.get_or_create( - name="test company", address="IN", sub_domain="test", country="IN" - ) - - self.user = User.objects.create( - first_name="jane doe", - username="jane doe Opp", - email="janeOpp@example.com", - role="ADMIN", - company=self.company, - ) - self.user.set_password("password") - self.user.save() - - self.user1 = User.objects.create( - first_name="john doe", - username="john doe opportunity", - email="johnOpp@example.com", - role="USER", - company=self.company, - ) - self.user1.set_password("password") - self.user1.save() - - self.user2 = User.objects.create( - first_name="john doe", - username="jane doe opportunity", - email="janeDoeOpp@example.com", - role="USER", - has_sales_access=True, - company=self.company, - ) - self.user2.set_password("password") - self.user2.save() - - self.user3 = User.objects.create( - first_name="john doe", - username="joe doe opportunity", - email="joeDoeOpp@example.com", - role="USER", - has_sales_access=True, - company=self.company, - ) - self.user3.set_password("password") - self.user3.save() - - self.address = Address.objects.create( - street="", city="city name", postcode="1234", country="IN" - ) - - self.client.login(email="janeOpp@example.com", password="password") - - self.account = Account.objects.create( - name="john", - email="johndoe@example.com", - phone="1234", - billing_address_line="", - billing_street="street", - billing_city="city", - billing_postcode="1234", - billing_country="IN", - website="example.com", - industry="", - description="account description", - created_by=self.user, - ) - - self.contacts = Contact.objects.create( - first_name="joe", - last_name="doe", - email="joedoe@example", - phone="1234", - description="description for contact", - address=self.address, - created_by=self.user, - ) - - self.opportunity = Opportunity.objects.create( - name="jane opportunity", - amount="478", - stage="negotiation/review", - lead_source="Call", - probability="58", - closed_on="2016-05-04", - account=self.account, - description="opportunity description", - created_by=self.user, - ) - self.opportunity.assigned_to.add(self.user) - - self.opportunity_1 = Opportunity.objects.create( - name="new opportunity", - amount="478", - stage="negotiation/review", - probability="92", - closed_on="2016-05-04", - description="opportunity description", - created_by=self.user, - ) - - self.opportunity_2 = Opportunity.objects.create( - name="joe opportunity", - amount="478", - stage="negotiation/review", - probability="92", - closed_on="2016-05-04", - description="opportunity description", - created_by=self.user3, - ) - - self.case = Case.objects.create( - name="case name", - case_type="Problem", - status="New", - account=self.account, - priority="Low", - description="case description", - created_by=self.user, - closed_on="2016-05-04", - ) - self.comment = Comment.objects.create( - comment="test comment", case=self.case, commented_by=self.user - ) - self.attachment = Attachments.objects.create( - attachment="image.png", - case=self.case, - created_by=self.user, - account=self.account, - opportunity=self.opportunity, - ) - - self.tag_1 = Tags.objects.create(name="tag9") - self.tag_2 = Tags.objects.create(name="tag10") - self.tag_3 = Tags.objects.create(name="tag11") - - -class OpportunityCreateTestCase(OpportunityModel, TestCase): - def test_opportunity_create(self): - response = self.client.get( - "/opportunities/create/", - { - "name": "opportunity test", - "amount": "478", - "stage": "NEGOTIATION/REVIEW", - "lead_source": "Call", - "probability": "58", - "closed_on": "2016-05-04", - "description": "description", - }, - ) - self.assertEqual(response.status_code, 200) - - def test_opportunity_create_post(self): - upload_file = open("static/images/user.png", "rb") - url = "/opportunities/create/" - data = { - "name": "jane opportunity", - "amount": "500", - "stage": "CLOSED WON", - "assigned_to": str(self.user.id), - "contacts": str(self.contacts.id), - "tags": "tag", - "from_account": self.account.id, - "oppurtunity_attachment": SimpleUploadedFile( - upload_file.name, upload_file.read() - ), - } - response = self.client.post(url, data) - # self.assertEqual(response.status_code, 302) - self.assertEqual(response.status_code, 200) - - def test_opportunity_invalid(self): - url = "/opportunities/create/" - data = {"name": "jane", "amount": "", "stage": ""} - response = self.client.post(url, data) - self.assertEqual(response.status_code, 200) - - -class opportunityCreateTestCase(OpportunityModel, TestCase): - def test_view_opportunity(self): - response = self.client.get( - "/opportunities/" + str(self.opportunity.id) + "/view/" - ) - self.assertEqual(response.status_code, 200) - self.assertEqual(response.context["opportunity_record"].id, self.opportunity.id) - - def test_del_opportunity_url(self): - response = self.client.get( - "/opportunities/" + str(self.opportunity.id) + "/delete/" - ) - self.assertEqual(response["location"], "/opportunities/") - - def test_opportunity_delete(self): - Opportunity.objects.filter(id=self.account.id).delete() - response = self.client.get(reverse("opportunity:list")) - self.assertEqual(response.status_code, 200) - - -class EditOpportunityTestCase(OpportunityModel, TestCase): - def test_edit_url(self): - response = self.client.get( - "/opportunities/" + str(self.opportunity.id) + "/edit/" - ) - self.assertEqual(response.status_code, 200) - - def test_edit_opportunity(self): - response = self.client.get( - "/opportunities/" + str(self.opportunity.id) + "/edit/", - { - "name": "joe", - "amount": "478", - "stage": "negotiation/review", - "lead_source": "Call", - "probability": "58", - "closed_on": "2016-05-04", - "description": "description", - }, - ) - resp = self.client.post( - "/opportunities/" + str(self.opportunity.id) + "/edit/", - **{"HTTP_X_REQUESTED_WITH": "XMLHttpRequest"} - ) - self.assertEqual(resp.status_code, 200) - resp1 = self.client.post( - "/opportunities/create/", **{"HTTP_X_REQUESTED_WITH": "XMLHttpRequest"} - ) - self.assertEqual(resp1.status_code, 200) - - def test_update_opportunity(self): - upload_file = open("static/images/user.png", "rb") - url = "/opportunities/" + str(self.opportunity.id) + "/edit/" - data = { - "name": "jane", - "amount": "478", - "stage": "QUALIFICATION", - "probability": "58", - "closed_on": "2016-05-04", - "description": "description", - "tags": "tag", - "assigned_to": str(self.user.id), - "contacts": str(self.contacts.id), - "oppurtunity_attachment": SimpleUploadedFile( - upload_file.name, upload_file.read() - ), - } - response = self.client.post(url, data) - # self.assertEqual(response.status_code, 302) - self.assertEqual(response.status_code, 200) - - def test_update_opportunity_invalid(self): - url = "/opportunities/" + str(self.opportunity.id) + "/edit/" - data = { - "name": "", - "amount": "478", - "stage": "", - "probability": "58", - "closed_on": "2016-05-04", - "description": "description", - } - response = self.client.post(url, data) - self.assertEqual(response.status_code, 200) - - -class OpportunityListView(OpportunityModel, TestCase): - def test_opportunity_list(self): - self.opportunity = Opportunity.objects.all() - response = self.client.get(reverse("opportunity:list")) - self.assertEqual(response.status_code, 200) - self.assertTemplateUsed(response, "opportunity.html") - - def test_opportunity_list_queryset(self): - self.account = Account.objects.all() - data = { - "name": "joe", - "stage": "city", - "lead_source": "Call", - "accounts": self.account, - } - response = self.client.post(reverse("opportunity:list"), data) - get_opp_val = Opportunity.objects.get(lead_source="Call") - self.assertEqual(get_opp_val.lead_source, "Call") - self.assertEqual(get_opp_val.name, str(get_opp_val)) - get_contact = Contact.objects.get(last_name="doe") - # get_account = Account.objects.get(name='john') # not done - # print(get_account.name,"wqieoruopwqeiruqrewiou") - # print(self.account.last()) - self.assertEqual(get_contact.last_name, "doe") - # self.assertEqual(get_account, self.account.last()) # not done - # self.assertEqual(get_opp_val.lead_source,'call') - self.assertEqual(response.status_code, 200) - self.assertTemplateUsed(response, "opportunity.html") - - -class ContactGetViewTestCase(OpportunityModel, TestCase): - def test_get_contact(self): - url = "/opportunities/contacts/" - response = self.client.get(url) - get_contact = Contact.objects.get(last_name="doe") - self.assertEqual(get_contact.last_name, "doe") - self.assertEqual(response.status_code, 200) - - -class CommentTestCase(OpportunityModel, TestCase): - def test_comment_add(self): - self.client.login(email="mp@micropyramid.com", password="mp") - response = self.client.post( - "/opportunities/comment/add/", {"opportunityid": self.opportunity.id} - ) - self.assertEqual(response.status_code, 200) - - def test_comment_create(self): - response = self.client.post( - "/opportunities/comment/add/", - {"opportunityid": self.opportunity.id, "comment": "comment"}, - ) - self.assertEqual(response.status_code, 200) - - def test_comment_edit(self): - response = self.client.post( - "/opportunities/comment/edit/", {"commentid": self.comment.id} - ) - self.assertEqual(response.status_code, 200) - - def test_comment_update(self): - response = self.client.post( - "/opportunities/comment/edit/", - {"commentid": self.comment.id, "comment": "comment"}, - ) - self.assertEqual(response.status_code, 200) - - def test_comment_delete(self): - response = self.client.post( - "/opportunities/comment/remove/", {"comment_id": self.comment.id} - ) - self.assertEqual(response.status_code, 200) - - def test_comment_form_valid(self): - response = self.client.post( - "/opportunities/comment/add/", - {"opportunityid": self.opportunity.id, "comment": "hello"}, - ) - self.assertEqual(response.status_code, 200) - - -class AttachmentTestCase(OpportunityModel, TestCase): - def test_attachment_create(self): - self.client.login(email="johnOpp@example.com", password="password") - url = "/opportunities/attachment/add/" - data = {"opportunityid": self.opportunity.id} - response = self.client.post(url, data) - self.assertEqual(response.status_code, 200) - - def test_attachment_add(self): - upload_file = open("static/images/user.png", "rb") - url = "/opportunities/attachment/add/" - data = { - "opportunityid": self.opportunity.id, - "attachment": SimpleUploadedFile(upload_file.name, upload_file.read()), - } - response = self.client.post(url, data) - self.assertEqual(response.status_code, 200) - data = {"opportunityid": self.opportunity.id} - self.assertEqual(response.status_code, 200) - - def test_attachment_delete(self): - url = "/opportunities/attachment/remove/" - data = {"attachment_id": self.attachment.id} - response = self.client.post(url, data) - self.assertEqual(response.status_code, 200) - - def test_attachment_deletion(self): - self.client.login(email="johnOpp@example.com", password="password") - url = "/opportunities/attachment/remove/" - data = {"attachment_id": self.attachment.id} - response = self.client.post(url, data) - self.assertEqual(response.status_code, 200) - - -class TestGetOpportunitiesView(OpportunityModel, TestCase): - def test_get_page(self): - url = "/opportunities/get/list/" - resp = self.client.get(url) - self.assertEqual(resp.status_code, 200) - self.assertIsNotNone(resp.context["opportunities"]) - - -class TestOpportunityListViewForUser(OpportunityModel, TestCase): - def test_queryset_for_user(self): - - self.usermp = User.objects.create( - first_name="john", - username="johndoeopportunity@example.com", - email="johndoeopportunity@example.com", - role="USER", - has_sales_access=True, - company=self.company, - ) - self.usermp.set_password("password") - self.usermp.save() - - self.usermp1 = User.objects.create( - first_name="jane", - username="johndoeopportunity1@example.com", - email="johndoeopportunity1@example.com", - role="USER", - company=self.company, - ) - self.usermp1.set_password("password") - self.usermp1.save() - - self.opportunity = Opportunity.objects.create( - name="john jane doe", - amount="478", - stage="negotiation/review", - lead_source="Call", - probability="58", - closed_on="2016-05-04", - description="sample description", - created_by=self.usermp, - ) - - self.client.login(email="johndoeopportunity@example.com", password="password") - response = self.client.get(reverse("opportunity:list")) - self.assertEqual(response.status_code, 200) - - response = self.client.post( - reverse("opportunity:list"), - {"account": self.account.id, "contacts": self.contacts.id}, - ) - self.assertEqual(response.status_code, 200) - - self.account_mp = Account.objects.create( - name="john doe", - email="johnAccount@example.com", - phone="911234567892", - billing_address_line="", - billing_street="", - billing_city="city ", - billing_state="state", - billing_postcode="12345", - billing_country="IN", - website="www.example.com", - created_by=self.usermp, - status="open", - industry="SOFTWARE", - description="test description", - ) - - self.address = Address.objects.create( - street="street name", - city="city name", - state="state name", - postcode=1234, - country="IN", - ) - - self.contact_mp = Contact.objects.create( - first_name="john contact", - email="johnDoeContact@example.com", - address=self.address, - description="contact description", - created_by=self.usermp, - ) - # self.contact_mp.assigned_to.add(self.usermp) - - response = self.client.get(reverse("opportunity:save")) - self.assertEqual(response.status_code, 200) - - response = self.client.post( - reverse("opportunity:save"), - {"name": "sample test", "stage": "CLOSED WON", "tags": "tag11"}, - ) - self.assertEqual(response.status_code, 200) - - response = self.client.get( - reverse("opportunity:opp_edit", args=(self.opportunity.id,)) - ) - self.assertEqual(200, response.status_code) - - response = self.client.post( - reverse("opportunity:opp_edit", args=(self.opportunity.id,)), - { - "name": "sample update", - "stage": "CLOSED WON", - "assigned_to": str(self.user.id), - "tags": "tag11", - }, - ) - self.assertEqual(200, response.status_code) - - response = self.client.post( - reverse("opportunity:opp_edit", args=(self.opportunity.id,)), - {"name": "sample update", "stage": "CLOSED WON", "tags": "tag11"}, - ) - self.assertEqual(200, response.status_code) - - response = self.client.post( - "/opportunities/comment/add/", {"opportunityid": self.opportunity.id} - ) - self.assertJSONEqual( - force_text(response.content), {"error": ["This field is required."]} - ) - - self.comment = Comment.objects.create( - comment="testikd", case=self.case, commented_by=self.usermp - ) - response = self.client.post( - "/opportunities/comment/edit/", {"commentid": self.comment.id} - ) - self.assertJSONEqual( - force_text(response.content), {"error": ["This field is required."]} - ) - - self.client.logout() - - def test_detail_view_error(self): - self.usermp_2 = User.objects.create( - first_name="johnDoe", - username="johnDoe@user.com", - email="johnDoe@user.com", - role="USER", - company=self.company, - ) - self.usermp_2.set_password("password") - self.usermp_2.save() - self.client.login(email="johnDoe@user.com", password="password") - - response = self.client.get( - reverse("opportunity:opp_view", args=(self.opportunity.id,)) - ) - self.assertEqual(403, response.status_code) - - response = self.client.post( - reverse("opportunity:opp_remove", args=(self.opportunity.id,)), - {"pk": self.opportunity.id}, - ) - self.assertEqual(403, response.status_code) - - def test_update_opportunity_error(self): - self.usermp_3 = User.objects.create( - first_name="janedoe", - username="janedoe@user.com", - email="janedoe@user.com", - role="USER", - company=self.company, - ) - self.usermp_3.set_password("password") - self.usermp_3.save() - self.client.login(email="janedoe@user.com", password="password") - - self.usermp4 = User.objects.create( - first_name="johnDoe", - username="janeJohn@user.com", - email="janeJohn@user.com", - role="USER", - company=self.company, - ) - self.usermp4.set_password("password") - self.usermp4.save() - - self.opportunity2 = Opportunity.objects.create( - name="jane oppurtunity", - amount="478", - stage="negotiation/review", - lead_source="Call", - probability="58", - closed_on="2016-05-04", - description="description", - created_by=self.usermp4, - ) - - response = self.client.get( - reverse("opportunity:opp_edit", args=(self.opportunity2.id,)) - ) - self.assertEqual(403, response.status_code) - - -class CommentTestCaseError(OpportunityModel, TestCase): - def test_comment_add(self): - - self.client.login(email="johnOpp@example.com", password="password") - response = self.client.post( - "/opportunities/comment/add/", {"opportunityid": self.opportunity.id} - ) - self.assertJSONEqual( - force_text(response.content), - {"error": "You don't have permission to comment."}, - ) - - self.usermp5 = User.objects.create( - first_name="janeD", - username="joeDoe@user.com", - email="joeDoe@user.com", - role="USER", - company=self.company, - ) - self.usermp5.set_password("password") - self.usermp5.save() - - self.comment_mp = Comment.objects.create( - comment="comment", case=self.case, commented_by=self.user - ) - - response = self.client.post( - "/opportunities/comment/edit/", {"commentid": self.comment_mp.id} - ) - self.assertJSONEqual( - force_text(response.content), - {"error": "You don't have permission to edit this comment."}, - ) - - response = self.client.post( - "/opportunities/comment/remove/", {"comment_id": self.comment_mp.id} - ) - self.assertJSONEqual( - force_text(response.content), - {"error": "You don't have permission to delete this comment."}, - ) - - -class AttachmentTestCaseError(OpportunityModel, TestCase): - def test_attachment_add(self): - url = "/opportunities/attachment/add/" - response = self.client.post(url, {"opportunityid": self.opportunity.id}) - self.assertJSONEqual( - force_text(response.content), {"error": ["This field is required."]} - ) - - response = self.client.get( - reverse("opportunity:list") + "?tag={}".format(self.tag_1.id) - ) - self.assertEqual(200, response.status_code) - - response = self.client.post( - reverse("opportunity:list") + "?tag={}".format(self.tag_1.id), - { - "tag": self.tag_1.id, - }, - ) - self.assertEqual(200, response.status_code) - - self.team_opp = Teams.objects.create(name="opp team") - self.team_opp.users.add(self.user1.id) - self.client.logout() - self.client.login(email="janeOpp@example.com", password="password") - data = { - "name": "opportunity teams", - "stage": "QUALIFICATION", - "teams": self.team_opp.id, - "savenewform": "true", - } - response = self.client.post(reverse("opportunity:save"), data) - self.assertEqual(200, response.status_code) - - response = self.client.get( - reverse("opportunity:save") + "?view_account={}".format(self.account.id) - ) - self.assertEqual(200, response.status_code) - - response = self.client.get( - reverse("opportunity:opp_view", args=(self.opportunity_1.id,)) - ) - self.assertEqual(200, response.status_code) - - self.client.logout() - self.client.login(email="janeDoeOpp@example.com", password="password") - response = self.client.get( - reverse("opportunity:opp_view", args=(self.opportunity.id,)) - ) - self.assertEqual(403, response.status_code) - - self.client.logout() - self.client.login(email="joeDoeOpp@example.com", password="password") - response = self.client.get( - reverse("opportunity:opp_view", args=(self.opportunity_2.id,)) - ) - self.assertEqual(200, response.status_code) - - self.client.logout() - self.client.login(email="janeOpp@example.com", password="password") - data = { - "name": "opportunity teams edit", - "stage": "QUALIFICATION", - "teams": self.team_opp.id, - "savenewform": "true", - "from_account": self.account.id, - } - response = self.client.post( - reverse("opportunity:opp_edit", args=(self.opportunity_2.id,)), data - ) - self.assertEqual(200, response.status_code) - - response = self.client.get( - reverse("opportunity:opp_edit", args=(self.opportunity_2.id,)) - + "?view_account={}".format(self.account.id) - ) - self.assertEqual(200, response.status_code) - - self.client.logout() - self.client.login(email="joeDoeOpp@example.com", password="password") - response = self.client.get( - reverse("opportunity:opp_edit", args=(self.opportunity_1.id,)), data - ) - self.assertEqual(403, response.status_code) - - self.client.logout() - self.client.login(email="janeOpp@example.com", password="password") - response = self.client.get( - reverse("opportunity:opp_remove", args=(self.opportunity_1.id,)), - { - "pk": self.opportunity_1.id, - }, - HTTP_X_REQUESTED_WITH="XMLHttpRequest", - ) - - self.client.logout() - self.client.login(email="joeDoeOpp@example.com", password="password") - response = self.client.post( - reverse("opportunity:opp_remove", args=(self.opportunity.id,)) - + "?view_account={}".format(self.account.id), - {"pk": self.opportunity.id}, - ) - self.assertEqual(403, response.status_code) - - self.client.logout() - self.client.login(email="janeOpp@example.com", password="password") - response = self.client.post( - reverse("opportunity:opp_remove", args=(self.opportunity_2.id,)) - + "?view_account={}".format(self.account.id), - {"pk": self.opportunity_2.id}, - ) - self.assertEqual(302, response.status_code) - - response = self.client.get( - reverse("opportunity:contacts") + "?account={}".format(self.account.id) - ) - self.assertEqual(200, response.status_code) diff --git a/opportunity/urls.py b/opportunity/urls.py deleted file mode 100644 index 973f2f1..0000000 --- a/opportunity/urls.py +++ /dev/null @@ -1,38 +0,0 @@ -from django.urls import path -from opportunity.views import ( - OpportunityListView, - create_opportunity, - OpportunityDetailView, - update_opportunity, - DeleteOpportunityView, - GetContactView, - GetOpportunitiesView, - AddCommentView, - get_teams_and_users, - UpdateCommentView, - DeleteCommentView, - AddAttachmentsView, - DeleteAttachmentsView, -) - - -app_name = "opportunity" - - -urlpatterns = [ - path("", OpportunityListView.as_view(), name="list"), - path("create/", create_opportunity, name="save"), - path("/view/", OpportunityDetailView.as_view(), name="opp_view"), - path("/edit/", update_opportunity, name="opp_edit"), - path("/delete/", DeleteOpportunityView.as_view(), name="opp_remove"), - path("contacts/", GetContactView.as_view(), name="contacts"), - path("get/list/", GetOpportunitiesView.as_view(), name="get_opportunity"), - path("comment/add/", AddCommentView.as_view(), name="add_comment"), - path("comment/edit/", UpdateCommentView.as_view(), name="edit_comment"), - path("comment/remove/", DeleteCommentView.as_view(), name="remove_comment"), - path("attachment/add/", AddAttachmentsView.as_view(), name="add_attachment"), - path( - "attachment/remove/", DeleteAttachmentsView.as_view(), name="remove_attachment" - ), - path("get_teams_and_users/", get_teams_and_users, name="get_teams_and_users"), -] diff --git a/opportunity/views.py b/opportunity/views.py deleted file mode 100644 index b1a77cc..0000000 --- a/opportunity/views.py +++ /dev/null @@ -1,702 +0,0 @@ -import json -from django.contrib.auth.decorators import login_required -from django.contrib.auth.mixins import LoginRequiredMixin -from django.contrib.sites.shortcuts import get_current_site -from django.core.mail import EmailMessage -from django.http import JsonResponse -from django.shortcuts import get_object_or_404, redirect, render -from django.template.loader import render_to_string -from django.views.generic import CreateView, DetailView, ListView, TemplateView, View -from accounts.models import Account, Tags -from common.models import User, Comment, Attachments -from common.utils import STAGES, SOURCES, CURRENCY_CODES -from contacts.models import Contact -from opportunity.forms import ( - OpportunityForm, - OpportunityCommentForm, - OpportunityAttachmentForm, -) -from opportunity.models import Opportunity -from django.urls import reverse -from django.db.models import Q -from django.core.exceptions import PermissionDenied -from common.tasks import send_email_user_mentions -from opportunity.tasks import send_email_to_assigned_user -from common.access_decorators_mixins import ( - sales_access_required, - marketing_access_required, - SalesAccessRequiredMixin, - MarketingAccessRequiredMixin, -) -from teams.models import Teams - - -@login_required -def get_teams_and_users(request): - data = {} - teams = Teams.objects.filter(company=request.company) - teams_data = [ - {"team": team.id, "users": [user.id for user in team.users.all()]} - for team in teams - ] - users = User.objects.filter(company=request.company).values_list("id", flat=True) - data["teams"] = teams_data - data["users"] = list(users) - return JsonResponse(data) - - -class OpportunityListView(SalesAccessRequiredMixin, LoginRequiredMixin, TemplateView): - model = Opportunity - context_object_name = "opportunity_list" - template_name = "opportunity.html" - - def get_queryset(self): - queryset = self.model.objects.all().prefetch_related("contacts", "account") - if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: - queryset = queryset.filter( - Q(assigned_to__in=[self.request.user]) - | Q(created_by=self.request.user.id) - ) - - if self.request.GET.get("tag", None): - queryset = queryset.filter(tags__in=self.request.GET.getlist("tag")) - - request_post = self.request.POST - if request_post: - if request_post.get("name"): - queryset = queryset.filter(name__icontains=request_post.get("name")) - if request_post.get("stage"): - queryset = queryset.filter(stage=request_post.get("stage")) - if request_post.get("lead_source"): - queryset = queryset.filter(lead_source=request_post.get("lead_source")) - if request_post.get("account"): - queryset = queryset.filter(account_id=request_post.get("account")) - if request_post.get("contacts"): - queryset = queryset.filter(contacts=request_post.get("contacts")) - if request_post.get("tag"): - queryset = queryset.filter(tags__in=request_post.getlist("tag")) - return queryset.filter(company=self.request.company).distinct() - - def get_context_data(self, **kwargs): - context = super(OpportunityListView, self).get_context_data(**kwargs) - context["opportunity_list"] = self.get_queryset() - context["accounts"] = Account.objects.filter( - status="open", company=self.request.company - ) - context["contacts"] = Contact.objects.filter(company=self.request.company) - context["stages"] = STAGES - context["sources"] = SOURCES - context["per_page"] = self.request.POST.get("per_page") - tag_ids = list(set(Opportunity.objects.values_list("tags", flat=True))) - context["tags"] = Tags.objects.filter(id__in=tag_ids) - if self.request.POST.get("tag", None): - context["request_tags"] = self.request.POST.getlist("tag") - elif self.request.GET.get("tag", None): - context["request_tags"] = self.request.GET.getlist("tag") - else: - context["request_tags"] = None - search = False - if ( - self.request.POST.get("name") - or self.request.POST.get("stage") - or self.request.POST.get("lead_source") - or self.request.POST.get("account") - or self.request.POST.get("contacts") - ): - search = True - - context["search"] = search - return context - - def post(self, request, *args, **kwargs): - context = self.get_context_data(**kwargs) - return self.render_to_response(context) - - -@login_required -@sales_access_required -def create_opportunity(request): - accounts = Account.objects.filter(status="open", company=request.company) - contacts = Contact.objects.filter(company=request.company) - if request.user.role != "ADMIN" and not request.user.is_superuser: - accounts = Account.objects.filter( - created_by=request.user, company=request.company - ) - contacts = Contact.objects.filter( - Q(assigned_to__in=[request.user]) | Q(created_by=request.user) - ).filter(company=request.company) - users = [] - if request.user.role == "ADMIN" or request.user.is_superuser: - users = User.objects.filter(is_active=True, company=request.company).order_by( - "email" - ) - elif request.user.google.all(): - users = [] - else: - users = User.objects.filter(role="ADMIN", company=request.company).order_by( - "email" - ) - kwargs_data = { - "assigned_to": users, - "account": accounts, - "contacts": contacts, - "request_obj": request, - } - if request.POST: - form = OpportunityForm(request.POST, request.FILES, **kwargs_data) - if form.is_valid(): - opportunity_obj = form.save(commit=False) - opportunity_obj.created_by = request.user - opportunity_obj.company = request.company - if request.POST.get("stage") in ["CLOSED WON", "CLOSED LOST"]: - opportunity_obj.closed_by = request.user - opportunity_obj.save() - if request.POST.getlist("assigned_to", []): - opportunity_obj.assigned_to.add(*request.POST.getlist("assigned_to")) - # assigned_to_list = request.POST.getlist('assigned_to') - # current_site = get_current_site(request) - # recipients = assigned_to_list - # send_email_to_assigned_user.delay(recipients, opportunity_obj.id, domain=current_site.domain, - # protocol=request.scheme) - # for assigned_to_user in assigned_to_list: - # user = get_object_or_404(User, pk=assigned_to_user) - # mail_subject = 'Assigned to opportunity.' - # message = render_to_string( - # 'assigned_to/opportunity_assigned.html', { - # 'user': user, - # 'domain': current_site.domain, - # 'protocol': request.scheme, - # 'opportunity': opportunity_obj - # }) - # email = EmailMessage( - # mail_subject, message, to=[user.email]) - # email.content_subtype = "html" - # email.send() - if request.POST.getlist("teams", []): - user_ids = Teams.objects.filter( - id__in=request.POST.getlist("teams") - ).values_list("users", flat=True) - assinged_to_users_ids = opportunity_obj.assigned_to.all().values_list( - "id", flat=True - ) - for user_id in user_ids: - if user_id not in assinged_to_users_ids: - opportunity_obj.assigned_to.add(user_id) - - if request.POST.getlist("teams", []): - opportunity_obj.teams.add(*request.POST.getlist("teams")) - - current_site = get_current_site(request) - recipients = list( - opportunity_obj.assigned_to.all().values_list("id", flat=True) - ) - send_email_to_assigned_user.delay( - recipients, - opportunity_obj.id, - domain=current_site.domain, - protocol=request.scheme, - ) - - if request.POST.getlist("contacts", []): - opportunity_obj.contacts.add(*request.POST.getlist("contacts")) - if request.POST.get("tags", ""): - tags = request.POST.get("tags") - splitted_tags = tags.split(",") - for t in splitted_tags: - tag = Tags.objects.filter(name=t.lower()) - if tag: - tag = tag[0] - else: - tag = Tags.objects.create(name=t.lower()) - opportunity_obj.tags.add(tag) - if request.FILES.get("oppurtunity_attachment"): - attachment = Attachments() - attachment.created_by = request.user - attachment.file_name = request.FILES.get("oppurtunity_attachment").name - attachment.opportunity = opportunity_obj - attachment.attachment = request.FILES.get("oppurtunity_attachment") - attachment.save() - success_url = reverse("opportunities:list") - if request.POST.get("savenewform"): - success_url = reverse("opportunities:save") - if request.POST.get("from_account"): - from_account = request.POST.get("from_account") - success_url = reverse( - "accounts:view_account", kwargs={"pk": from_account} - ) - # print(success_url) - return JsonResponse({"error": False, "success_url": success_url}) - return JsonResponse({"error": True, "errors": form.errors}) - context = {} - context["opportunity_form"] = OpportunityForm(**kwargs_data) - - context["accounts"] = accounts - if request.GET.get("view_account"): - context["account"] = get_object_or_404( - Account, id=request.GET.get("view_account") - ) - context["contacts"] = contacts.filter(company=request.company) - context["users"] = kwargs_data["assigned_to"] - context["currencies"] = CURRENCY_CODES - context["stages"] = STAGES - context["sources"] = SOURCES - context["teams"] = Teams.objects.filter(company=request.company) - context["assignedto_list"] = [ - int(i) for i in request.POST.getlist("assigned_to", []) if i - ] - - context["contacts_list"] = [ - int(i) for i in request.POST.getlist("contacts", []) if i - ] - return render(request, "create_opportunity.html", context) - - -class OpportunityDetailView(SalesAccessRequiredMixin, LoginRequiredMixin, DetailView): - model = Opportunity - context_object_name = "opportunity_record" - template_name = "view_opportunity.html" - - def dispatch(self, request, *args, **kwargs): - opportunity = self.get_object() - if opportunity.company != request.company: - raise PermissionDenied - return super(OpportunityDetailView, self).dispatch(request, *args, **kwargs) - - def get_queryset(self): - queryset = super(OpportunityDetailView, self).get_queryset() - queryset = queryset.prefetch_related("contacts", "account") - return queryset - - def get_context_data(self, **kwargs): - context = super(OpportunityDetailView, self).get_context_data(**kwargs) - user_assgn_list = [ - assigned_to.id for assigned_to in context["object"].assigned_to.all() - ] - user_assigned_accounts = set( - self.request.user.account_assigned_users.values_list("id", flat=True) - ) - if context["object"].account: - opportunity_account = set([context["object"].account.id]) - else: - opportunity_account = set() - if user_assigned_accounts.intersection(opportunity_account): - user_assgn_list.append(self.request.user.id) - if self.request.user == context["object"].created_by: - user_assgn_list.append(self.request.user.id) - if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: - if self.request.user.id not in user_assgn_list: - raise PermissionDenied - assigned_data = [] - for each in context["opportunity_record"].assigned_to.all(): - assigned_dict = {} - assigned_dict["id"] = each.id - assigned_dict["name"] = each.email - assigned_data.append(assigned_dict) - - comments = context["opportunity_record"].opportunity_comments.all() - - if self.request.user.is_superuser or self.request.user.role == "ADMIN": - users_mention = list( - User.objects.filter( - is_active=True, company=self.request.company - ).values("username") - ) - elif self.request.user != context["object"].created_by: - users_mention = [{"username": context["object"].created_by.username}] - else: - users_mention = list(context["object"].assigned_to.all().values("username")) - - context.update( - { - "comments": comments, - "attachments": context[ - "opportunity_record" - ].opportunity_attachment.all(), - "users_mention": users_mention, - "assigned_data": json.dumps(assigned_data), - } - ) - return context - - -@login_required -@sales_access_required -def update_opportunity(request, pk): - opportunity_object = Opportunity.objects.filter(pk=pk).first() - if opportunity_object.company != request.company: - raise PermissionDenied - accounts = Account.objects.filter(status="open", company=request.company) - contacts = Contact.objects.filter(company=request.company) - if request.user.role != "ADMIN" and not request.user.is_superuser: - accounts = Account.objects.filter( - created_by=request.user, company=request.company - ) - contacts = Contact.objects.filter( - Q(assigned_to__in=[request.user]) | Q(created_by=request.user) - ).filter(company=request.company) - users = [] - if request.user.role == "ADMIN" or request.user.is_superuser: - users = User.objects.filter(is_active=True, company=request.company).order_by( - "email" - ) - elif request.user.google.all(): - users = [] - else: - users = User.objects.filter(role="ADMIN", company=request.company).order_by( - "email" - ) - kwargs_data = { - "assigned_to": users, - "account": accounts, - "contacts": contacts, - "request_obj": request, - } - form = OpportunityForm(instance=opportunity_object, **kwargs_data) - - if request.POST: - form = form = OpportunityForm( - request.POST, request.FILES, instance=opportunity_object, **kwargs_data - ) - if form.is_valid(): - assigned_to_ids = opportunity_object.assigned_to.all().values_list( - "id", flat=True - ) - opportunity_obj = form.save(commit=False) - if request.POST.get("stage") in ["CLOSED WON", "CLOSED LOST"]: - opportunity_obj.closed_by = request.user - previous_assigned_to_users = list( - opportunity_obj.assigned_to.all().values_list("id", flat=True) - ) - opportunity_obj.save() - - opportunity_obj.contacts.clear() - all_members_list = [] - if request.POST.getlist("assigned_to", []): - current_site = get_current_site(request) - assigned_form_users = form.cleaned_data.get("assigned_to").values_list( - "id", flat=True - ) - all_members_list = list( - set(list(assigned_form_users)) - set(list(assigned_to_ids)) - ) - # current_site = get_current_site(request) - # recipients = all_members_list - # send_email_to_assigned_user.delay(recipients, opportunity_obj.id, domain=current_site.domain, - # protocol=request.scheme) - # if all_members_list: - # for assigned_to_user in all_members_list: - # user = get_object_or_404(User, pk=assigned_to_user) - # mail_subject = 'Assigned to opportunity.' - # message = render_to_string( - # 'assigned_to/opportunity_assigned.html', { - # 'user': user, - # 'domain': current_site.domain, - # 'protocol': request.scheme, - # 'opportunity': opportunity_obj - # }) - # email = EmailMessage( - # mail_subject, message, to=[user.email]) - # email.content_subtype = "html" - # email.send() - - opportunity_obj.assigned_to.clear() - opportunity_obj.assigned_to.add(*request.POST.getlist("assigned_to")) - else: - opportunity_obj.assigned_to.clear() - - if request.POST.getlist("teams", []): - user_ids = Teams.objects.filter( - id__in=request.POST.getlist("teams") - ).values_list("users", flat=True) - assinged_to_users_ids = opportunity_obj.assigned_to.all().values_list( - "id", flat=True - ) - for user_id in user_ids: - if user_id not in assinged_to_users_ids: - opportunity_obj.assigned_to.add(user_id) - - if request.POST.getlist("teams", []): - opportunity_obj.teams.clear() - opportunity_obj.teams.add(*request.POST.getlist("teams")) - else: - opportunity_obj.teams.clear() - - current_site = get_current_site(request) - assigned_to_list = list( - opportunity_obj.assigned_to.all().values_list("id", flat=True) - ) - recipients = list(set(assigned_to_list) - set(previous_assigned_to_users)) - send_email_to_assigned_user.delay( - recipients, - opportunity_obj.id, - domain=current_site.domain, - protocol=request.scheme, - ) - - if request.POST.getlist("contacts", []): - opportunity_obj.contacts.add(*request.POST.getlist("contacts")) - opportunity_obj.tags.clear() - if request.POST.get("tags", ""): - tags = request.POST.get("tags") - splitted_tags = tags.split(",") - for t in splitted_tags: - tag = Tags.objects.filter(name=t.lower()) - if tag: - tag = tag[0] - else: - tag = Tags.objects.create(name=t.lower()) - opportunity_obj.tags.add(tag) - if request.FILES.get("oppurtunity_attachment"): - attachment = Attachments() - attachment.created_by = request.user - attachment.file_name = request.FILES.get("oppurtunity_attachment").name - attachment.opportunity = opportunity_obj - attachment.attachment = request.FILES.get("oppurtunity_attachment") - attachment.save() - success_url = reverse("opportunities:list") - if request.POST.get("from_account"): - from_account = request.POST.get("from_account") - success_url = reverse( - "accounts:view_account", kwargs={"pk": from_account} - ) - return JsonResponse({"error": False, "success_url": success_url}) - return JsonResponse({"error": True, "errors": form.errors}) - context = {} - context["opportunity_obj"] = opportunity_object - user_assgn_list = [ - assigned_to.id for assigned_to in context["opportunity_obj"].assigned_to.all() - ] - if request.user == context["opportunity_obj"].created_by: - user_assgn_list.append(request.user.id) - if request.user.role != "ADMIN" and not request.user.is_superuser: - if request.user.id not in user_assgn_list: - raise PermissionDenied - context["opportunity_form"] = form - context["accounts"] = accounts - if request.GET.get("view_account"): - context["account"] = get_object_or_404( - Account, id=request.GET.get("view_account") - ) - context["contacts"] = contacts - context["users"] = kwargs_data["assigned_to"] - context["currencies"] = CURRENCY_CODES - context["stages"] = STAGES - context["sources"] = SOURCES - context["teams"] = Teams.objects.filter(company=request.company) - context["assignedto_list"] = [ - int(i) for i in request.POST.getlist("assigned_to", []) if i - ] - context["contacts_list"] = [ - int(i) for i in request.POST.getlist("contacts", []) if i - ] - return render(request, "create_opportunity.html", context) - - -class DeleteOpportunityView(SalesAccessRequiredMixin, LoginRequiredMixin, View): - def get(self, request, *args, **kwargs): - return self.post(request, *args, **kwargs) - - def post(self, request, *args, **kwargs): - self.object = get_object_or_404(Opportunity, id=kwargs.get("pk")) - if self.object.company != request.company: - raise PermissionDenied - if ( - self.request.user.role == "ADMIN" - or self.request.user.is_superuser - or self.request.user == self.object.created_by - ): - self.object.delete() - if request.is_ajax(): - return JsonResponse({"error": False}) - - if request.GET.get("view_account"): - account = request.GET.get("view_account") - return redirect("accounts:view_account", pk=account) - - return redirect("opportunities:list") - raise PermissionDenied - - -class GetContactView(LoginRequiredMixin, View): - def get(self, request, *args, **kwargs): - account_id = request.GET.get("account") - if account_id: - account = get_object_or_404(Account, id=account_id) - contacts = account.contacts.all() - else: - contacts = Contact.objects.all() - data = {contact.pk: contact.first_name for contact in contacts.distinct()} - return JsonResponse(data) - - -class AddCommentView(LoginRequiredMixin, CreateView): - model = Comment - form_class = OpportunityCommentForm - http_method_names = ["post"] - - def post(self, request, *args, **kwargs): - self.object = None - self.opportunity = get_object_or_404( - Opportunity, id=request.POST.get("opportunityid") - ) - if ( - request.user in self.opportunity.assigned_to.all() - or request.user == self.opportunity.created_by - or request.user.is_superuser - or request.user.role == "ADMIN" - ): - form = self.get_form() - if form.is_valid(): - return self.form_valid(form) - return self.form_invalid(form) - - data = {"error": "You don't have permission to comment."} - return JsonResponse(data) - - def form_valid(self, form): - comment = form.save(commit=False) - comment.commented_by = self.request.user - comment.opportunity = self.opportunity - comment.save() - comment_id = comment.id - current_site = get_current_site(self.request) - send_email_user_mentions.delay( - comment_id, - "opportunity", - domain=current_site.domain, - protocol=self.request.scheme, - ) - return JsonResponse( - { - "comment_id": comment.id, - "comment": comment.comment, - "commented_on": comment.commented_on, - "commented_on_arrow": comment.commented_on_arrow, - "commented_by": comment.commented_by.email, - } - ) - - def form_invalid(self, form): - return JsonResponse({"error": form["comment"].errors}) - - -class UpdateCommentView(LoginRequiredMixin, View): - http_method_names = ["post"] - - def post(self, request, *args, **kwargs): - self.comment_obj = get_object_or_404(Comment, id=request.POST.get("commentid")) - if request.user == self.comment_obj.commented_by: - form = OpportunityCommentForm(request.POST, instance=self.comment_obj) - if form.is_valid(): - return self.form_valid(form) - return self.form_invalid(form) - - data = {"error": "You don't have permission to edit this comment."} - return JsonResponse(data) - - def form_valid(self, form): - self.comment_obj.comment = form.cleaned_data.get("comment") - self.comment_obj.save(update_fields=["comment"]) - comment_id = self.comment_obj.id - current_site = get_current_site(self.request) - send_email_user_mentions.delay( - comment_id, - "opportunity", - domain=current_site.domain, - protocol=self.request.scheme, - ) - return JsonResponse( - { - "commentid": self.comment_obj.id, - "comment": self.comment_obj.comment, - } - ) - - def form_invalid(self, form): - return JsonResponse({"error": form["comment"].errors}) - - -class DeleteCommentView(LoginRequiredMixin, View): - def post(self, request, *args, **kwargs): - self.object = get_object_or_404(Comment, id=request.POST.get("comment_id")) - if request.user == self.object.commented_by: - self.object.delete() - data = {"cid": request.POST.get("comment_id")} - return JsonResponse(data) - - data = {"error": "You don't have permission to delete this comment."} - return JsonResponse(data) - - -class GetOpportunitiesView(LoginRequiredMixin, ListView): - model = Opportunity - context_object_name = "opportunities" - template_name = "opportunities_list.html" - - -class AddAttachmentsView(LoginRequiredMixin, CreateView): - model = Attachments - form_class = OpportunityAttachmentForm - http_method_names = ["post"] - - def post(self, request, *args, **kwargs): - self.object = None - self.opportunity = get_object_or_404( - Opportunity, id=request.POST.get("opportunityid") - ) - if ( - request.user in self.opportunity.assigned_to.all() - or request.user == self.opportunity.created_by - or request.user.is_superuser - or request.user.role == "ADMIN" - ): - form = self.get_form() - if form.is_valid(): - return self.form_valid(form) - return self.form_invalid(form) - - data = {"error": "You don't have permission to add attachment."} - return JsonResponse(data) - - def form_valid(self, form): - attachment = form.save(commit=False) - attachment.created_by = self.request.user - attachment.file_name = attachment.attachment.name - attachment.opportunity = self.opportunity - attachment.save() - return JsonResponse( - { - "attachment_id": attachment.id, - "attachment": attachment.file_name, - "attachment_url": attachment.attachment.url, - "created_on": attachment.created_on, - "created_on_arrow": attachment.created_on_arrow, - "created_by": attachment.created_by.email, - "download_url": reverse( - "common:download_attachment", kwargs={"pk": attachment.id} - ), - "attachment_display": attachment.get_file_type_display(), - "file_type": attachment.file_type(), - } - ) - - def form_invalid(self, form): - return JsonResponse({"error": form["attachment"].errors}) - - -class DeleteAttachmentsView(LoginRequiredMixin, View): - def post(self, request, *args, **kwargs): - self.object = get_object_or_404( - Attachments, id=request.POST.get("attachment_id") - ) - if ( - request.user == self.object.created_by - or request.user.is_superuser - or request.user.role == "ADMIN" - ): - self.object.delete() - data = {"aid": request.POST.get("attachment_id")} - return JsonResponse(data) - - data = {"error": "You don't have permission to delete this attachment."} - return JsonResponse(data) diff --git a/requirements.txt b/requirements.txt index 7cf1eda..b54e7aa 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,17 +1,34 @@ +amqp==5.0.5 appdirs==1.4.4 arrow==0.17.0 +asgiref==3.3.1 +attrs==20.3.0 +billiard==3.6.3.0 black==20.8b1 boto==2.49.0 +boto3==1.16.63 +botocore==1.19.63 CacheControl==0.12.6 celery==5.0.5 +certifi==2020.12.5 +chardet==3.0.4 +click==7.1.2 +click-didyoumean==0.0.3 +click-plugins==1.1.1 +click-repl==0.1.6 codacy-coverage==1.3.11 colorama==0.4.4 +colorclass==2.2.0 contextlib2==0.6.0.post1 +coreapi==2.3.3 +coreschema==0.0.4 coverage==5.4 cssselect==1.1.0 distlib==0.3.1 distro==1.5.0 -django==3.1.7 +Django==3.1.6 +django-appconf==1.0.4 +django-compressor==2.4 django-cors-headers==3.7.0 django-haystack==3.0 django-libsass==0.8 @@ -20,34 +37,79 @@ django-ses==1.0.3 django-settings-export==1.2.1 django-simple-pagination==1.3 django-storages==1.11.1 -djangorestframework-jwt==1.11.0 +djangorestframework==3.12.2 drf-compound-fields==2.0.0 drf-yasg==1.20.0 -elasticsearch==7.11.0 +elastic-apm==5.10.0 +elasticsearch==7.10.1 +et-xmlfile==1.0.1 +future==0.18.2 html5lib==1.1 +idna==2.10 importlib-metadata==3.4.0 +inflection==0.5.1 +iniconfig==1.1.1 ipaddr==2.2.0 +itypes==1.2.0 +jdcal==1.4.1 +Jinja2==2.11.3 +jmespath==0.10.0 +kombu==5.0.2 +libsass==0.20.1 lockfile==0.12.2 lxml==4.6.2 -openpyxl==3.0.6 +MarkupSafe==1.1.1 +msgpack==1.0.0 +mypy-extensions==0.4.3 +openpyxl==3.0.5 +packaging==20.9 +pathspec==0.8.1 pdfkit==0.6.1 -phonenumbers==8.12.18 +pep517==0.9.1 +phonenumbers==8.12.17 Pillow==8.1.0 pip-check==2.6 pipdeptree==2.0.0 +pluggy==0.13.1 progress==1.5 +prompt-toolkit==3.0.14 psycopg2-binary==2.8.6 +py==1.10.0 +PyJWT==1.7.1 +pyparsing==2.4.7 +pytest==6.2.2 pytest-django==4.1.0 +python-dateutil==2.8.1 python-dotenv==0.15.0 +python-memcached==1.59 pytoml==0.1.21 +pytz==2021.1 raven==6.10.0 +rcssmin==1.0.6 redis==3.5.3 +regex==2020.11.13 +requests==2.25.1 retrying==1.3.3 -sentry-sdk==0.20.3 +rjsmin==1.1.0 +ruamel.yaml==0.16.12 +ruamel.yaml.clib==0.2.2 +s3transfer==0.3.4 +sentry-sdk==0.19.5 +six==1.15.0 sorl-thumbnail==12.7.0 +sqlparse==0.4.1 +terminaltables==3.1.0 +toml==0.10.2 +typed-ast==1.4.2 +typing-extensions==3.7.4.3 +uritemplate==3.0.1 +urllib3==1.26.3 uWSGI==2.0.19.1 -wheel==0.36.1 +vine==5.0.0 +wcwidth==0.2.5 +webencodings==0.5.1 whitenoise==5.2.0 -xlrd==1.2.1 +xlrd==1.2.0 xlwt==1.3.0 -git+https://github.com/MicroPyramid/django-blog-it \ No newline at end of file +zipp==3.4.0 +djangorestframework-jwt==1.11.0 \ No newline at end of file diff --git a/static/css/403.css b/static/css/403.css deleted file mode 100644 index 4c46ea5..0000000 --- a/static/css/403.css +++ /dev/null @@ -1,43 +0,0 @@ -body { - color: #666; - text-align: center; - font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; - margin: auto; - font-size: 14px; -} - -h1 { - font-size: 56px; - line-height: 100px; - font-weight: normal; - color: #456; -} - -h2 { - font-size: 24px; - color: #666; - line-height: 1.5em; -} - -h3 { - color: #456; - font-size: 20px; - font-weight: normal; - line-height: 28px; -} - -hr { - max-width: 800px; - margin: 18px auto; - border: 0; - border-top: 1px solid #eee; - border-bottom: 1px solid white; -} - -img { - max-width: 40vw; -} - -.container { - margin: auto 20px; -} diff --git a/static/css/bootstrap-suggest.css b/static/css/bootstrap-suggest.css deleted file mode 100644 index e626335..0000000 --- a/static/css/bootstrap-suggest.css +++ /dev/null @@ -1,27 +0,0 @@ -/*! - * bootstra-suggest - v2.0.1 (https://github.com/lodev09/bootstrap-suggest#readme) - * Copyright 2013-2019 Jovanni Lo (lodev09@gmail.com) - * Licensed under MIT (https://github.com/lodev09/bootstrap-suggest/blob/master/LICENSE) - */ - -.suggest { - /* position: relative; */ - top: 7px; - z-index: 30; - text-align: left; -} - -.suggest > .dropdown-menu { - margin-top: 15px; - position: absolute; -} - -.suggest > .dropdown-menu > a.dropdown-item { - border-top: 1px solid #eeeeee; - padding: 5px 10px; -} - -.suggest > .dropdown-menu > a.dropdown-item:first-child { - border-top: 0; -} - diff --git a/static/css/main.scss b/static/css/main.scss deleted file mode 100644 index aa90761..0000000 --- a/static/css/main.scss +++ /dev/null @@ -1,1607 +0,0 @@ -@import "ref.scss"; -* { - font-family: "Quicksand", sans-serif; -} -body { - font-family: "Quicksand", sans-serif; - padding: 0; - font-weight: 500; - margin: 0; - font-size: 14px; - background: #f7f7f9; - @media (min-width: $large) { - font-size: 17px; - } - @media (min-width: $mob_min) and (max-width: $smob_max) { - padding-top: 50px; - } -} -.login_register_body { -} -/**{ - font-size: 15px; - @media(min-width:$large){ - font-size:17px; - } - }*/ -.no_mar_top { - margin-top: 0 !important; -} -.marl { - margin-left: 0; - margin-right: 0; -} -.no-padding { - padding: 0; -} -.login_row { -} -.login_block { - margin-top: 0px; - - .welcome { - font-size: 1.6rem; - font-weight: 600; - color: #333; - span { - color: $sky_color; - &.create_head { - color: $sky_color; - } - } - } -} -a { - &:hover { - text-decoration: none; - } -} -.anchor { - color: darken($text_color, 15%) !important; -} -.login_form_block { - margin-top: 30px; - padding: 50px 15px; - .welcome { - margin-bottom: 20px; - text-align: center; - } - .forgot { - font-size: 13px; - display: block; - color: darken($text_color2, 15%); - a { - display: inline-block; - color: $dark_sky; - margin-bottom: 10px; - font-size: 13px; - } - } - .form-group { - margin-bottom: 15px; - } - .errorlist li { - color: red; - font-size: 0.83rem; - } - label { - font-size: 14px; - color: darken($text_color2, 15%); - font-weight: 500; - } - .form-control, - input { - color: $text_color; - min-height: 40px; - font-size: 13px; - letter-spacing: 0.5px; - border: 1px solid #ddd; - //Instead of the line below you could use @include box-shadow($shadow-1, $shadow-2, $shadow-3, $shadow-4, $shadow-5, $shadow-6, $shadow-7, $shadow-8, $shadow-9, $shadow-10) - box-shadow: none; - //Instead of the line below you could use @include border-radius($radius, $vertical-radius) - border-radius: 3px; - } - .btn { - //Instead of the line below you could use @include border-radius($radius, $vertical-radius) - border-radius: 3px; - border: none; - font-size: 1rem; - font-weight: 600; - color: $white; - width: 100%; - outline: none; - padding: 10px 20px; - &:hover { - text-decoration: none; - } - } - .checkbox { - text-align: center; - input[type="checkbox"] { - vertical-align: middle; - margin: 0; - margin-top: 1px; - margin-left: -19px; - } - } -} - -/* inner_pages starts here */ -/*.main_body_bg_color{ - background: #fff; -}*/ - -.primary_btn { - background: $login_btn_bg; - color: #fff; - border: none; - font-size: 0.9rem; - font-weight: 500; - text-transform: capitalize; - letter-spacing: initial; - display: inline-block; - border-radius: 3px; - padding: 2px 10px; - line-height: 1.5rem; - border: none; - cursor: pointer; - &:hover { - background: darken($login_btn_bg, 10%); - color: #fff; - } - @media (min-width: $large) { - font-size: 1rem; - svg { - position: relative; - top: 0px; - } - } - svg { - display: inline-block; - margin-right: 5px; - } -} -.secondary_btn { - @extend .primary_btn; - background: $blue; - &:hover { - background: darken($blue, 10%); - } -} -.tertiary_btn { -} -header { - .navbar { - background: #fff; - border: none; - border: 1px solid #ddd; - padding: 0 15px; - @media (min-width: $mob_min) and (max-width: $smob_max) { - padding: 5px 15px; - } - .navbar-brand { - color: darken($text_color, 10%); - font-weight: 600; - margin-right: 50px; - &:hover { - color: $login_btn_bg; - } - } - .navbar-toggler { - svg { - color: #333; - } - } - .navbar-nav { - .nav-item { - a { - color: lighten($text_color, 5%) !important; - font-weight: 500; - font-size: 0.9rem; - padding: 10px 15px; - display: inline-block; - padding-top: 16px; - border-bottom: 3px solid #fff; - @media (min-width: $mob_min) and (max-width: $smob_max) { - padding: 5px 10px; - } - @media (min-width: $large) { - font-size: 1rem; - } - &:hover { - color: darken($text_color, 5%) !important; - border-bottom: 3px solid $dark_sky; - } - &.active { - color: darken($text_color, 5%) !important; - border-bottom: 3px solid $dark_sky; - } - } - } - .open { - a { - background: $login_btn_bg !important; - } - } - li { - .dropdown-toggle { - img { - width: 25px; - height: 25px; - } - } - .dropdown-menu { - padding: 0; - a { - font-size: 0.9rem; - padding: 8px 10px; - color: darken($text_color, 5%); - border: none !important; - svg { - display: inline-block; - margin-right: 5px; - font-size: 0.75rem; - } - @media (min-width: $large) { - font-size: 0.95rem; - } - &:hover { - border: none !important; - } - } - } - } - &.navbar-right { - .dropdown { - .dropdown-toggle { - img { - width: 25px; - height: 25px; - } - } - a { - color: #fff; - &.nav-link { - padding: 11px 15px; - border-bottom: 3px solid #fff; - } - &:hover { - color: darken($text_color, 5%) !important; - border-bottom: 3px solid $dark_sky; - } - } - } - } - /* li{ - a{ - &:hover{ - color:lighten($text_color,15%); - } - } - }*/ - } - .navbar-form { - .form-group { - .form-control { - border-radius: 3px; - border: none; - } - } - .btn { - border-radius: 3px; - padding: 7px 12px; - border: none; - background: $green; - &.btn-default { - color: #fff; - } - } - } - } -} -/* inner_pages ends here */ - -/* CSS used here will be applied after bootstrap.css */ -$color_1: #ff7788; -$color_2: #000; - -.glyphicon-bell { - font-size: 1.5rem; -} -.notifications { - min-width: 420px; - font-size: 12px; - padding: 0; - border: none; - a.content { - text-decoration: none; - background: #ccc; - } -} -.notifications-wrapper { - overflow: auto; - max-height: 250px; -} -.menu-title { - color: #ffffff; - font-size: 12px; - display: inline-block; - text-transform: uppercase; - font-weight: 500; - letter-spacing: 1px; -} -.glyphicon-circle-arrow-right { - margin-left: 10px; -} -.notification-heading { - padding: 2px 10px; - background: lighten($text_color, 5%); - border-top: 1px solid lighten($text_color, 10%); -} -.notification-footer { - padding: 2px 10px; - background: $green; -} -.dropdown-menu.divider { - margin: 5px 0; -} -.item-title { - font-size: 12px; - color: darken($text_color, 15%); - margin: 0; -} -.notification-item { - padding: 10px; - margin: 5px; - background: #ccc; - border-radius: 4px; - p { - margin: 0; - color: #fff; - margin-top: 6px; - } -} - -/* main_container stats here */ -.main_container { - padding-top: 0; - .heading_create { - .heading { - font-size: 1.1rem; - text-transform: uppercase; - letter-spacing: 1px; - color: darken($text_color, 15%); - h4 { - font-size: 1.1rem; - font-weight: 800; - } - } - - .search-row { - .form-group { - .input-group { - .left-dropdown { - .filters-button { - font-size: 12px; - background: #fff; - border: none; - box-shadow: none; - margin-top: 1px; - } - .dropdown-menu { - li { - a { - font-size: 12px; - } - &.checkbox { - color: #000; - padding-left: 10px; - font-size: 12px; - letter-spacing: 0.4px; - input[type="checkbox"] { - margin: 0; - margin-left: -10px; - margin-top: 1px; - margin-right: 10px; - } - } - } - } - } - .form-control { - height: 29px; - border: none; - margin-top: 2px; - } - .search { - background: $green; - color: #fff; - border: none; - padding: 5px 13px; - margin-top: 2px; - } - } - } - .extra_option_btn { - font-size: 12px; - background: #5b636e; - border: none; - color: #fff; - padding-top: 7px; - padding-bottom: 7px; - &.add-filter-button { - background-color: $dark_sky; - } - } - .dropdown-menu { - font-size: 12px; - } - } - } - - /* filter_row starts here */ - .filter_row { - margin-top: 10px; - .card { - border: 1px solid #ccc; - .card-body { - padding: 0px 0; - .card-title { - background: #e5e5e5; - padding: 6px 10px; - font-weight: 600; - font-size: 1rem; - } - .form-group { - margin-bottom: 10px; - label { - color: black; - font-size: 0.85rem; - font-weight: 600; - text-transform: none; - } - .form-control { - border-radius: 0; - box-shadow: none; - font-size: 0.85rem; - } - &.buttons_row { - margin-top: 30px; - } - } - } - } - .table_container_row { - margin-top: 0; - } - } - /* filter_row ends here */ - /* table_container_row starts here */ -} -.remove_tag { - position: relative; -} -.remove_tag .fa-times { - color: #000 !important; - position: absolute; - background: #fff; - top: -6px; - padding: 1px; - border-radius: 50%; - font-size: 0.6rem; - height: 10px; - width: 10px; - border: 1px solid #000; -} -/* main_container ends here */ -.table_container_row { - margin-top: 10px; - .card { - border: none; - border-radius: 0; - box-shadow: none; - .card-title { - padding: 5px 10px !important; - background: #e5e5e5; - font-size: 1rem; - margin-bottom: 0; - font-weight: 600; - line-height: 2.3rem; - &.title_lh { - line-height: 2rem; - } - .dropdown { - display: inline-block; - .dropdown-toggle { - background: $dark_sky; - font-size: 12px; - color: #fff; - border-radius: 0; - border: none; - } - } - .mark_read { - background: $inner_page_bg; - display: inline-block; - padding: 6px 10px; - margin-left: 6px; - color: $text_color; - &:hover { - background: $text_color; - color: #fff; - text-decoration: none; - } - } - .total_count { - margin-top: 0px; - } - } - .card-body { - padding: 0px 0px; - table { - border: none; - margin-bottom: 0; - thead { - tr { - th { - color: #454545; - font-weight: 900; - font-size: 0.9rem; - border: none; - text-align: left; - padding: 6px; - border-bottom: 1px solid darken(#f7f7f9, 2%); - } - } - } - tbody { - tr { - td { - vertical-align: middle; - color: #454545; - font-size: 0.83rem; - text-align: left; - font-weight: 500; - padding: 7px 5px; - border-bottom: 1px solid darken(#f7f7f9, 2%); - @media (min-width: $large) { - font-size: 1rem; - } - a { - color: lighten($dark_sky, 5%); - font-size: 0.85rem; - &:hover { - color: $dark_sky; - text-decoration: underline; - } - } - .dropdown { - .dropdown-toggle { - background: $dark_sky; - font-size: 12px; - color: #fff; - border-radius: 0; - border: none; - } - } - &.actions { - a { - &.box { - @extend .box; - line-height: 1.5rem; - width: 1.65rem; - height: 1.65rem; - } - } - } - } - } - } - } - } - } - - /* mail_menu starts here */ - .mail_menu { - .panel { - border-radius: 0; - padding: 0; - background: none; - border: 0; - .panel-content { - padding: 0; - .mail_options { - margin: 0; - padding: 0; - li { - list-style: none; - a { - display: block; - padding: 10px; - background: $text_color; - margin: 1px; - color: white; - text-transform: uppercase; - letter-spacing: 0.6px; - &:hover { - background: $green; - color: #fff; - text-decoration: none; - border-left: 3px solid white; - } - } - &.active { - a { - background: $green; - color: #fff; - text-decoration: none; - border-left: 3px solid white; - } - } - } - } - } - } - } - /* mail_menu ends here */ -} -/* table_container_row ends here */ -/* breadcrumb starts here */ -.breadcrumb { - margin: 0; - padding: 0 15px; - background: none; - .breadcrumb-item { - a { - color: $dark_sky; - } - } -} -.breadcrumb li + li:before { - color: $text_color; -} -/* breadcrumb ends here */ -/* assigned_teams starts here */ -.assigned_teams { - @extend .filter_row; - margin-top: 0; -} -/* assigned_teams ends here */ - -/* overview_form_block starts here */ -.overview_form_block { - @extend .filter_row; - .card-title { - min-height: 36px; - padding: 8px 10px !important; - h5 { - margin-bottom: 0; - position: relative; - font-size: 1rem; - font-weight: 600; - .title { - position: relative; - top: 2px; - } - } - .dropdown { - .dropdown-menu { - li { - a { - font-size: 0.85rem; - color: #454545; - text-transform: capitalize !important; - font-weight: 400; - display: block; - padding: 5px 8px; - } - } - } - } - } - .buttons_row { - margin: 0; - position: relative; - } - .form-control { - border-radius: 0; - box-shadow: none; - font-size: 0.85rem; - } - margin-top: 0; - .country_class { - margin-top: 10px; - } - .shiiping_block { - margin-top: 10px; - .checkbox { - color: $text_color; - } - } - .filters-button { - border-radius: 0; - } - .website_block { - margin-top: 10px; - } - .search { - border-radius: 0; - } - .copy_billing_btn { - margin-top: 10px; - display: block; - } -} -/* overview_form_block ends here */ -/* details_block starts here */ -.details_block { - @extend .filter_row; - .form-control { - border-radius: 0; - box-shadow: none; - font-size: 12px; - } -} -.buttons_row { - margin-bottom: 0px; - button { - border-radius: 0; - font-size: 0.85rem; - font-weight: 600; - &.save { - background: $dark_sky; - color: #fff; - } - } -} -/* details_block ends here */ -/* attendees starts here */ -.attendees { - @extend .filter_row; -} -/* attendees ends here */ - -.case-list-container { - margin-bottom: 15px; -} - -.profile_pic { - text-align: center; - img { - width: 5rem; - height: 5rem; - border-radius: 50%; - } -} - -.error, -.errors { - color: red; -} - -.required_color { - color: red; -} - -.error ul { - list-style-type: none; - padding: 0px; -} - -.view-pad { - padding: 0px !important; - h5 { - width: 90%; - margin-bottom: 0; - position: relative; - font-size: 1rem; - font-weight: 600; - display: inline-block; - text-align: left; - padding-top: 0px; - } - a { - float: right; - border-radius: 0; - font-size: 1rem; - padding: 3px 10px; - color: #fff; - margin-top: -4px; - &:hover { - text-decoration: none; - } - } -} - -.select2-container { - width: 100% !important; - border-radius: 0; - border: 1px solid #ced4da; -} -.select2-container--default .select2-selection--multiple { - border-radius: 0 important; - border: none !important; -} -.select2-container--open { - width: inherit !important; - display: block !important; -} -.created_information { - padding-left: 15px; - margin: 10px 0; -} -.pagination { - li { - a { - padding: 5px 10px; - border: 1px solid #ddd; - font-weight: 600; - } - .active { - background: #369cbe; - padding: 5px 10px; - border: 1px solid #369cbe; - color: #fff; - } - } -} - -.text-center { - justify-content: center !important; -} - -.pull-right { - float: right; -} -.credentials { - border: 1px solid; - width: 309px; - border: 6px solid #040404; - padding: 30px 0; - text-align: center; - position: relative; - margin-top: 6rem; -} -.credentials .heading { - position: absolute; - display: inline-block; - top: -15px; - left: 17%; - background: #333; - color: #fff; - padding: 3px 10px; - border-radius: 3px; -} - -.filter_toggle { - cursor: pointer; - position: relative; - top: 1px; - @media (min-width: $large) { - top: 2px; - } - a { - line-height: 1.6rem; - } - svg { - margin-right: 0; - } -} -.list_filter_row { - display: none; -} -.form_btn_row { - margin-bottom: 1rem !important; -} - -#list_tag { - color: #fff; - border: none; - background: #333; - font-weight: 500; - padding: 1px 5px; - margin-right: 5px; - font-size: 0.8rem; - display: inline-block; - margin-bottom: 5px; - border-radius: 2px; - &.color1 { - background: darken($dark_sky, 5%); - } - &.red { - background: darken($color_cerise_red_approx, 5%); - } - &.green { - background: darken($green, 5%); - } - &.color2 { - background: darken($dark_yellow, 10%); - } - &.color3 { - background: darken($color_cerise_red_approx, 1%); - } - &.color4 { - background: darken($dark_yellow, 40%); - } - &.color5 { - background: darken($dark_sky, 30%); - } - &.color6 { - background: darken($green, 1%); - } - &.color7 { - background: blueviolet; - } - &.color8 { - background: #a2866f; - } - &.color9 { - background: cadetblue; - } - &.color10 { - background: cornflowerblue; - } - &.color11 { - background: dodgerblue; - } - &.color12 { - background: blue; - } - &.color13 { - background: coral; - } - &.color14 { - background: crimson; - } - &.color15 { - background: darkgoldenrod; - } -} -.nav-tabs { - li { - &.nav-item { - a { - &.nav-link { - background: lighten($color_blue_dianne_approx, 45%); - color: #fff; - font-size: 0.83rem; - font-weight: 600; - } - &.active { - background: $info_color; - } - } - } - } -} -.account_field { - font-size: 0.83rem; -} -.contact_field { - font-size: 0.83rem; -} -.lead_field { - font-size: 0.83rem; -} -.opportunity_field { - font-size: 0.83rem; -} - -.form-control-file { - font-size: 0.83rem; -} -.case_field { - font-size: 0.83rem; -} -pre { - margin-bottom: 0.5rem; - a { - } -} -#comments_div { - .list-group-item { - margin-bottom: 0.75rem; - border: none; - background: #f5f5f5; - position: relative; - .list-row-buttons { - position: absolute; - top: 0; - right: 0; - .primary_btn { - border-radius: 0; - } - .dropdown-menu { - padding: 0; - border-radius: 0; - li { - a { - padding: 8px 8px; - display: block; - text-align: left; - font-size: 0.83rem; - border-bottom: 1px solid #dedede; - } - } - } - } - .stream-post-container { - pre { - font-weight: 600; - a { - font-size: 0.83rem; - } - } - } - .stream-container { - .date { - font-size: 0.83rem; - color: lighten($text_color, 10%); - } - } - } -} -#attachment_div { - @extend #comments_div; -} -.bootstrap-datetimepicker-widget { - display: block !important; -} -.count_blocks_row { - margin-top: 2rem; - .item { - background: #fff; - border-radius: 0; - padding: 0; - border: none; - text-align: center; - .title { - line-height: 2.5rem; - font-weight: 600; - font-size: 0.85rem; - color: #fff; - text-transform: uppercase; - a { - color: #fff; - } - } - .count { - font-size: 2rem; - font-weight: 600; - padding: 0.5rem 0; - color: #fff; - } - .more { - font-size: 0.85rem; - a { - color: #fff; - display: block; - font-weight: 600; - padding: 0.35rem; - background: darken($color_cyan_aqua_approx, 10%); - } - &.green { - a { - background: darken($color_apricot_peach_approx, 10%); - } - } - &.blue { - a { - background: darken($color_blue_dianne_approx, 10%); - } - } - &.red { - a { - background: darken($color_cerise_red_approx, 10%); - } - } - } - &.sky_blue { - background: darken($dark_sky, 10%); - } - &.red { - background: darken($color_cerise_red_approx, 10%); - } - &.green { - background: darken($green, 5%); - } - &.yellow { - background: darken($dark_yellow, 10%); - } - } -} -/* open_sections */ -.open_sections { - margin-top: 1.5rem; - .table_container_row { - .table { - margin-bottom: 0; - tbody { - tr { - td { - a { - color: #333; - font-weight: 600; - } - } - } - } - } - } -} -.errorlist { - li { - font-size: 0.83rem; - } -} - -/* marketing_pages */ - -.side_menu { - background: #fff; - position: fixed; - left: 0; - width: 250px; - top: 0; - height: 100%; - border: none; - .logo_block { - a { - display: block; - padding: 0.75rem 1rem; - color: #000; - font-size: 1.35rem; - font-weight: 800; - .green_color { - color: $green; - } - } - } - .profile_block { - margin-top: 0.5rem; - ul { - margin: 0; - padding: 0; - padding-left: 1rem; - li { - list-style: none; - display: inline-block; - margin-right: 3px; - a { - &.profile_pic { - img { - width: 2rem; - height: 2rem; - border-radius: 3px; - } - } - &.box { - @extend .box; - } - } - } - } - } - .menu_block { - .main_menu { - margin-top: 1.5rem; - padding: 0; - padding-left: 1rem; - li { - list-style: none; - a { - font-size: 0.83rem; - font-size: 400; - transition: 0.6s all ease-out; - svg { - display: inline-block; - margin-right: 0.5rem; - font-size: 1.1rem; - } - } - &.parent_menu { - margin: 0; - padding: 0; - margin-bottom: 0.5rem; - list-style: none; - a { - display: inline-block; - color: $text_color; - padding-top: 0.35rem; - padding-bottom: 0.35rem; - transition: 0.6s all ease-out; - &.red { - color: $red; - } - &.green { - color: $green; - } - &.purple { - color: $purple; - } - } - .submenu { - padding-left: 1.6rem; - margin-top: 0.3rem; - position: relative; - &::before { - content: ""; - height: 100%; - background: lighten($text_color, 40%); - width: 1px; - position: absolute; - left: 0.5rem; - } - li { - a { - transition: 0.6s all ease-out; - &.yellow { - svg { - color: $dark_yellow; - } - &:hover { - color: $dark_yellow; - } - } - &.d_green { - svg { - color: $d_green; - } - &:hover { - color: $d_green; - } - } - &.sky_color { - svg { - color: $sky_color; - } - &:hover { - color: $sky_color; - } - } - } - } - } - } - } - } - } -} -/* side_menu */ -.marketing_pages { - margin-left: 250px; - margin-bottom: 1rem; - margin-top: 2rem; -} - -.badge { - width: auto !important; - height: auto !important; - font-size: 100%; - border-radius: 10rem; - display: inline-block; - padding: 0.05rem 1rem; -} -.a_color { - color: $text_color !important; - font-weight: 600; -} -.tooltip-inner { - font-size: 0.8rem; -} -#editor-container { - height: 30rem; -} - -.mar_btm { - margin-bottom: 1rem; -} -.radio_col { - font-size: 0.83rem; - margin-bottom: 0.6rem; - .radio_span { - margin-right: 1rem; - font-size: 0.83rem; - } -} -.well { - background: #efefef; - padding: 10px; - font-size: 0.83rem; - color: $text_color; - margin-bottom: 0.5rem; -} - -.example .btn-toggle { - top: 50%; - transform: translateY(-50%); -} -.btn-toggle { - margin: 0 4rem; - padding: 0; - position: relative; - border: none; - height: 1.5rem; - width: 3rem; - border-radius: 1.5rem; - color: #6b7381; - background: #bdc1c8; -} -.btn-toggle:focus, -.btn-toggle.focus, -.btn-toggle:focus.active, -.btn-toggle.focus.active { - outline: none; -} -.btn-toggle:before, -.btn-toggle:after { - line-height: 1.5rem; - width: 4rem; - text-align: center; - font-weight: 600; - font-size: 0.75rem; - text-transform: uppercase; - letter-spacing: 2px; - position: absolute; - bottom: 0; - transition: opacity 0.25s; -} -.btn-toggle:before { - content: "Off"; - left: -4rem; -} -.btn-toggle:after { - content: "On"; - right: -4rem; - opacity: 0.5; -} -.btn-toggle > .handle { - position: absolute; - top: 0.1875rem; - left: 0.1875rem; - width: 1.125rem; - height: 1.125rem; - border-radius: 1.125rem; - background: #fff; - transition: left 0.25s; -} -.btn-toggle.active { - transition: background-color 0.25s; -} -.btn-toggle.active > .handle { - left: 1.6875rem; - transition: left 0.25s; -} -.btn-toggle.active:before { - opacity: 0.5; -} -.btn-toggle.active:after { - opacity: 1; -} -.btn-toggle.btn-sm:before, -.btn-toggle.btn-sm:after { - line-height: -0.5rem; - color: #fff; - letter-spacing: 0.75px; - left: 0.4125rem; - width: 2.325rem; -} -.btn-toggle.btn-sm:before { - text-align: right; -} -.btn-toggle.btn-sm:after { - text-align: left; - opacity: 0; -} -.btn-toggle.btn-sm.active:before { - opacity: 0; -} -.btn-toggle.btn-sm.active:after { - opacity: 1; -} -.btn-toggle.btn-xs:before, -.btn-toggle.btn-xs:after { - display: none; -} -.btn-toggle:before, -.btn-toggle:after { - color: #6b7381; -} -.btn-toggle.active { - background-color: #29b5a8; -} -.btn-toggle.btn-lg:before, -.btn-toggle.btn-lg:after { - line-height: 2.5rem; - width: 5rem; - text-align: center; - font-weight: 600; - font-size: 1rem; - text-transform: uppercase; - letter-spacing: 2px; - position: absolute; - bottom: 0; - transition: opacity 0.25s; -} -.btn-toggle.btn-lg:before { - content: "Off"; - left: -5rem; -} -.btn-toggle.btn-lg:after { - content: "On"; - right: -5rem; - opacity: 0.5; -} -.btn-toggle.btn-lg > .handle { - position: absolute; - top: 0.3125rem; - left: 0.3125rem; - width: 1.875rem; - height: 1.875rem; - border-radius: 1.875rem; - background: #fff; - transition: left 0.25s; -} -.btn-toggle.btn-lg.active { - transition: background-color 0.25s; -} -.btn-toggle.btn-lg.active > .handle { - left: 2.8125rem; - transition: left 0.25s; -} -.btn-toggle.btn-lg.active:before { - opacity: 0.5; -} - -.hint { - font-size: 0.83rem; -} - -.help_container { - .heading { - font-size: 1.1rem; - font-weight: 600; - color: darken($text_color, 25%); - } - .desc { - font-size: 0.83rem; - } - ul { - margin: 0; - padding: 0; - li { - list-style: none; - margin-bottom: 1rem; - strong { - display: block; - } - code { - font-size: 0.83rem; - } - } - } -} - -.campaign_det { - .title { - font-size: 0.83rem; - .content { - font-size: 0.83rem; - } - .icon { - svg { - font-size: 0.7rem; - margin-left: 0.5rem; - } - } - } - .subject { - font-weight: bold; - margin: 0.4rem 0; - color: darken($text_color, 20%); - .icon { - svg { - font-size: 0.7rem; - margin-left: 0.5rem; - } - } - a { - font-size: 0.83rem; - color: darken($text_color, 20%); - .content { - font-size: 0.83rem; - color: darken($text_color, 20%); - } - } - } - .recievers { - .badge { - font-size: 0.83rem; - font-weight: 500; - } - } -} -.count_status { - margin: 1rem 0; - .well { - .badge { - font-size: 0.83rem !important; - } - .label { - font-size: 0.83rem; - font-weight: bold; - } - } -} -.mar_right_0 { - margin-right: 0 !important; -} -.demo_clist { - a { - font-size: 0.83rem; - color: darken($text_color, 15%); - font-weight: 600; - text-decoration: underline !important; - } -} -.table_det_section { - margin-bottom: 1rem; - .heading { - font-size: 1.3rem; - font-weight: 600; - } -} - -.copy-text { - border: 2px solid #dadada; - border-style: dashed; - padding: 10px; -} - -.help-text { - font-size: 12px; - color: #a7a7a7a7; -} - -.actions { - .edit, - .delete { - svg { - path { - fill: white; - } - } - } -} - -.btn-danger { - background-color: #ffc107; - border-color: #ffc107; - color: #fff !important; -} - -.btn-success { - color: #fff !important; - background-color: #099cbe; - border-color: #099cbe; -} - -.btn-info { - color: #fff !important; - background: #28a745; - border-color: #35a745; -} - -#dashboard{ - font-weight: 500; - font-size: 0.9rem; - padding: 10px 15px; - display: inline-block; - padding-top: 16px; - color: #4f616a!important; - border-bottom: 3px solid #099CBE; - float: right; -} -.intl-tel-input{ - display: block!important; -} \ No newline at end of file diff --git a/static/css/mention.css b/static/css/mention.css deleted file mode 100644 index 3ba9a63..0000000 --- a/static/css/mention.css +++ /dev/null @@ -1,67 +0,0 @@ -.mention-wrapper { - position: relative; - display: block; - width: 100%; - height: 100%; } - -.mention-wrapper textarea { - color: rgba(0, 0, 0, 0.1); } - -.mention-display { - color: rgba(0, 0, 0, 0.9); - position: absolute; - display: inline-block; - box-sizing: border-box; - pointer-events: none; - width: 100%; - height: 100%; - top: 0px; - left: 0px; - border-radius: 4px; - word-break: break-word; - -moz-appearance: textfield-multiline; - -webkit-appearance: textarea; - font: medium -moz-fixed; - font: -webkit-small-control; - border: 3px solid transparent; - padding: 10px; - font-size: 16px; } - -.mention-options { - position: absolute; - pointer-events: none; - opacity: 0; - color: rgba(0, 0, 0, 0.9); - width: 100%; - border: 3px solid transparent; - box-sizing: border-box; } - -.mention-options.show { - pointer-events: initial; - opacity: 1; - z-index: 9999; - border: 2px solid #ddd; - background: #ddd; } - -.mention-options .mention-option { - padding: 5px 10px; - background: #FFF; - position: relative; - cursor: pointer; - display: none; } - -.mention-options .mention-option:hover:after, .mention-options .mention-option.active:after { - content: ''; - position: absolute; - top: 0px; - left: 0px; - width: 100%; - height: 100%; - background: rgba(0, 0, 0, 0.1); - pointer-events: none; - cursor: pointer; } - -.mention-options .mention-option.show { - display: block; } - -/*# sourceMappingURL=mention.css.map */ diff --git a/static/css/mention.css.map b/static/css/mention.css.map deleted file mode 100644 index e6e84f5..0000000 --- a/static/css/mention.css.map +++ /dev/null @@ -1,7 +0,0 @@ -{ -"version": 3, -"mappings": "AAAA,gBAAiB;EACf,QAAQ,EAAE,QAAQ;EAClB,OAAO,EAAE,KAAK;EACd,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,IAAI;;AAGd,yBAA0B;EAAE,KAAK,EAAE,kBAAkB;;AAErD,gBAAiB;EACf,KAAK,EAAE,kBAAkB;EACzB,QAAQ,EAAE,QAAQ;EAClB,OAAO,EAAE,YAAY;EACrB,UAAU,EAAE,UAAU;EACtB,cAAc,EAAE,IAAI;EACpB,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,IAAI;EACZ,GAAG,EAAE,GAAG;EACR,IAAI,EAAE,GAAG;EACT,aAAa,EAAE,GAAG;EAClB,UAAU,EAAE,UAAU;EACtB,eAAe,EAAE,mBAAmB;EACpC,kBAAkB,EAAE,QAAQ;EAC5B,IAAI,EAAE,iBAAiB;EACvB,IAAI,EAAE,qBAAqB;EAC3B,MAAM,EAAE,qBAAqB;EAC7B,OAAO,EAAE,IAAI;EACb,SAAS,EAAE,IAAI;;AAGjB,gBAAiB;EACf,QAAQ,EAAE,QAAQ;EAClB,cAAc,EAAE,IAAI;EACpB,OAAO,EAAE,CAAC;EACV,KAAK,EAAE,kBAAkB;EACzB,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,qBAAqB;EAC7B,UAAU,EAAE,UAAU;;AAGxB,qBAAsB;EACpB,cAAc,EAAE,OAAO;EACvB,OAAO,EAAE,CAAC;EACV,OAAO,EAAE,IAAI;EACb,MAAM,EAAE,cAAc;EACtB,UAAU,EAAE,IAAI;;AAIlB,gCAAiC;EAC/B,OAAO,EAAE,QAAQ;EACjB,UAAU,EAAE,IAAI;EAChB,QAAQ,EAAE,QAAQ;EAClB,MAAM,EAAE,OAAO;EACf,OAAO,EAAE,IAAI;;AAGf,2FAA4F;EAC1F,OAAO,EAAE,EAAE;EACX,QAAQ,EAAE,QAAQ;EAClB,GAAG,EAAE,GAAG;EACR,IAAI,EAAE,GAAG;EACT,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,IAAI;EACZ,UAAU,EAAE,kBAAkB;EAC9B,cAAc,EAAE,IAAI;EACpB,MAAM,EAAE,OAAO;;AAGjB,qCAAsC;EAAE,OAAO,EAAE,KAAK", -"sources": ["mention.scss"], -"names": [], -"file": "mention.css" -} \ No newline at end of file diff --git a/static/css/mention.scss b/static/css/mention.scss deleted file mode 100644 index 9db9467..0000000 --- a/static/css/mention.scss +++ /dev/null @@ -1,70 +0,0 @@ -.mention-wrapper { - position: relative; - display: block; - width: 100%; - height: 100%; -} - -.mention-wrapper textarea { color: rgba(0, 0, 0, 0.1); } - -.mention-display { - color: rgba(0, 0, 0, 0.9); - position: absolute; - display: inline-block; - box-sizing: border-box; - pointer-events: none; - width: 100%; - height: 100%; - top: 0px; - left: 0px; - border-radius: 4px; - word-break: break-word; - -moz-appearance: textfield-multiline; - -webkit-appearance: textarea; - font: medium -moz-fixed; - font: -webkit-small-control; - border: 3px solid transparent; - padding: 10px; - font-size: 16px; -} - -.mention-options { - position: absolute; - pointer-events: none; - opacity: 0; - color: rgba(0, 0, 0, 0.9); - width: 100%; - border: 3px solid transparent; - box-sizing: border-box; -} - -.mention-options.show { - pointer-events: initial; - opacity: 1; - z-index: 9999; - border: 2px solid #ddd; - background: #ddd; -} - - -.mention-options .mention-option { - padding: 5px 10px; - background: #FFF; - position: relative; - cursor: pointer; - display: none; -} - -.mention-options .mention-option:hover:after, .mention-options .mention-option.active:after { - content: ''; - position: absolute; - top: 0px; - left: 0px; - width: 100%; - height: 100%; - background: rgba(0, 0, 0, 0.1); - pointer-events: none; - cursor: pointer; -} - -.mention-options .mention-option.show { display: block; } diff --git a/static/css/ref.scss b/static/css/ref.scss deleted file mode 100644 index ce066fa..0000000 --- a/static/css/ref.scss +++ /dev/null @@ -1,178 +0,0 @@ -//colors -$white: #fff; -$body_bg: #808080; -$login_bg:#fff; -$text_color:#5a6e79; -$text_color2:#7E849D; -$text_color3:#aaa; -$color_cyan_aqua_approx: #00e5ff; -$color_screamin_green_approx: #7eea51; -$color_apricot_peach_approx: #f6cdab; -$color_blue_dianne_approx: #273e48; -$color_cerise_red_approx: #e92064; -$login_btn_bg:#dc3545; -$info_color:#138496; -$dark_sky:#099CBE; -$dark_yellow:#FEA124; -$inner_page_bg:#CDCDCD; -$green: #7ae847; -$d_green: #06ae90; -$red:#fb1e07; -$sky_color:#099CBE; -$green: #7ae847; -$blue: #1095fe; -$purple: #9414c9; - - - - -//mediaviews -$large:1500px; -$med_min:992px; -$med_max:1199px; -$tab_max:991px; -$tab_min:768px; -$smob_max:767px; -$smob_min:480px; -$mob_max:479px; -$mob_min:240px; - -.btn-primary{ - bordeR:1x solid $dark_sky !important; -} - -.card{ - border:1px solid #ccc; -} - -.heading{ - margin-bottom: 1rem; - span{ - font-size: 1.35rem; - } -} -.buttons_row{ -/* margin-top: 10px; - margin-bottom: 10px;*/ - button{ - border-radius: 0; - font-size: 0.85rem; - font-weight: 600; - &.save{ - background: $dark_sky; - color: #fff; - } - } - .clear{ - border:1px solid $dark_sky; - border:1px solid $dark_sky; - border-radius: 0; - color: $dark_sky; - font-size: 0.85rem; - } - &.form_btn_row{ - display: block; - } -} -.table-responsive{ - padding:10px; -} -select{ - &.form-control{ - font-size: 0.85rem; - } -} - -.mar-top{ - margin-top: 15px; -} - -.table{ - tbody{ - tr{ - td{ - &.user_role{ - text-transform: capitalize; - } - } - } - } -} -.dropdown{ - .dropdown-menu{ - padding: 0; - border-radius: 0; - li{ - a{ - padding: 8px 8px; - display: block; - border-bottom: 1px solid #dedede; - } - } - } -} - - -.box{ - background: red; - display: inline-block; - width: 2rem; - height: 2rem; - line-height: 1.6rem; - border-radius: 3px; - text-align: center; - padding-top: 0.1rem; - transition: 0.6s all ease-out; - &.sky_blue{ - background: lighten($sky_color, 55%); - color: $sky_color; - &:hover{ - background: $sky_color; - } - } - &.red{ - background: lighten($red, 45%); - color: $red; - &:hover{ - background: $red; - } - } - &.green{ - background: lighten($d_green, 55%); - color: $d_green; - &:hover{ - background: $d_green; - } - } - &.l_green{ - background: lighten($green, 55%); - color: $green; - &:hover{ - background: $green; - } - } - &.purple{ - background: lighten($purple, 50%); - color: $purple; - &:hover{ - background: $purple; - } - } - &.yellow{ - background: lighten($dark_yellow, 50%); - color: $dark_yellow; - &:hover{ - background: $dark_yellow; - } - } - &.dark_grey{ - background: lighten(#6c757d, 45%); - color: #6c757d; - &:hover{ - background: #6c757d; - } - } - &:hover{ - color: #fff; - } -} \ No newline at end of file diff --git a/static/files/contacts_sample.csv b/static/files/contacts_sample.csv deleted file mode 100644 index e0c9214..0000000 --- a/static/files/contacts_sample.csv +++ /dev/null @@ -1,4 +0,0 @@ -company name,email,first name,last name,city,state -micropyramid,admin@micropyramid.com,Admin,MP,Hyderabad,Telangana -micropyramid,hr@micropyramid.com,HR,MP,Hyderabad,Telangana -micropyramid,contactus@micropyramid.com,Contact US,MP,Hyderabad,Telangana diff --git a/static/images/busy.gif b/static/images/busy.gif deleted file mode 100644 index c480dd0..0000000 Binary files a/static/images/busy.gif and /dev/null differ diff --git a/static/images/company.png b/static/images/company.png deleted file mode 100644 index fb2d934..0000000 Binary files a/static/images/company.png and /dev/null differ diff --git a/static/images/user.png b/static/images/user.png deleted file mode 100755 index c0b9594..0000000 Binary files a/static/images/user.png and /dev/null differ diff --git a/static/js/ajaxForm.js b/static/js/ajaxForm.js deleted file mode 100644 index 5006b2c..0000000 --- a/static/js/ajaxForm.js +++ /dev/null @@ -1,1277 +0,0 @@ -/*! - * jQuery Form Plugin - * version: 3.51.0-2014.06.20 - * Requires jQuery v1.5 or later - * Copyright (c) 2014 M. Alsup - * Examples and documentation at: http://malsup.com/jquery/form/ - * Project repository: https://github.com/malsup/form - * Dual licensed under the MIT and GPL licenses. - * https://github.com/malsup/form#copyright-and-license - */ -/*global ActiveXObject */ - -// AMD support -(function (factory) { - "use strict"; - if (typeof define === 'function' && define.amd) { - // using AMD; register as anon module - define(['jquery'], factory); - } else { - // no AMD; invoke directly - factory( (typeof(jQuery) != 'undefined') ? jQuery : window.Zepto ); - } -} - -(function($) { -"use strict"; - -/* - Usage Note: - ----------- - Do not use both ajaxSubmit and ajaxForm on the same form. These - functions are mutually exclusive. Use ajaxSubmit if you want - to bind your own submit handler to the form. For example, - - $(document).ready(function() { - $('#myForm').on('submit', function(e) { - e.preventDefault(); // <-- important - $(this).ajaxSubmit({ - target: '#output' - }); - }); - }); - - Use ajaxForm when you want the plugin to manage all the event binding - for you. For example, - - $(document).ready(function() { - $('#myForm').ajaxForm({ - target: '#output' - }); - }); - - You can also use ajaxForm with delegation (requires jQuery v1.7+), so the - form does not have to exist when you invoke ajaxForm: - - $('#myForm').ajaxForm({ - delegation: true, - target: '#output' - }); - - When using ajaxForm, the ajaxSubmit function will be invoked for you - at the appropriate time. -*/ - -/** - * Feature detection - */ -var feature = {}; -feature.fileapi = $("").get(0).files !== undefined; -feature.formdata = window.FormData !== undefined; - -var hasProp = !!$.fn.prop; - -// attr2 uses prop when it can but checks the return type for -// an expected string. this accounts for the case where a form -// contains inputs with names like "action" or "method"; in those -// cases "prop" returns the element -$.fn.attr2 = function() { - if ( ! hasProp ) { - return this.attr.apply(this, arguments); - } - var val = this.prop.apply(this, arguments); - if ( ( val && val.jquery ) || typeof val === 'string' ) { - return val; - } - return this.attr.apply(this, arguments); -}; - -/** - * ajaxSubmit() provides a mechanism for immediately submitting - * an HTML form using AJAX. - */ -$.fn.ajaxSubmit = function(options) { - /*jshint scripturl:true */ - - // fast fail if nothing selected (http://dev.jquery.com/ticket/2752) - if (!this.length) { - log('ajaxSubmit: skipping submit process - no element selected'); - return this; - } - - var method, action, url, $form = this; - - if (typeof options == 'function') { - options = { success: options }; - } - else if ( options === undefined ) { - options = {}; - } - - method = options.type || this.attr2('method'); - action = options.url || this.attr2('action'); - - url = (typeof action === 'string') ? $.trim(action) : ''; - url = url || window.location.href || ''; - if (url) { - // clean url (don't include hash value) - url = (url.match(/^([^#]+)/)||[])[1]; - } - - options = $.extend(true, { - url: url, - success: $.ajaxSettings.success, - type: method || $.ajaxSettings.type, - iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank' - }, options); - - // hook for manipulating the form data before it is extracted; - // convenient for use with rich editors like tinyMCE or FCKEditor - var veto = {}; - this.trigger('form-pre-serialize', [this, options, veto]); - if (veto.veto) { - log('ajaxSubmit: submit vetoed via form-pre-serialize trigger'); - return this; - } - - // provide opportunity to alter form data before it is serialized - if (options.beforeSerialize && options.beforeSerialize(this, options) === false) { - log('ajaxSubmit: submit aborted via beforeSerialize callback'); - return this; - } - - var traditional = options.traditional; - if ( traditional === undefined ) { - traditional = $.ajaxSettings.traditional; - } - - var elements = []; - var qx, a = this.formToArray(options.semantic, elements); - if (options.data) { - options.extraData = options.data; - qx = $.param(options.data, traditional); - } - - // give pre-submit callback an opportunity to abort the submit - if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) { - log('ajaxSubmit: submit aborted via beforeSubmit callback'); - return this; - } - - // fire vetoable 'validate' event - this.trigger('form-submit-validate', [a, this, options, veto]); - if (veto.veto) { - log('ajaxSubmit: submit vetoed via form-submit-validate trigger'); - return this; - } - - var q = $.param(a, traditional); - if (qx) { - q = ( q ? (q + '&' + qx) : qx ); - } - if (options.type.toUpperCase() == 'GET') { - options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q; - options.data = null; // data is null for 'get' - } - else { - options.data = q; // data is the query string for 'post' - } - - var callbacks = []; - if (options.resetForm) { - callbacks.push(function() { $form.resetForm(); }); - } - if (options.clearForm) { - callbacks.push(function() { $form.clearForm(options.includeHidden); }); - } - - // perform a load on the target only if dataType is not provided - if (!options.dataType && options.target) { - var oldSuccess = options.success || function(){}; - callbacks.push(function(data) { - var fn = options.replaceTarget ? 'replaceWith' : 'html'; - $(options.target)[fn](data).each(oldSuccess, arguments); - }); - } - else if (options.success) { - callbacks.push(options.success); - } - - options.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg - var context = options.context || this ; // jQuery 1.4+ supports scope context - for (var i=0, max=callbacks.length; i < max; i++) { - callbacks[i].apply(context, [data, status, xhr || $form, $form]); - } - }; - - if (options.error) { - var oldError = options.error; - options.error = function(xhr, status, error) { - var context = options.context || this; - oldError.apply(context, [xhr, status, error, $form]); - }; - } - - if (options.complete) { - var oldComplete = options.complete; - options.complete = function(xhr, status) { - var context = options.context || this; - oldComplete.apply(context, [xhr, status, $form]); - }; - } - - // are there files to upload? - - // [value] (issue #113), also see comment: - // https://github.com/malsup/form/commit/588306aedba1de01388032d5f42a60159eea9228#commitcomment-2180219 - var fileInputs = $('input[type=file]:enabled', this).filter(function() { return $(this).val() !== ''; }); - - var hasFileInputs = fileInputs.length > 0; - var mp = 'multipart/form-data'; - var multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp); - - var fileAPI = feature.fileapi && feature.formdata; - log("fileAPI :" + fileAPI); - var shouldUseFrame = (hasFileInputs || multipart) && !fileAPI; - - var jqxhr; - - // options.iframe allows user to force iframe mode - // 06-NOV-09: now defaulting to iframe mode if file input is detected - if (options.iframe !== false && (options.iframe || shouldUseFrame)) { - // hack to fix Safari hang (thanks to Tim Molendijk for this) - // see: http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d - if (options.closeKeepAlive) { - $.get(options.closeKeepAlive, function() { - jqxhr = fileUploadIframe(a); - }); - } - else { - jqxhr = fileUploadIframe(a); - } - } - else if ((hasFileInputs || multipart) && fileAPI) { - jqxhr = fileUploadXhr(a); - } - else { - jqxhr = $.ajax(options); - } - - $form.removeData('jqxhr').data('jqxhr', jqxhr); - - // clear element array - for (var k=0; k < elements.length; k++) { - elements[k] = null; - } - - // fire 'notify' event - this.trigger('form-submit-notify', [this, options]); - return this; - - // utility fn for deep serialization - function deepSerialize(extraData){ - var serialized = $.param(extraData, options.traditional).split('&'); - var len = serialized.length; - var result = []; - var i, part; - for (i=0; i < len; i++) { - // #252; undo param space replacement - serialized[i] = serialized[i].replace(/\+/g,' '); - part = serialized[i].split('='); - // #278; use array instead of object storage, favoring array serializations - result.push([decodeURIComponent(part[0]), decodeURIComponent(part[1])]); - } - return result; - } - - // XMLHttpRequest Level 2 file uploads (big hat tip to francois2metz) - function fileUploadXhr(a) { - var formdata = new FormData(); - - for (var i=0; i < a.length; i++) { - formdata.append(a[i].name, a[i].value); - } - - if (options.extraData) { - var serializedData = deepSerialize(options.extraData); - for (i=0; i < serializedData.length; i++) { - if (serializedData[i]) { - formdata.append(serializedData[i][0], serializedData[i][1]); - } - } - } - - options.data = null; - - var s = $.extend(true, {}, $.ajaxSettings, options, { - contentType: false, - processData: false, - cache: false, - type: method || 'POST' - }); - - if (options.uploadProgress) { - // workaround because jqXHR does not expose upload property - s.xhr = function() { - var xhr = $.ajaxSettings.xhr(); - if (xhr.upload) { - xhr.upload.addEventListener('progress', function(event) { - var percent = 0; - var position = event.loaded || event.position; /*event.position is deprecated*/ - var total = event.total; - if (event.lengthComputable) { - percent = Math.ceil(position / total * 100); - } - options.uploadProgress(event, position, total, percent); - }, false); - } - return xhr; - }; - } - - s.data = null; - var beforeSend = s.beforeSend; - s.beforeSend = function(xhr, o) { - //Send FormData() provided by user - if (options.formData) { - o.data = options.formData; - } - else { - o.data = formdata; - } - if(beforeSend) { - beforeSend.call(this, xhr, o); - } - }; - return $.ajax(s); - } - - // private function for handling file uploads (hat tip to YAHOO!) - function fileUploadIframe(a) { - var form = $form[0], el, i, s, g, id, $io, io, xhr, sub, n, timedOut, timeoutHandle; - var deferred = $.Deferred(); - - // #341 - deferred.abort = function(status) { - xhr.abort(status); - }; - - if (a) { - // ensure that every serialized input is still enabled - for (i=0; i < elements.length; i++) { - el = $(elements[i]); - if ( hasProp ) { - el.prop('disabled', false); - } - else { - el.removeAttr('disabled'); - } - } - } - - s = $.extend(true, {}, $.ajaxSettings, options); - s.context = s.context || s; - id = 'jqFormIO' + (new Date().getTime()); - if (s.iframeTarget) { - $io = $(s.iframeTarget); - n = $io.attr2('name'); - if (!n) { - $io.attr2('name', id); - } - else { - id = n; - } - } - else { - $io = $('