diff --git a/.gitignore b/.gitignore index a8b5fa0..a5df4a6 100644 --- a/.gitignore +++ b/.gitignore @@ -476,3 +476,7 @@ code.style.schemes.xml # Pyre type checker # End of https://www.gitignore.io/api/pycharm,python,django + +# virtualenv +bin +include diff --git a/JH_RestAPI/settings.py b/JH_RestAPI/settings.py index 725c071..7a49c31 100644 --- a/JH_RestAPI/settings.py +++ b/JH_RestAPI/settings.py @@ -39,26 +39,21 @@ 'django.contrib.messages', 'django.contrib.staticfiles', 'background_task', - 'rest_framework', # new + 'rest_framework', # new\ 'corsheaders', 'oauth2_provider', 'social_django', 'rest_framework_social_oauth2', 'users', - 'alumni', - 'event', 'major', 'college', - 'jobapps', - 'metrics', - 'blog', - 'poll', + 'positionapps', 'company', 'position', 'notifications', - 'review', 'faq', 'utils', + 'cvparser', ] MIDDLEWARE = [ @@ -119,8 +114,10 @@ 'JH_RestAPI.backends.ModelBackend', ) -SOCIAL_AUTH_LINKEDIN_OAUTH2_KEY = os.environ.get('JOBHAX_LINKEDIN_CLIENT_KEY', '') -SOCIAL_AUTH_LINKEDIN_OAUTH2_SECRET = os.environ.get('JOBHAX_LINKEDIN_CLIENT_SECRET', '') +SOCIAL_AUTH_LINKEDIN_OAUTH2_KEY = os.environ.get( + 'JOBHAX_LINKEDIN_CLIENT_KEY', '') +SOCIAL_AUTH_LINKEDIN_OAUTH2_SECRET = os.environ.get( + 'JOBHAX_LINKEDIN_CLIENT_SECRET', '') SOCIAL_AUTH_LINKEDIN_OAUTH2_SCOPE = ['r_emailaddress', 'r_liteprofile'] SOCIAL_AUTH_LINKEDIN_OAUTH2_FIELD_SELECTORS = [ @@ -129,7 +126,8 @@ if DEBUG: SOCIAL_AUTH_LOGIN_REDIRECT_URL = 'http://localhost:8080/action-linkedin-oauth2' else: - SOCIAL_AUTH_LOGIN_REDIRECT_URL = 'https://' + SITE_URL + '/action-linkedin-oauth2' + SOCIAL_AUTH_LOGIN_REDIRECT_URL = 'https://' + \ + SITE_URL + '/action-linkedin-oauth2' SOCIAL_AUTH_PIPELINE = ( 'social_core.pipeline.social_auth.social_details', @@ -190,7 +188,7 @@ 'ENGINE': 'django.db.backends.postgresql', 'NAME': 'jobhaxdb', 'USER': 'jobhaxdbuser', - 'PASSWORD': '123456', + 'PASSWORD': 'Proddb1234#', 'HOST': 'localhost' } } diff --git a/JH_RestAPI/urls.py b/JH_RestAPI/urls.py index 31fdf52..f30ed1f 100644 --- a/JH_RestAPI/urls.py +++ b/JH_RestAPI/urls.py @@ -23,22 +23,18 @@ urlpatterns = [ path('admin/', admin.site.urls), path('api/users/', include('users.urls')), - path('api/jobapps/', include('jobapps.urls')), - path('api/metrics/', include('metrics.urls')), - path('api/polls/', include('poll.urls')), + path('api/positionapps/', include('positionapps.urls')), path('api/faqs/', include('faq.urls')), - path('api/blogs/', include('blog.urls')), path('api/notifications/', include('notifications.urls')), path('api/companies/', include('company.urls')), - path('api/events/', include('event.urls')), path('api/colleges/', include('college.urls')), path('api/majors/', include('major.urls')), - path('api/alumni/', include('alumni.urls')), path('api/positions/', include('position.urls')), - path('api/reviews/', include('review.urls')), + path('api/parser/', include('cvparser.urls')), path('api/', include('utils.urls')), re_path(r'^auth/', include('rest_framework_social_oauth2.urls')), ] if settings.DEBUG: - urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + urlpatterns += static(settings.MEDIA_URL, + document_root=settings.MEDIA_ROOT) diff --git a/README.md b/README.md index 06f8d1b..195159b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ ### Quickstart +![JobHax Website](https://img.shields.io/website?label=jobposting-be.jobhax.com/admin&up_message=Up%20and%20Running&url=https%3A%2F%2Fjobposting.jobhax.com) ![Alt text](https://img.shields.io/github/issues-raw/job-hax/backend.svg) ![GitHub commit activity](https://img.shields.io/github/commit-activity/w/job-hax/backend.svg?style=plastic) ![GitHub contributors](https://img.shields.io/github/contributors/job-hax/backend.svg) @@ -42,7 +43,7 @@ export JOBHAX_LINKEDIN_CLIENT_SECRET=/*linkedin application client_secret*/ #to 7. To use Rest API you need to create oauth2 credentials. ``` -- Under http://localhost:8000/admin/oauth2_provider/application/ click 'ADD APPLICATION' +- Under http://localhost:8001/admin/oauth2_provider/application/ click 'ADD APPLICATION' - Do not change 'client_id' & 'client_secret' (They will be used for generate access token to use in your requests header) diff --git a/alumni/admin.py b/alumni/admin.py deleted file mode 100644 index 846f6b4..0000000 --- a/alumni/admin.py +++ /dev/null @@ -1 +0,0 @@ -# Register your models here. diff --git a/alumni/apps.py b/alumni/apps.py deleted file mode 100644 index a2004e9..0000000 --- a/alumni/apps.py +++ /dev/null @@ -1,5 +0,0 @@ -from django.apps import AppConfig - - -class AlumniConfig(AppConfig): - name = 'alumni' diff --git a/alumni/models.py b/alumni/models.py deleted file mode 100644 index 6b20219..0000000 --- a/alumni/models.py +++ /dev/null @@ -1 +0,0 @@ -# Create your models here. diff --git a/alumni/serializers.py b/alumni/serializers.py deleted file mode 100644 index 5d034eb..0000000 --- a/alumni/serializers.py +++ /dev/null @@ -1,30 +0,0 @@ -from django.contrib.auth import get_user_model -from rest_framework import serializers - -from college.serializers import CollegeSerializer -from company.serializers import CompanyBasicsSerializer -from major.serializers import MajorSerializer -from position.serializers import JobPositionSerializer -from utils.serializers import CountrySerializer, StateSerializer - - -class AlumniSerializer(serializers.ModelSerializer): - college = CollegeSerializer(read_only=True) - major = MajorSerializer(read_only=True) - company = CompanyBasicsSerializer(read_only=True) - country = CountrySerializer(read_only=True) - state = StateSerializer(read_only=True) - job_position = JobPositionSerializer(read_only=True) - email = serializers.SerializerMethodField() - - def get_email(self, obj): - if obj.is_email_public: - return obj.email - else: - return None - - class Meta: - model = get_user_model() - fields = ( - 'id', 'first_name', 'last_name', 'email', 'college', 'major', 'company', 'country', 'state', 'job_position', - 'profile_photo', 'grad_year') diff --git a/alumni/urls.py b/alumni/urls.py deleted file mode 100644 index d9c37d9..0000000 --- a/alumni/urls.py +++ /dev/null @@ -1,15 +0,0 @@ -from django.urls import path -from rest_framework.urlpatterns import format_suffix_patterns - -from alumni import views - -urlpatterns = [ - path('', views.alumni), - path('majors/', - views.majors), - path('companies/', - views.companies), - path('positions/', - views.positions), -] -urlpatterns = format_suffix_patterns(urlpatterns) diff --git a/alumni/views.py b/alumni/views.py deleted file mode 100644 index c6849cc..0000000 --- a/alumni/views.py +++ /dev/null @@ -1,111 +0,0 @@ -from django.contrib.auth import get_user_model -from django.db.models import Q -from django.http import JsonResponse -from django.views.decorators.csrf import csrf_exempt -from rest_framework.decorators import api_view - -from JH_RestAPI import pagination -from utils.generic_json_creator import create_response -from .serializers import AlumniSerializer -from major.serializers import MajorSerializer -from company.serializers import CompanyBasicsSerializer -from college.models import College -from utils.error_codes import ResponseCodes -from position.serializers import JobPositionSerializer - -User = get_user_model() - - -@csrf_exempt -@api_view(["GET"]) -def alumni(request): - user_profile = request.user - if not user_profile.user_type.alumni_listing_enabled: - return JsonResponse(create_response(data=None, success=False, error_code=ResponseCodes.not_supported_user), - safe=False) - alumni_list = User.objects.filter(user_type__name__iexact='Alumni', college__pk=user_profile.college.id) - - q = request.GET.get('q') - year = request.GET.get('year') - major_id = request.GET.get('major_id') - company_id = request.GET.get('company_id') - position_id = request.GET.get('position_id') - country_id = request.GET.get('country_id') - state_id = request.GET.get('state_id') - if q is not None: - alumni_list = alumni_list.filter(Q(first_name__icontains=q) | Q(last_name__icontains=q)) - if year is not None: - alumni_list = alumni_list.filter(grad_year=year) - if major_id is not None: - alumni_list = alumni_list.filter(major__pk=major_id) - if company_id is not None: - alumni_list = alumni_list.filter(company__pk=company_id) - if position_id is not None: - alumni_list = alumni_list.filter(job_position__pk=position_id) - if country_id is not None: - alumni_list = alumni_list.filter(country__pk=country_id) - if state_id is not None: - alumni_list = alumni_list.filter(state__pk=state_id) - - paginator = pagination.CustomPagination() - alumni_list = paginator.paginate_queryset(alumni_list, request) - serialized_alumni = AlumniSerializer( - instance=alumni_list, many=True, context={'user': request.user}).data - return JsonResponse(create_response(data=serialized_alumni, paginator=paginator), safe=False) - - -@csrf_exempt -@api_view(["GET"]) -def majors(request): - user_profile = request.user - if not user_profile.user_type.alumni_listing_enabled: - return JsonResponse(create_response(data=None, success=False, error_code=ResponseCodes.not_supported_user), - safe=False) - college = College.objects.get(pk=user_profile.college.pk) - alumni = User.objects.filter(~Q(major=None), college=college, user_type__name__iexact='Alumni') - data = [] - for a in alumni: - if a.major is not None: - data.append(a.major) - data = set(data) - serialized_majors = MajorSerializer( - instance=data, many=True, ).data - return JsonResponse(create_response(data=serialized_majors), safe=False) - - -@csrf_exempt -@api_view(["GET"]) -def companies(request): - user_profile = request.user - if not user_profile.user_type.alumni_listing_enabled: - return JsonResponse(create_response(data=None, success=False, error_code=ResponseCodes.not_supported_user), - safe=False) - college = College.objects.get(pk=user_profile.college.pk) - alumni = User.objects.filter(~Q(major=None), college=college, user_type__name__iexact='Alumni') - data = [] - for a in alumni: - if a.company is not None: - data.append(a.company) - data = set(data) - serialized_companies = CompanyBasicsSerializer( - instance=data, many=True, ).data - return JsonResponse(create_response(data=serialized_companies), safe=False) - - -@csrf_exempt -@api_view(["GET"]) -def positions(request): - user_profile = request.user - if not user_profile.user_type.alumni_listing_enabled: - return JsonResponse(create_response(data=None, success=False, error_code=ResponseCodes.not_supported_user), - safe=False) - college = College.objects.get(pk=user_profile.college.pk) - alumni = User.objects.filter(~Q(major=None), college=college, user_type__name__iexact='Alumni') - data = [] - for a in alumni: - if a.job_position is not None: - data.append(a.job_position) - data = set(data) - serialized_positions = JobPositionSerializer( - instance=data, many=True, ).data - return JsonResponse(create_response(data=serialized_positions), safe=False) diff --git a/blog/admin.py b/blog/admin.py deleted file mode 100644 index ef9df9b..0000000 --- a/blog/admin.py +++ /dev/null @@ -1,10 +0,0 @@ -from django.contrib import admin - -from .models import Blog - -@admin.register(Blog) -class BlogAdmin(admin.ModelAdmin): - list_display = ('publisher_profile', 'title', 'view_count', - 'created_at', 'updated_at', 'is_publish', 'is_approved') - list_filter = ('publisher_profile', 'title', 'view_count', - 'created_at', 'updated_at', 'is_publish', 'is_approved') diff --git a/blog/apps.py b/blog/apps.py deleted file mode 100644 index 7930587..0000000 --- a/blog/apps.py +++ /dev/null @@ -1,5 +0,0 @@ -from django.apps import AppConfig - - -class BlogConfig(AppConfig): - name = 'blog' diff --git a/blog/migrations/0001_initial.py b/blog/migrations/0001_initial.py deleted file mode 100644 index 2a6f45d..0000000 --- a/blog/migrations/0001_initial.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 2.1.5 on 2019-04-22 20:18 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - initial = True - - dependencies = [ - ] - - operations = [ - migrations.CreateModel( - name='Blog', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('title', models.CharField(max_length=50)), - ('content', models.TextField()), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('updated_at', models.DateTimeField(auto_now=True)), - ], - ), - ] diff --git a/blog/migrations/0002_auto_20190422_2110.py b/blog/migrations/0002_auto_20190422_2110.py deleted file mode 100644 index bcb682d..0000000 --- a/blog/migrations/0002_auto_20190422_2110.py +++ /dev/null @@ -1,27 +0,0 @@ -# Generated by Django 2.1.5 on 2019-04-22 21:10 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('blog', '0001_initial'), - ] - - operations = [ - migrations.AddField( - model_name='blog', - name='image', - field=models.CharField(max_length=200, null=True), - ), - migrations.AddField( - model_name='blog', - name='is_html', - field=models.BooleanField(default=False), - ), - migrations.AddField( - model_name='blog', - name='snippet', - field=models.CharField(max_length=150, null=True), - ), - ] diff --git a/blog/migrations/0003_auto_20190423_1935.py b/blog/migrations/0003_auto_20190423_1935.py deleted file mode 100644 index 0901345..0000000 --- a/blog/migrations/0003_auto_20190423_1935.py +++ /dev/null @@ -1,27 +0,0 @@ -# Generated by Django 2.2 on 2019-04-23 19:35 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('blog', '0002_auto_20190422_2110'), - ] - - operations = [ - migrations.AddField( - model_name='blog', - name='downvote', - field=models.IntegerField(default=0), - ), - migrations.AddField( - model_name='blog', - name='upvote', - field=models.IntegerField(default=0), - ), - migrations.AddField( - model_name='blog', - name='view_count', - field=models.IntegerField(default=0), - ), - ] diff --git a/blog/migrations/0004_auto_20190423_1947.py b/blog/migrations/0004_auto_20190423_1947.py deleted file mode 100644 index db6561a..0000000 --- a/blog/migrations/0004_auto_20190423_1947.py +++ /dev/null @@ -1,33 +0,0 @@ -# Generated by Django 2.2 on 2019-04-23 19:47 - -import django.db.models.deletion -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('blog', '0003_auto_20190423_1935'), - ] - - operations = [ - migrations.RemoveField( - model_name='blog', - name='downvote', - ), - migrations.RemoveField( - model_name='blog', - name='upvote', - ), - migrations.CreateModel( - name='Vote', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('vote_type', models.BooleanField(default=False)), - ('blog', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='blog.Blog')), - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='vote_user', - to=settings.AUTH_USER_MODEL)), - ], - ), - ] diff --git a/blog/migrations/0005_auto_20190429_1944.py b/blog/migrations/0005_auto_20190429_1944.py deleted file mode 100644 index 110726c..0000000 --- a/blog/migrations/0005_auto_20190429_1944.py +++ /dev/null @@ -1,16 +0,0 @@ -# Generated by Django 2.2 on 2019-04-29 19:44 - -from django.db import migrations - - -class Migration(migrations.Migration): - dependencies = [ - ('blog', '0004_auto_20190423_1947'), - ] - - operations = [ - migrations.AlterModelOptions( - name='blog', - options={'ordering': ['-created_at']}, - ), - ] diff --git a/blog/migrations/0006_auto_20190429_2000.py b/blog/migrations/0006_auto_20190429_2000.py deleted file mode 100644 index a28b35e..0000000 --- a/blog/migrations/0006_auto_20190429_2000.py +++ /dev/null @@ -1,22 +0,0 @@ -# Generated by Django 2.2 on 2019-04-29 20:00 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('blog', '0005_auto_20190429_1944'), - ] - - operations = [ - migrations.AddField( - model_name='blog', - name='author_image', - field=models.CharField(max_length=200, null=True), - ), - migrations.AddField( - model_name='blog', - name='author_name', - field=models.CharField(default='JobHax', max_length=30), - ), - ] diff --git a/blog/migrations/0007_auto_20190429_2002.py b/blog/migrations/0007_auto_20190429_2002.py deleted file mode 100644 index bd66295..0000000 --- a/blog/migrations/0007_auto_20190429_2002.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 2.2 on 2019-04-29 20:02 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('blog', '0006_auto_20190429_2000'), - ] - - operations = [ - migrations.AlterField( - model_name='blog', - name='author_image', - field=models.CharField(blank=True, max_length=200, null=True), - ), - ] diff --git a/blog/migrations/0008_auto_20190429_2006.py b/blog/migrations/0008_auto_20190429_2006.py deleted file mode 100644 index 74ab615..0000000 --- a/blog/migrations/0008_auto_20190429_2006.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 2.2 on 2019-04-29 20:06 - -import django.core.validators -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('blog', '0007_auto_20190429_2002'), - ] - - operations = [ - migrations.AlterField( - model_name='blog', - name='snippet', - field=models.CharField(max_length=400, null=True, - validators=[django.core.validators.MinLengthValidator(250)]), - ), - ] diff --git a/blog/migrations/0009_auto_20190807_0459.py b/blog/migrations/0009_auto_20190807_0459.py deleted file mode 100644 index 7ecaf25..0000000 --- a/blog/migrations/0009_auto_20190807_0459.py +++ /dev/null @@ -1,38 +0,0 @@ -# Generated by Django 2.2 on 2019-08-07 04:59 - -import django.db.models.deletion -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('blog', '0008_auto_20190429_2006'), - ] - - operations = [ - migrations.RemoveField( - model_name='blog', - name='author_image', - ), - migrations.RemoveField( - model_name='blog', - name='author_name', - ), - migrations.RemoveField( - model_name='blog', - name='image', - ), - migrations.AddField( - model_name='blog', - name='header_image', - field=models.FileField(blank=True, null=True, upload_to=''), - ), - migrations.AddField( - model_name='blog', - name='publisher_profile', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, - to=settings.AUTH_USER_MODEL), - ), - ] diff --git a/blog/migrations/0010_auto_20190807_0515.py b/blog/migrations/0010_auto_20190807_0515.py deleted file mode 100644 index 2c1cc08..0000000 --- a/blog/migrations/0010_auto_20190807_0515.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 2.2 on 2019-08-07 05:15 - -import django.core.files.storage -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('blog', '0009_auto_20190807_0459'), - ] - - operations = [ - migrations.AlterField( - model_name='blog', - name='header_image', - field=models.FileField(blank=True, null=True, storage=django.core.files.storage.FileSystemStorage( - location='/Users/hellsayenci/Documents/web_projects/JobHax/JobHaxBackend/JH_RestAPI/media/blog'), - upload_to=''), - ), - ] diff --git a/blog/migrations/0011_remove_blog_is_html.py b/blog/migrations/0011_remove_blog_is_html.py deleted file mode 100644 index 617062a..0000000 --- a/blog/migrations/0011_remove_blog_is_html.py +++ /dev/null @@ -1,16 +0,0 @@ -# Generated by Django 2.2 on 2019-08-07 05:28 - -from django.db import migrations - - -class Migration(migrations.Migration): - dependencies = [ - ('blog', '0010_auto_20190807_0515'), - ] - - operations = [ - migrations.RemoveField( - model_name='blog', - name='is_html', - ), - ] diff --git a/blog/migrations/0012_auto_20190807_0531.py b/blog/migrations/0012_auto_20190807_0531.py deleted file mode 100644 index c6da732..0000000 --- a/blog/migrations/0012_auto_20190807_0531.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 2.2 on 2019-08-07 05:31 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('blog', '0011_remove_blog_is_html'), - ] - - operations = [ - migrations.AlterField( - model_name='blog', - name='publisher_profile', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, - to='users.Profile'), - ), - ] diff --git a/blog/migrations/0013_auto_20190807_0601.py b/blog/migrations/0013_auto_20190807_0601.py deleted file mode 100644 index e5aa43d..0000000 --- a/blog/migrations/0013_auto_20190807_0601.py +++ /dev/null @@ -1,22 +0,0 @@ -# Generated by Django 2.2 on 2019-08-07 06:01 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('blog', '0012_auto_20190807_0531'), - ] - - operations = [ - migrations.AddField( - model_name='blog', - name='is_published', - field=models.BooleanField(default=False), - ), - migrations.AlterField( - model_name='blog', - name='header_image', - field=models.FileField(blank=True, null=True, upload_to=''), - ), - ] diff --git a/blog/migrations/0014_auto_20190821_0619.py b/blog/migrations/0014_auto_20190821_0619.py deleted file mode 100644 index 2e315c0..0000000 --- a/blog/migrations/0014_auto_20190821_0619.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2 on 2019-08-21 06:19 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('blog', '0013_auto_20190807_0601'), - ] - - operations = [ - migrations.AlterField( - model_name='blog', - name='snippet', - field=models.CharField(max_length=400, null=True), - ), - ] diff --git a/blog/migrations/0015_auto_20190821_1710.py b/blog/migrations/0015_auto_20190821_1710.py deleted file mode 100644 index 00970b8..0000000 --- a/blog/migrations/0015_auto_20190821_1710.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 2.2 on 2019-08-21 17:10 - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('blog', '0014_auto_20190821_0619'), - ] - - operations = [ - migrations.AlterField( - model_name='blog', - name='publisher_profile', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL), - ), - ] diff --git a/blog/migrations/0016_blog_is_approved.py b/blog/migrations/0016_blog_is_approved.py deleted file mode 100644 index 46ab5e0..0000000 --- a/blog/migrations/0016_blog_is_approved.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2 on 2019-08-23 21:04 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('blog', '0015_auto_20190821_1710'), - ] - - operations = [ - migrations.AddField( - model_name='blog', - name='is_approved', - field=models.BooleanField(default=False), - ), - ] diff --git a/blog/migrations/0017_blog_is_public.py b/blog/migrations/0017_blog_is_public.py deleted file mode 100644 index 63e8648..0000000 --- a/blog/migrations/0017_blog_is_public.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2 on 2019-08-24 22:02 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('blog', '0016_blog_is_approved'), - ] - - operations = [ - migrations.AddField( - model_name='blog', - name='is_public', - field=models.BooleanField(default=False), - ), - ] diff --git a/blog/migrations/0018_auto_20190826_2243.py b/blog/migrations/0018_auto_20190826_2243.py deleted file mode 100644 index e378820..0000000 --- a/blog/migrations/0018_auto_20190826_2243.py +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by Django 2.2 on 2019-08-27 05:43 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('blog', '0017_blog_is_public'), - ] - - operations = [ - migrations.AlterField( - model_name='blog', - name='content', - field=models.TextField(blank=True, null=True), - ), - migrations.AlterField( - model_name='blog', - name='snippet', - field=models.CharField(blank=True, max_length=400, null=True), - ), - migrations.AlterField( - model_name='blog', - name='title', - field=models.CharField(blank=True, max_length=50, null=True), - ), - ] diff --git a/blog/migrations/0019_auto_20190826_2322.py b/blog/migrations/0019_auto_20190826_2322.py deleted file mode 100644 index 43e7d74..0000000 --- a/blog/migrations/0019_auto_20190826_2322.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2 on 2019-08-27 06:22 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('blog', '0018_auto_20190826_2243'), - ] - - operations = [ - migrations.RenameField( - model_name='blog', - old_name='is_published', - new_name='is_publish', - ), - ] diff --git a/blog/migrations/0020_remove_blog_is_public.py b/blog/migrations/0020_remove_blog_is_public.py deleted file mode 100644 index 27d3461..0000000 --- a/blog/migrations/0020_remove_blog_is_public.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 2.2 on 2019-09-28 22:16 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('blog', '0019_auto_20190826_2322'), - ] - - operations = [ - migrations.RemoveField( - model_name='blog', - name='is_public', - ), - ] diff --git a/blog/migrations/0021_blog_user_types.py b/blog/migrations/0021_blog_user_types.py deleted file mode 100644 index 56756aa..0000000 --- a/blog/migrations/0021_blog_user_types.py +++ /dev/null @@ -1,35 +0,0 @@ -# Generated by Django 2.2 on 2019-09-30 04:13 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0048_auto_20190929_2057'), - ('blog', '0020_remove_blog_is_public'), - ] - - def migrate_user_types(apps, schema_editor): - UserType = apps.get_model('users', 'UserType') - Blog = apps.get_model('blog', 'Blog') - blogs = Blog.objects.all() - for e in blogs: - if e.publisher_profile.user_type is None or e.publisher_profile.user_type.name == 'Undefined' \ - or e.publisher_profile.user_type.name == 'Public': - e.user_types.add(UserType.objects.get(name__iexact='Public')) - elif e.publisher_profile.user_type.name == 'Student': - e.user_types.add(UserType.objects.get(name__iexact='Student')) - elif e.publisher_profile.user_type.name == 'Alumni': - e.user_types.add(UserType.objects.get(name__iexact='Alumni')) - else: - e.user_types.add(UserType.objects.get(name__iexact='Public')) - - operations = [ - migrations.AddField( - model_name='blog', - name='user_types', - field=models.ManyToManyField(to='users.UserType'), - ), - migrations.RunPython(migrate_user_types, reverse_code=migrations.RunPython.noop) - ] diff --git a/blog/models.py b/blog/models.py deleted file mode 100644 index 55d373c..0000000 --- a/blog/models.py +++ /dev/null @@ -1,28 +0,0 @@ -from django.contrib.auth import get_user_model -from django.db import models -from users.models import UserType - - -class Blog(models.Model): - publisher_profile = models.ForeignKey( - get_user_model(), on_delete=models.SET_NULL, null=True, blank=True) - title = models.CharField(max_length=50, null=True, blank=True) - user_types = models.ManyToManyField(UserType) - snippet = models.CharField(null=True, blank=True, max_length=400) - header_image = models.FileField(blank=True, null=True) - view_count = models.IntegerField(default=0) - content = models.TextField(null=True, blank=True) - created_at = models.DateTimeField(auto_now_add=True) - updated_at = models.DateTimeField(auto_now=True) - is_publish = models.BooleanField(default=False) - is_approved = models.BooleanField(default=False) - - class Meta: - ordering = ['-created_at'] - - -class Vote(models.Model): - User = get_user_model() - user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='vote_user') - blog = models.ForeignKey(Blog, on_delete=models.CASCADE) - vote_type = models.BooleanField(default=False) diff --git a/blog/serializers.py b/blog/serializers.py deleted file mode 100644 index f45ab79..0000000 --- a/blog/serializers.py +++ /dev/null @@ -1,98 +0,0 @@ -import pytz -from rest_framework import serializers -from bs4 import BeautifulSoup as bs - -from users.serializers import UserSerializer -from . import models - - -class BlogSerializer(serializers.ModelSerializer): - publisher_profile = UserSerializer(read_only=True) - upvote = serializers.SerializerMethodField() - downvote = serializers.SerializerMethodField() - voted = serializers.SerializerMethodField() - word_count = serializers.SerializerMethodField() - mine = serializers.SerializerMethodField() - - def get_mine(self, obj): - return obj.publisher_profile == self.context.get('user') - - def get_word_count(self, obj): - if obj.content: - line_soup = bs(obj.content.strip(), 'html.parser') - # naive way to get words count - words_count = len(line_soup.text.split()) - return words_count - return 0 - - def get_created_at(self, obj): - if obj.date is None: - return None - return obj.date.astimezone(pytz.timezone('US/Pacific')) - - def get_upvote(self, obj): - return models.Vote.objects.filter(blog=obj, vote_type=True).count() - - def get_downvote(self, obj): - return models.Vote.objects.filter(blog=obj, vote_type=False).count() - - def get_voted(self, obj): - voted = 0 - user_vote = models.Vote.objects.filter( - user=self.context.get('user'), blog=obj) - if len(user_vote) > 0: - if user_vote[0].vote_type: - voted = 1 - else: - voted = -1 - return voted - - class Meta: - fields = ('id', 'publisher_profile', 'mine', 'title', 'content', 'header_image', 'snippet', - 'created_at', 'updated_at', 'view_count', 'upvote', 'downvote', 'word_count', 'voted', 'is_publish', - 'is_approved') - model = models.Blog - - -class BlogSnippetSerializer(serializers.ModelSerializer): - publisher_profile = UserSerializer(read_only=True) - upvote = serializers.SerializerMethodField() - downvote = serializers.SerializerMethodField() - voted = serializers.SerializerMethodField() - word_count = serializers.SerializerMethodField() - - def get_word_count(self, obj): - if obj.content: - line_soup = bs(obj.content.strip(), 'html.parser') - # naive way to get words count - words_count = len(line_soup.text.split()) - return words_count - return 0 - - def get_created_at(self, obj): - if obj.date is None: - return None - return obj.date.astimezone(pytz.timezone('US/Pacific')) - - def get_upvote(self, obj): - return models.Vote.objects.filter(blog=obj, vote_type=True).count() - - def get_downvote(self, obj): - return models.Vote.objects.filter(blog=obj, vote_type=False).count() - - def get_voted(self, obj): - voted = 0 - user_vote = models.Vote.objects.filter( - user=self.context.get('user'), blog=obj) - if len(user_vote) > 0: - if user_vote[0].vote_type: - voted = 1 - else: - voted = -1 - return voted - - class Meta: - fields = ('id', 'publisher_profile', 'title', 'snippet', - 'header_image', 'created_at', 'updated_at', 'view_count', 'upvote', 'downvote', 'word_count', 'voted', - 'is_publish', 'is_approved') - model = models.Blog diff --git a/blog/tests.py b/blog/tests.py deleted file mode 100644 index a39b155..0000000 --- a/blog/tests.py +++ /dev/null @@ -1 +0,0 @@ -# Create your tests here. diff --git a/blog/urls.py b/blog/urls.py deleted file mode 100644 index 394be13..0000000 --- a/blog/urls.py +++ /dev/null @@ -1,13 +0,0 @@ -from django.urls import path - -from blog import views - -urlpatterns = [ - path('', views.blogs), - path('/', - views.blog), - path('/vote/', - views.vote), - path('/view/', - views.view), -] diff --git a/blog/views.py b/blog/views.py deleted file mode 100644 index 69a2cde..0000000 --- a/blog/views.py +++ /dev/null @@ -1,147 +0,0 @@ -import uuid -from datetime import datetime -from enum import Enum - -from django.contrib.auth import get_user_model -from django.db.models import Q -from django.http import JsonResponse -from django.views.decorators.csrf import csrf_exempt -from rest_framework.decorators import api_view - -from JH_RestAPI import pagination -from blog.models import Blog -from blog.models import Vote -from utils import utils -from utils.error_codes import ResponseCodes -from utils.generic_json_creator import create_response -from utils.utils import get_boolean_from_request, send_notification_email_to_admins -from .serializers import BlogSerializer -from .serializers import BlogSnippetSerializer - -User = get_user_model() - - -class ActionType(Enum): - none = 0 - upvote = 1 - downvote = -1 - view = 2 - - -@csrf_exempt -@api_view(["GET", "PUT", "POST", "DELETE"]) -def blogs(request): - user_profile = request.user - if request.method == "GET": - mine = get_boolean_from_request(request, 'mine') - if not mine: - queryset = Blog.objects.filter(Q(is_approved=True) | Q(publisher_profile=request.user), - Q(user_types__in=[user_profile.user_type]) | Q(publisher_profile__is_staff=True)) - else: - queryset = Blog.objects.filter(publisher_profile=request.user) - queryset = queryset.filter(publisher_profile__isnull=False) - paginator = pagination.CustomPagination() - blogs = paginator.paginate_queryset(queryset, request) - serialized_blogs = BlogSnippetSerializer( - instance=blogs, many=True, context={'user': request.user}).data - return JsonResponse(create_response(data=serialized_blogs, paginator=paginator), safe=False) - else: - if not user_profile.user_type.blog_creation_enabled: - return JsonResponse(create_response(data=None, success=False, error_code=ResponseCodes.not_supported_user), - safe=False) - if request.method == "POST": - body = request.data - blog = Blog() - if 'header_image' in body: - file = body['header_image'] - ext = file.name.split('.')[-1] - filename = "%s.%s" % (uuid.uuid4(), ext) - blog.header_image.save(filename, file, save=True) - if 'title' in body: - title = body['title'] - blog.title = title - if 'content' in body: - content = body['content'] - blog.content = content - if 'snippet' in body: - snippet = body['snippet'][:130] + '...' - blog.snippet = snippet - if 'is_publish' in body: - is_publish = get_boolean_from_request(request, 'is_publish') - blog.is_publish = is_publish - send_notification_email_to_admins('blog') - blog.publisher_profile = request.user - blog.user_types.add(request.user.user_type) - - blog.save() - return JsonResponse(create_response(data={"id": blog.id}), safe=False) - elif request.method == "PUT": - body = request.data - blog = Blog.objects.get(pk=body['blog_id'], publisher_profile=request.user) - if 'title' in body: - blog.title = body['title'] - if 'content' in body: - blog.content = body['content'] - blog.snippet = body['snippet'][:130] + '...' - if 'header_image' in body: - file = body['header_image'] - ext = file.name.split('.')[-1] - filename = "%s.%s" % (uuid.uuid4(), ext) - blog.header_image.save(filename, file, save=True) - if 'is_publish' in body: - blog.is_publish = get_boolean_from_request(request, 'is_publish') - blog.is_approved = False - blog.updated_at = datetime.now() - blog.save() - send_notification_email_to_admins('blog') - return JsonResponse(create_response(data={"id": blog.id}), safe=False) - elif request.method == "DELETE": - body = request.data - blog = Blog.objects.get(pk=body['blog_id'], publisher_profile=request.user) - blog.delete() - return JsonResponse(create_response(data=None), safe=False) - - -@csrf_exempt -@api_view(["GET"]) -def blog(request, blog_pk): - blog = Blog.objects.get(pk=blog_pk) - return JsonResponse(create_response(BlogSerializer(instance=blog, many=False, context={'user': request.user}).data), - safe=False) - - -def do_action(request, blog_pk, type): - body = request.data - if 'recaptcha_token' in body and utils.verify_recaptcha(None, body['recaptcha_token'], - 'blog_stats') == ResponseCodes.verify_recaptcha_failed: - return JsonResponse(create_response(data=None, success=False, error_code=ResponseCodes.verify_recaptcha_failed), - safe=False) - - blog = Blog.objects.get(pk=blog_pk) - if type == ActionType.view: - blog.view_count = blog.view_count + 1 - blog.save() - else: - if type == ActionType.none: - Vote.objects.filter(user=request.user, blog=blog).delete() - else: - vote, new = Vote.objects.get_or_create(user=request.user, blog=blog) - if type == ActionType.upvote: - vote.vote_type = True - elif type == ActionType.downvote: - vote.vote_type = False - vote.save() - return JsonResponse(create_response(data=None)) - - -@csrf_exempt -@api_view(["POST"]) -def vote(request, blog_pk): - action = request.data['action'] - return do_action(request, blog_pk, ActionType(action)) - - -@csrf_exempt -@api_view(["POST"]) -def view(request, blog_pk): - return do_action(request, blog_pk, ActionType.view) diff --git a/college/migrations/0001_initial.py b/college/migrations/0001_initial.py index 1ebd8d7..b3b522d 100644 --- a/college/migrations/0001_initial.py +++ b/college/migrations/0001_initial.py @@ -1,10 +1,11 @@ -# Generated by Django 2.2 on 2019-08-07 08:37 +# Generated by Django 2.2 on 2019-10-03 23:52 import django.contrib.postgres.fields from django.db import migrations, models class Migration(migrations.Migration): + initial = True dependencies = [ @@ -15,13 +16,9 @@ class Migration(migrations.Migration): name='College', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('web_pages', - django.contrib.postgres.fields.ArrayField(base_field=models.TextField(blank=True, null=True), - size=None)), - ('domains', - django.contrib.postgres.fields.ArrayField(base_field=models.TextField(blank=True, null=True), - size=None)), - ('name', models.CharField(blank=True, max_length=200)), + ('web_pages', django.contrib.postgres.fields.ArrayField(base_field=models.TextField(blank=True, null=True), size=None)), + ('domains', django.contrib.postgres.fields.ArrayField(base_field=models.TextField(blank=True, null=True), size=None)), + ('name', models.CharField(max_length=200)), ('alpha_two_code', models.CharField(blank=True, max_length=5)), ('state_province', models.CharField(blank=True, max_length=30, null=True)), ('country', models.CharField(blank=True, max_length=50)), diff --git a/college/migrations/0003_college_supported.py b/college/migrations/0003_college_supported.py deleted file mode 100644 index 24b8eac..0000000 --- a/college/migrations/0003_college_supported.py +++ /dev/null @@ -1,12 +0,0 @@ -# Generated by Django 2.2 on 2019-08-03 21:41 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('college', '0002_import_college_data_from_json'), - ] - - operations = [ - ] diff --git a/college/migrations/0004_auto_20190804_0034.py b/college/migrations/0004_auto_20190804_0034.py deleted file mode 100644 index 9605d6d..0000000 --- a/college/migrations/0004_auto_20190804_0034.py +++ /dev/null @@ -1,27 +0,0 @@ -# Generated by Django 2.2 on 2019-08-04 00:34 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('college', '0003_college_supported'), - ] - - operations = [ - migrations.CreateModel( - name='Major', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(blank=True, max_length=200)), - ('supported', models.BooleanField(default=False)), - ], - options={ - 'ordering': ['name'], - }, - ), - migrations.AlterModelOptions( - name='college', - options={'ordering': ['name']}, - ), - ] diff --git a/college/migrations/0005_delete_major.py b/college/migrations/0005_delete_major.py deleted file mode 100644 index 8f9b429..0000000 --- a/college/migrations/0005_delete_major.py +++ /dev/null @@ -1,16 +0,0 @@ -# Generated by Django 2.2 on 2019-08-07 08:47 - -from django.db import migrations - - -class Migration(migrations.Migration): - dependencies = [ - ('users', '0033_auto_20190807_0847'), - ('college', '0004_auto_20190804_0034'), - ] - - operations = [ - migrations.DeleteModel( - name='Major', - ), - ] diff --git a/college/migrations/0006_auto_20190924_1146.py b/college/migrations/0006_auto_20190924_1146.py deleted file mode 100644 index 9297723..0000000 --- a/college/migrations/0006_auto_20190924_1146.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2 on 2019-09-24 18:46 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('college', '0005_delete_major'), - ] - - operations = [ - migrations.AlterField( - model_name='college', - name='name', - field=models.CharField(max_length=200), - ), - ] diff --git a/company/admin.py b/company/admin.py index aae76d5..485254c 100644 --- a/company/admin.py +++ b/company/admin.py @@ -7,8 +7,6 @@ # Register your models here. @admin.register(Company) class CompanyAdmin(admin.ModelAdmin, ExportCsv): - list_display = ('company', 'company_logo', 'cb_name', - 'cb_company_logo', 'cb_domain') - list_filter = ('company', 'company_logo', 'cb_name', - 'cb_company_logo', 'cb_domain') + list_display = ('company', 'logo', 'domain', 'location_address') + list_filter = ('company', 'logo', 'domain', 'location_address') actions = ["export_as_csv"] diff --git a/company/migrations/0001_initial.py b/company/migrations/0001_initial.py index 005953b..11daf4e 100644 --- a/company/migrations/0001_initial.py +++ b/company/migrations/0001_initial.py @@ -1,9 +1,10 @@ -# Generated by Django 2.1.5 on 2019-04-22 23:09 +# Generated by Django 2.2 on 2019-10-03 23:52 from django.db import migrations, models class Migration(migrations.Migration): + initial = True dependencies = [ @@ -14,11 +15,14 @@ class Migration(migrations.Migration): name='Company', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('company', models.CharField(max_length=200, null=True)), + ('company', models.CharField(max_length=200)), ('company_logo', models.CharField(blank=True, max_length=200, null=True)), ('cb_name', models.CharField(max_length=200, null=True)), ('cb_company_logo', models.CharField(blank=True, max_length=200, null=True)), ('cb_domain', models.CharField(max_length=50, null=True)), ], + options={ + 'ordering': ['company'], + }, ), ] diff --git a/company/migrations/0002_auto_20190429_2110.py b/company/migrations/0002_auto_20190429_2110.py deleted file mode 100644 index 11b1d57..0000000 --- a/company/migrations/0002_auto_20190429_2110.py +++ /dev/null @@ -1,16 +0,0 @@ -# Generated by Django 2.2 on 2019-04-29 21:10 - -from django.db import migrations - - -class Migration(migrations.Migration): - dependencies = [ - ('company', '0001_initial'), - ] - - operations = [ - migrations.AlterModelOptions( - name='company', - options={'ordering': ['company']}, - ), - ] diff --git a/company/migrations/0002_auto_20191014_2316.py b/company/migrations/0002_auto_20191014_2316.py new file mode 100644 index 0000000..f917f3e --- /dev/null +++ b/company/migrations/0002_auto_20191014_2316.py @@ -0,0 +1,59 @@ +# Generated by Django 2.2 on 2019-10-15 06:16 + +from django.db import migrations, models +import requests, json +import os + + +class Migration(migrations.Migration): + + dependencies = [ + ('company', '0001_initial'), + ] + + def fetch_locations(apps, schema_editor): + Company = apps.get_model('company', 'Company') + companies = Company.objects.all() + url = "https://maps.googleapis.com/maps/api/place/textsearch/json?" + api_key = os.environ.get('JOBHAX_BACKEND_MAPS_API_KEY', '') + if api_key is not '': + for company in companies: + query = company.company + if query is None: + query = company.cb_name + if query is not None: + r = requests.get(url + 'query=' + query + + '&key=' + api_key) + x = r.json() + y = x['results'] + for i in range(len(y)): + place = y[i] + if 'establishment' in place['types']: + lat = place['geometry']['location']['lat'] + lng = place['geometry']['location']['lng'] + formatted_address = place['formatted_address'] + company.location_lat = lat + company.location_lon = lng + company.location_address = formatted_address + company.save() + break + + + operations = [ + migrations.AddField( + model_name='company', + name='location_address', + field=models.CharField(blank=True, max_length=250, null=True), + ), + migrations.AddField( + model_name='company', + name='location_lat', + field=models.FloatField(blank=True, null=True), + ), + migrations.AddField( + model_name='company', + name='location_lon', + field=models.FloatField(blank=True, null=True), + ), + migrations.RunPython(fetch_locations, reverse_code=migrations.RunPython.noop), + ] diff --git a/company/migrations/0003_auto_20190924_1146.py b/company/migrations/0003_auto_20190924_1146.py deleted file mode 100644 index 10c9cbc..0000000 --- a/company/migrations/0003_auto_20190924_1146.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 2.2 on 2019-09-24 18:46 - -from django.db import migrations, models -import django.utils.timezone - - -class Migration(migrations.Migration): - - dependencies = [ - ('company', '0002_auto_20190429_2110'), - ] - - operations = [ - migrations.AlterField( - model_name='company', - name='company', - field=models.CharField(default=django.utils.timezone.now, max_length=200), - preserve_default=False, - ), - ] diff --git a/company/migrations/0003_auto_20191015_1230.py b/company/migrations/0003_auto_20191015_1230.py new file mode 100644 index 0000000..76c1846 --- /dev/null +++ b/company/migrations/0003_auto_20191015_1230.py @@ -0,0 +1,58 @@ +# Generated by Django 2.2 on 2019-10-15 19:30 + +from django.db import migrations, models +import uuid +from django.core.files import File +from urllib.request import urlretrieve +from urllib.error import HTTPError +import os + + +class Migration(migrations.Migration): + + dependencies = [ + ('company', '0002_auto_20191014_2316'), + ] + + def migrate_data(apps, schema_editor): + Company = apps.get_model('company', 'Company') + companies = Company.objects.all() + for company in companies: + if company.cb_company_logo is not None and company.cb_company_logo is not '': + try: + urlretrieve(company.cb_company_logo, filename=company.cb_company_logo.split('/')[-1]) + file = open(company.cb_company_logo.split('/')[-1], 'rb') + filename = "%s.%s" % (uuid.uuid4(), 'jpg') + company.logo.save(filename, File(file), save=True) + company.save() + os.remove(company.cb_company_logo.split('/')[-1]) + except FileNotFoundError as err: + pass # something wrong with local path + except HTTPError as err: + pass # something wrong with url + elif company.company_logo is not None and company.company_logo is not '': + try: + urlretrieve(company.company_logo, filename=company.company_logo.split('/')[-1]) + file = open(company.company_logo.split('/')[-1], 'rb') + filename = "%s.%s" % (uuid.uuid4(), 'jpg') + company.logo.save(filename, File(file), save=True) + company.save() + os.remove(company.company_logo.split('/')[-1]) + except FileNotFoundError as err: + pass # something wrong with local path + except HTTPError as err: + pass # something wrong with url + + operations = [ + migrations.RenameField( + model_name='company', + old_name='cb_domain', + new_name='domain', + ), + migrations.AddField( + model_name='company', + name='logo', + field=models.FileField(default='8af3c0b7-6f12-4d54-8d64-5c49f40f28fb.png', upload_to=''), + ), + migrations.RunPython(migrate_data, reverse_code=migrations.RunPython.noop), + ] diff --git a/company/migrations/0004_auto_20191015_1248.py b/company/migrations/0004_auto_20191015_1248.py new file mode 100644 index 0000000..e4e1b31 --- /dev/null +++ b/company/migrations/0004_auto_20191015_1248.py @@ -0,0 +1,30 @@ +# Generated by Django 2.2 on 2019-10-15 19:48 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('company', '0003_auto_20191015_1230'), + ] + + operations = [ + migrations.RemoveField( + model_name='company', + name='cb_company_logo', + ), + migrations.RemoveField( + model_name='company', + name='cb_name', + ), + migrations.RemoveField( + model_name='company', + name='company_logo', + ), + migrations.AlterField( + model_name='company', + name='logo', + field=models.FileField(default='8af3c0b7-6f12-4d54-8d64-5c49f40f28fb.png', upload_to=''), + ), + ] diff --git a/company/migrations/0005_auto_20191021_2237.py b/company/migrations/0005_auto_20191021_2237.py new file mode 100644 index 0000000..41c8d44 --- /dev/null +++ b/company/migrations/0005_auto_20191021_2237.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2 on 2019-10-22 05:37 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('company', '0004_auto_20191015_1248'), + ] + + operations = [ + migrations.AlterField( + model_name='company', + name='logo', + field=models.FileField(default='8af3c0b7-6f12-4d54-8d64-5c49f40f28fb.png', upload_to=''), + ), + ] diff --git a/company/migrations/0006_auto_20191021_2243.py b/company/migrations/0006_auto_20191021_2243.py new file mode 100644 index 0000000..d34b8a9 --- /dev/null +++ b/company/migrations/0006_auto_20191021_2243.py @@ -0,0 +1,23 @@ +# Generated by Django 2.2 on 2019-10-22 05:43 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('company', '0005_auto_20191021_2237'), + ] + + def fix_data(apps, schema_editor): + Company = apps.get_model('company', 'Company') + companies = Company.objects.all() + for company in companies: + if company.logo.name.startswith('settings'): + company.logo.name = '8af3c0b7-6f12-4d54-8d64-5c49f40f28fb.png' + company.save() + + + operations = [ + migrations.RunPython(fix_data, reverse_code=migrations.RunPython.noop), + ] diff --git a/company/migrations/0007_auto_20191202_1351.py b/company/migrations/0007_auto_20191202_1351.py new file mode 100644 index 0000000..49cc2a5 --- /dev/null +++ b/company/migrations/0007_auto_20191202_1351.py @@ -0,0 +1,29 @@ +# Generated by Django 2.2.5 on 2019-12-02 21:51 + +import django.core.validators +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('company', '0006_auto_20191021_2243'), + ] + + operations = [ + migrations.AddField( + model_name='company', + name='description', + field=models.TextField(blank=True, null=True), + ), + migrations.AddField( + model_name='company', + name='employees_number', + field=models.IntegerField(blank=True, null=True), + ), + migrations.AddField( + model_name='company', + name='phone_number', + field=models.CharField(blank=True, max_length=17, validators=[django.core.validators.RegexValidator(message="Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed.", regex='^\\+?1?\\d{9,15}$')]), + ), + ] diff --git a/company/models.py b/company/models.py index 45a0af4..4907a93 100644 --- a/company/models.py +++ b/company/models.py @@ -1,12 +1,22 @@ from django.db import models +from django.core.validators import RegexValidator class Company(models.Model): company = models.CharField(max_length=200, blank=False) - company_logo = models.CharField(max_length=200, null=True, blank=True) - cb_name = models.CharField(max_length=200, null=True) - cb_company_logo = models.CharField(max_length=200, null=True, blank=True) - cb_domain = models.CharField(max_length=50, null=True) + logo = models.FileField(blank=False, null=False, + default='8af3c0b7-6f12-4d54-8d64-5c49f40f28fb.png') + domain = models.CharField(max_length=50, null=True) + location_lat = models.FloatField(blank=True, null=True) + location_lon = models.FloatField(blank=True, null=True) + location_address = models.CharField(max_length=250, blank=True, null=True) + description = models.TextField(blank=True, null=True) + phone_regex = RegexValidator( + regex=r'^\+?1?\d{9,15}$', + message="Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed.") + phone_number = models.CharField( + validators=[phone_regex], max_length=17, blank=True) # validators should be a list + employees_number = models.IntegerField(null=True, blank=True) class Meta: ordering = ['company'] diff --git a/company/serializers.py b/company/serializers.py index 610808b..470df62 100644 --- a/company/serializers.py +++ b/company/serializers.py @@ -1,7 +1,6 @@ from django.db.models import Count from rest_framework import serializers -from review.models import Review, CompanyEmploymentAuth from .models import Company @@ -12,58 +11,11 @@ def create(self, validated_data): class Meta: model = Company - fields = '__all__' + fields = ('id', 'company', 'domain', 'logo', 'location_lat', + 'location_lon', 'location_address', 'description', 'employees_number', 'phone_number') class CompanySerializer(serializers.ModelSerializer): - ratings = serializers.SerializerMethodField() - supported_employment_auths = serializers.SerializerMethodField() - review_id = serializers.SerializerMethodField() - review_count = serializers.SerializerMethodField() - - def get_review_count(self, obj): - if 'position' in self.context: - position = self.context.get('position') - review = Review.objects.filter( - is_published=True, company__pk=obj.pk, position=position) - return review.count() - else: - return Review.objects.filter(is_published=True, company__pk=obj.pk).count() - - def get_review_id(self, obj): - if 'position' in self.context: - position = self.context.get('position') - review = Review.objects.filter(user=self.context.get( - 'user'), company__pk=obj.pk, position=position) - if review.count() == 0: - return None - return review[0].pk - else: - return None - - def get_ratings(self, obj): - ratings = [] - for i in range(1, 6): - rating = {'id': i, 'count': Review.objects.filter(company=obj, overall_company_experience=i, - is_published=True).aggregate( - Count('overall_company_experience'))['overall_company_experience__count']} - ratings.append(rating) - return ratings - - def get_supported_employment_auths(self, obj): - from review.models import EmploymentAuth - from review.serializers import EmploymentAuthSerializer - auths = [] - for auth in EmploymentAuth.objects.all(): - a_ser = EmploymentAuthSerializer(instance=auth, many=False).data - emp_auths = CompanyEmploymentAuth.objects.filter( - review__company=obj, employment_auth=auth) - a_ser['yes'] = emp_auths.filter(value=True).aggregate( - Count('value'))['value__count'] - a_ser['no'] = emp_auths.filter(value=False).aggregate( - Count('value'))['value__count'] - auths.append(a_ser) - return auths def create(self, validated_data): return Company.objects.create(**validated_data) diff --git a/company/urls.py b/company/urls.py index 4d5c083..05153fb 100644 --- a/company/urls.py +++ b/company/urls.py @@ -5,7 +5,6 @@ urlpatterns = [ path('', views.companies), - path('/positions/', - views.positions), + path('', views.company) ] urlpatterns = format_suffix_patterns(urlpatterns) diff --git a/company/utils.py b/company/utils.py index a1ed422..1a7dfa1 100644 --- a/company/utils.py +++ b/company/utils.py @@ -1,5 +1,11 @@ from company.models import Company from utils.clearbit_company_checker import get_company_detail +import os +import uuid +from django.core.files import File +from urllib.request import urlretrieve +from urllib.error import HTTPError +from background_task import background def get_or_create_company(name): @@ -8,16 +14,54 @@ def get_or_create_company(name): company_title = name else: company_title = cd['name'] - jc = Company.objects.all().filter(cb_name__iexact=company_title) + jc = Company.objects.all().filter(company__iexact=company_title) if jc.count() == 0: # if company doesnt exist save it if cd is None: - jc = Company(company=name, company_logo=None, - cb_name=name, cb_company_logo=None, cb_domain=None) + jc = Company(company=name, domain=None) else: - jc = Company(company=name, company_logo=None, - cb_name=cd['name'], cb_company_logo=cd['logo'], cb_domain=cd['domain']) + jc = Company(company=cd['name'], domain=cd['domain']) + jc.save() + if 'logo' in cd and cd['logo'] is not None and cd['logo'] is not '': + try: + urlretrieve(cd['logo'], filename=cd['logo'].split('/')[-1]) + file = open(cd['logo'].split('/')[-1], 'rb') + filename = "%s.%s" % (uuid.uuid4(), 'jpg') + jc.logo.save(filename, File(file), save=True) + jc.save() + os.remove(cd['logo'].split('/')[-1]) + except FileNotFoundError as err: + pass # something wrong with local path + except HTTPError as err: + pass # something wrong with url jc.save() else: jc = jc[0] - return jc \ No newline at end of file + if jc.location_address is None: + fetch_company_location(name) + return jc + + +@background(schedule=3) +def fetch_company_location(query): + url = "https://maps.googleapis.com/maps/api/place/textsearch/json?" + api_key = os.environ.get('JOBHAX_BACKEND_MAPS_API_KEY', '') + if api_key is not '': + log('Looking location of ' + query, 'e') + if query is not None: + r = requests.get(url + 'query=' + query + + '&key=' + api_key) + x = r.json() + y = x['results'] + for i in range(len(y)): + place = y[i] + if 'establishment' in place['types']: + lat = place['geometry']['location']['lat'] + lng = place['geometry']['location']['lng'] + formatted_address = place['formatted_address'] + company = Company.objects.get(company=query) + company.location_lat = lat + company.location_lon = lng + company.location_address = formatted_address + company.save() + break diff --git a/company/views.py b/company/views.py index ebb04fd..a3b2c8d 100644 --- a/company/views.py +++ b/company/views.py @@ -3,28 +3,19 @@ from rest_framework.decorators import api_view from JH_RestAPI import pagination -from jobapps.models import JobApplication from position.serializers import JobPositionSerializer from utils.generic_json_creator import create_response from utils.utils import get_boolean_from_request from .models import Company -from review.models import Review -from .serializers import CompanySerializer +from .serializers import CompanyBasicsSerializer, CompanySerializer +from utils.error_codes import ResponseCodes @csrf_exempt @api_view(["GET"]) def companies(request): q = request.GET.get('q') - has_review = get_boolean_from_request(request, 'hasReview') - mine = get_boolean_from_request(request, 'mine') companies = Company.objects.all() - if has_review: - companies_has_review = Review.objects.filter(is_published=True).order_by('company__id').distinct('company__id') - companies = Company.objects.all().filter(id__in=[r.company.id for r in companies_has_review]) - if mine: - users_companies = JobApplication.objects.filter(user=request.user, is_deleted=False) - companies = companies.filter(id__in=[j.company_object.id for j in users_companies]) if q is not None: companies = companies.filter(company__icontains=q) paginator = pagination.CustomPagination() @@ -35,16 +26,37 @@ def companies(request): @csrf_exempt -@api_view(["GET"]) -def positions(request, company_pk): - has_review = get_boolean_from_request(request, 'hasReview') - company = Company.objects.get(pk=company_pk) - queryset = JobApplication.objects.filter(company_object=company) - if has_review: - positions_has_review = Review.objects.filter(company=company, is_published=True).order_by('position__id').distinct('position__id') - queryset = queryset.filter(position__id__in=[r.position.id for r in positions_has_review]) - positions = set() - for q in queryset: - if q is not None: - positions.add(q.position) - return JsonResponse(create_response(data=JobPositionSerializer(instance=positions, many=True).data), safe=False) +@api_view(["GET", "PATCH"]) +def company(request, company_pk): + body = request.data + if company_pk is None: + return JsonResponse(create_response(data=None, success=False, error_code=ResponseCodes.invalid_parameters), safe=False) + if request.method == "GET": + company = Company.objects.get(pk=company_pk) + serialized_company = CompanyBasicsSerializer( + instance=company, many=False, context={"user": request.user}).data + return JsonResponse(create_response(data=serialized_company), safe=False) + elif request.method == "PATCH": + company = Company.objects.get(pk=company_pk) + company_name = body.get("company") + domain = body.get("domain") + location_address = body.get("location_address") + description = body.get("description") + employees_number = body.get("employees_number") + phone_number = body.get("phone_number") + + if company_name is not None: + company.company = company_name + if domain is not None: + company.domain = domain + if location_address is not None: + company.location_address = location_address + if description is not None: + company.description = description + if employees_number is not None: + company.employees_number = employees_number + if phone_number is not None: + company.phone_number = phone_number + + company.save() + return JsonResponse(create_response(data=CompanyBasicsSerializer(instance=company, many=False, context={"user": request.user}).data), safe=False) diff --git a/alumni/__init__.py b/cvparser/__init__.py similarity index 100% rename from alumni/__init__.py rename to cvparser/__init__.py diff --git a/cvparser/admin.py b/cvparser/admin.py new file mode 100644 index 0000000..1e9a387 --- /dev/null +++ b/cvparser/admin.py @@ -0,0 +1,6 @@ +from django.contrib import admin + +# Register your models here. +from .models import Resume + +admin.site.register(Resume) \ No newline at end of file diff --git a/cvparser/apps.py b/cvparser/apps.py new file mode 100644 index 0000000..9d2fe20 --- /dev/null +++ b/cvparser/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class CvparserConfig(AppConfig): + name = 'cvparser' diff --git a/cvparser/migrations/0001_initial.py b/cvparser/migrations/0001_initial.py new file mode 100644 index 0000000..f008ac6 --- /dev/null +++ b/cvparser/migrations/0001_initial.py @@ -0,0 +1,36 @@ +# Generated by Django 2.2.5 on 2019-12-02 12:20 + +import django.contrib.postgres.fields +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Resume', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('contact', django.contrib.postgres.fields.ArrayField(base_field=models.TextField(blank=True, null=True), size=None)), + ('skills', django.contrib.postgres.fields.ArrayField(base_field=models.TextField(blank=True, null=True), size=None)), + ('linkedin', models.CharField(max_length=200)), + ('certifications', django.contrib.postgres.fields.ArrayField(base_field=models.TextField(blank=True, null=True), size=None)), + ('summary', django.contrib.postgres.fields.ArrayField(base_field=models.TextField(blank=True, null=True), size=None)), + ('languages', django.contrib.postgres.fields.ArrayField(base_field=models.TextField(blank=True, null=True), size=None)), + ('school', models.CharField(max_length=200)), + ('degree', models.CharField(max_length=200)), + ('company', models.CharField(max_length=200)), + ('position', models.CharField(max_length=200)), + ('startdate', models.CharField(max_length=200)), + ('enddate', models.CharField(max_length=200)), + ], + options={ + 'ordering': ['linkedin'], + }, + ), + ] diff --git a/review/migrations/0005_auto_20190429_0046.py b/cvparser/migrations/0002_resume_user.py similarity index 54% rename from review/migrations/0005_auto_20190429_0046.py rename to cvparser/migrations/0002_resume_user.py index fedd771..8921d94 100644 --- a/review/migrations/0005_auto_20190429_0046.py +++ b/cvparser/migrations/0002_resume_user.py @@ -1,25 +1,21 @@ -# Generated by Django 2.2 on 2019-04-29 00:46 +# Generated by Django 2.2.5 on 2019-12-03 09:12 -import django.db.models.deletion 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), - ('review', '0004_auto_20190429_0014'), + ('cvparser', '0001_initial'), ] operations = [ - migrations.RemoveField( - model_name='review', - name='jobapp', - ), migrations.AddField( - model_name='review', + model_name='resume', name='user', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, - to=settings.AUTH_USER_MODEL), + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), ), ] diff --git a/cvparser/migrations/0003_resume_pos_app.py b/cvparser/migrations/0003_resume_pos_app.py new file mode 100644 index 0000000..afa0757 --- /dev/null +++ b/cvparser/migrations/0003_resume_pos_app.py @@ -0,0 +1,20 @@ +# Generated by Django 2.1.7 on 2019-12-05 06:59 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('positionapps', '0003_feedback'), + ('cvparser', '0002_resume_user'), + ] + + operations = [ + migrations.AddField( + model_name='resume', + name='pos_app', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='positionapps.PositionApplication'), + ), + ] diff --git a/alumni/migrations/__init__.py b/cvparser/migrations/__init__.py similarity index 100% rename from alumni/migrations/__init__.py rename to cvparser/migrations/__init__.py diff --git a/cvparser/models.py b/cvparser/models.py new file mode 100644 index 0000000..6d7211f --- /dev/null +++ b/cvparser/models.py @@ -0,0 +1,31 @@ +from django.db import models +from django.contrib.postgres.fields import ArrayField +from django.contrib.auth import get_user_model + +from positionapps.models import PositionApplication + +User = get_user_model() + + +# Create your models here. + +class Resume(models.Model): + contact = ArrayField(models.TextField(null=True, blank=True)) + skills = ArrayField(models.TextField(null=True, blank=True)) + linkedin = models.CharField(max_length=200, blank=False) + certifications = ArrayField(models.TextField(null=True, blank=True)) + summary = ArrayField(models.TextField(null=True, blank=True)) + languages = ArrayField(models.TextField(null=True, blank=True)) + school = models.CharField(max_length=200, blank=False) + degree = models.CharField(max_length=200, blank=False) + company = models.CharField(max_length=200, blank=False) + position = models.CharField(max_length=200, blank=False) + startdate = models.CharField(max_length=200, blank=False) + enddate = models.CharField(max_length=200, blank=False) + user = models.ForeignKey( + User, on_delete=models.CASCADE, null=True, blank=True) + pos_app = models.ForeignKey( + PositionApplication, on_delete=models.CASCADE, null=True, blank=True) + + class Meta: + ordering = ['linkedin'] diff --git a/cvparser/serializer.py b/cvparser/serializer.py new file mode 100644 index 0000000..7d73d02 --- /dev/null +++ b/cvparser/serializer.py @@ -0,0 +1,12 @@ +from rest_framework import serializers + +from .models import Resume + + +class ResumeSerializer(serializers.ModelSerializer): + def create(self, validated_data): + return Resume.objects.create(**validated_data) + + class Meta: + model = Resume + fields = ('__all__') \ No newline at end of file diff --git a/event/tests.py b/cvparser/tests.py similarity index 100% rename from event/tests.py rename to cvparser/tests.py diff --git a/cvparser/urls.py b/cvparser/urls.py new file mode 100644 index 0000000..ae418d0 --- /dev/null +++ b/cvparser/urls.py @@ -0,0 +1,11 @@ +from django.urls import path +from rest_framework.urlpatterns import format_suffix_patterns + +from cvparser import views + +urlpatterns = [ + path('', views.resume_parser), + path('metrics', views.metrics) + +] +urlpatterns = format_suffix_patterns(urlpatterns) diff --git a/cvparser/utils.py b/cvparser/utils.py new file mode 100644 index 0000000..f989d30 --- /dev/null +++ b/cvparser/utils.py @@ -0,0 +1,26 @@ +import json +from collections import Counter + + +def top_skills_in(comp, data, top_number): + comp = comp.lower() + target = [] + for line in data: + job = ' '.join(line["position"]).lower() + if comp in job: + target.append(line) + + skills = Counter() + for line in target: + skills.update(Counter(line["top_skills"])) + return skills.most_common(top_number) + + +def common_attr(attr, data, top_number): + attrs = Counter() + for line in data: + if isinstance(line[attr], list): + attrs.update(Counter(line[attr])) + else: + attrs.update(Counter([line[attr]])) + return attrs.most_common((top_number)) diff --git a/cvparser/views.py b/cvparser/views.py new file mode 100644 index 0000000..7cb6434 --- /dev/null +++ b/cvparser/views.py @@ -0,0 +1,102 @@ +from django.shortcuts import render +from django.http import JsonResponse + +from django.views.decorators.csrf import csrf_exempt +from rest_framework.decorators import api_view + +from JH_RestAPI import pagination + + +import requests +from utils.error_codes import ResponseCodes +from rest_framework.parsers import JSONParser +import json +from utils.generic_json_creator import create_response +from cvparser.models import Resume +from cvparser.serializer import ResumeSerializer +from positionapps.models import PositionApplication +from cvparser.utils import common_attr, top_skills_in + +# Create your views here. + + +@csrf_exempt +@api_view(["GET", "POST"]) +def resume_parser(request): + if request.method == "GET": + pos_app_id = request.GET.get('id') + if pos_app_id is not None: + resume = Resume.objects.filter(pos_app__pk=pos_app_id) + resume = ResumeSerializer(instance=resume, many=True).data + return JsonResponse(create_response(data=resume), safe=False) + else: + user = request.user + resumes = Resume.objects.filter(user=user).values() + resumes_list = ResumeSerializer(instance=resumes, many=True).data + return JsonResponse(create_response(data=resumes_list), safe=False) + elif request.method == "POST": + body = request.data + if 'resume' in body and 'pos_app_id' in body: + pos_app = PositionApplication.objects.get( + pk=body['pos_app_id']) + pre_resumes = Resume.objects.filter(pos_app__pk=body['pos_app_id']) + post_data = body['resume'] + files = {'resume': post_data} + response = requests.post( + 'http://127.0.0.1:8002/api/parser/', files=files) + if response.status_code == requests.codes.ok: + json_res = json.loads(response.text) + # fill the model + resume = Resume() + resume.user = request.user + resume.contact = json_res['contact'] + resume.skills = json_res['skills'] + resume.linkedin = json_res['linkedin'] + resume.certifications = json_res['certifications'] + resume.summary = json_res['summary'] + resume.languages = json_res['languages'] + resume.school = json_res['school'] + resume.degree = json_res['degree'] + resume.company = json_res['company'] + resume.position = json_res['position'] + resume.startdate = json_res['startdate'] + resume.enddate = json_res['enddate'] + resume.pos_app = pos_app + if pre_resumes is not None: + for pre_resume in pre_resumes: + pre_resume.delete() + resume.save() + resume = ResumeSerializer(instance=resume, many=False).data + return JsonResponse(create_response(data=resume), safe=False) + else: + return JsonResponse(create_response(success=False, error_code=ResponseCodes.invalid_parameters), safe=False) + return JsonResponse(create_response(success=False, error_code=ResponseCodes.invalid_parameters), safe=False) + else: + return JsonResponse(create_response(success=False, error_code=ResponseCodes.invalid_parameters), safe=False) + + +@csrf_exempt +@api_view(["GET"]) +def metrics(request): + if request.method == 'GET': + user = request.user + resumes = Resume.objects.filter(user=user).values() + resumes_list = ResumeSerializer(instance=resumes, many=True).data + attrs = ['skills', 'position', 'languages', + 'school', 'company', 'degree', 'certifications'] + res = {i: {} for i in attrs} + + top_number = 10 + for attr in attrs: + for x, cnt in common_attr(attr, resumes_list, top_number): + res[attr][x] = { + "count": cnt, + "percentage": cnt / len(resumes_list) + } + + # company = 'OpenGov Inc.' # amazon, apple, facebook, google, salesforce + # for skill, cnt in top_skills_in(company, resumes_list, top_number): + # res[attr].append( + # "{}, {} people, {}".format(company, cnt, skill)) + + return JsonResponse(create_response(data=res), safe=False) diff --git a/event/__init__.py b/event/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/event/admin.py b/event/admin.py deleted file mode 100644 index 06fd101..0000000 --- a/event/admin.py +++ /dev/null @@ -1,14 +0,0 @@ -from django.contrib import admin -from .models import Event, EventType - - -@admin.register(Event) -class EventAdmin(admin.ModelAdmin): - list_display = ("title", "event_date_start", "event_date_end", "host_user") - list_filter = ("title", "event_date_start", "event_date_end", "host_user") - - -@admin.register(EventType) -class EventTypeAdmin(admin.ModelAdmin): - list_display = ('id', 'name') - list_filter = ('id', 'name') diff --git a/event/apps.py b/event/apps.py deleted file mode 100644 index 13b1f16..0000000 --- a/event/apps.py +++ /dev/null @@ -1,5 +0,0 @@ -from django.apps import AppConfig - - -class EventConfig(AppConfig): - name = 'event' diff --git a/event/migrations/0001_initial.py b/event/migrations/0001_initial.py deleted file mode 100644 index 296f183..0000000 --- a/event/migrations/0001_initial.py +++ /dev/null @@ -1,67 +0,0 @@ -# Generated by Django 2.2 on 2019-08-08 07:53 - -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), - ('users', '0033_auto_20190807_0847'), - ] - - operations = [ - migrations.CreateModel( - name='Event', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('title', models.CharField(max_length=50)), - ('short_description', models.CharField(max_length=400, null=True, validators=[django.core.validators.MinLengthValidator(250)])), - ('header_image', models.FileField(blank=True, null=True, upload_to='')), - ('view_count', models.IntegerField(default=0)), - ('details', models.TextField()), - ('location_lat', models.FloatField(blank=True, null=True)), - ('location_lon', models.FloatField(blank=True, null=True)), - ('location_address', models.CharField(blank=True, max_length=250, null=True)), - ('event_date', models.DateTimeField()), - ('spot_count', models.IntegerField(blank=True, null=True)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('updated_at', models.DateTimeField(auto_now=True)), - ('is_published', models.BooleanField(default=False)), - ], - options={ - 'ordering': ['-created_at'], - }, - ), - migrations.CreateModel( - name='EventType', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=20)), - ], - ), - migrations.CreateModel( - name='EventAttendee', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('event', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='event.Event')), - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='event_attendee', to=settings.AUTH_USER_MODEL)), - ], - ), - migrations.AddField( - model_name='event', - name='event_type', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='event.EventType'), - ), - migrations.AddField( - model_name='event', - name='host_profile', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='users.Profile'), - ), - ] diff --git a/event/migrations/0002_auto_20190808_0815.py b/event/migrations/0002_auto_20190808_0815.py deleted file mode 100644 index c5d46c7..0000000 --- a/event/migrations/0002_auto_20190808_0815.py +++ /dev/null @@ -1,25 +0,0 @@ -# Generated by Django 2.2 on 2019-08-08 08:15 - -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), - ('event', '0001_initial'), - ] - - operations = [ - migrations.RemoveField( - model_name='event', - name='host_profile', - ), - migrations.AddField( - model_name='event', - name='host_user', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL), - ), - ] diff --git a/event/migrations/0003_remove_event_view_count.py b/event/migrations/0003_remove_event_view_count.py deleted file mode 100644 index 342e643..0000000 --- a/event/migrations/0003_remove_event_view_count.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 2.2 on 2019-08-08 08:51 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('event', '0002_auto_20190808_0815'), - ] - - operations = [ - migrations.RemoveField( - model_name='event', - name='view_count', - ), - ] diff --git a/event/migrations/0004_auto_20190808_0940.py b/event/migrations/0004_auto_20190808_0940.py deleted file mode 100644 index c60412c..0000000 --- a/event/migrations/0004_auto_20190808_0940.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2 on 2019-08-08 09:40 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('event', '0003_remove_event_view_count'), - ] - - operations = [ - migrations.AlterField( - model_name='event', - name='short_description', - field=models.CharField(max_length=400, null=True), - ), - ] diff --git a/event/migrations/0005_auto_20190820_0543.py b/event/migrations/0005_auto_20190820_0543.py deleted file mode 100644 index 43089db..0000000 --- a/event/migrations/0005_auto_20190820_0543.py +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by Django 2.2 on 2019-08-20 05:43 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('event', '0004_auto_20190808_0940'), - ] - - operations = [ - migrations.RenameField( - model_name='event', - old_name='event_date', - new_name='event_date_start', - ), - migrations.AddField( - model_name='event', - name='event_date_end', - field=models.DateTimeField(blank=True, null=True), - ), - migrations.AddField( - model_name='event', - name='location_title', - field=models.CharField(blank=True, max_length=250, null=True), - ), - ] diff --git a/event/migrations/0006_event_is_public.py b/event/migrations/0006_event_is_public.py deleted file mode 100644 index 9980027..0000000 --- a/event/migrations/0006_event_is_public.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2 on 2019-08-24 22:02 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('event', '0005_auto_20190820_0543'), - ] - - operations = [ - migrations.AddField( - model_name='event', - name='is_public', - field=models.BooleanField(default=False), - ), - ] diff --git a/event/migrations/0007_auto_20190826_2248.py b/event/migrations/0007_auto_20190826_2248.py deleted file mode 100644 index 54a72d1..0000000 --- a/event/migrations/0007_auto_20190826_2248.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2 on 2019-08-27 05:48 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('event', '0006_event_is_public'), - ] - - operations = [ - migrations.AlterField( - model_name='event', - name='event_date_start', - field=models.DateTimeField(blank=True, null=True), - ), - ] diff --git a/event/migrations/0008_auto_20190826_2322.py b/event/migrations/0008_auto_20190826_2322.py deleted file mode 100644 index 6ecec74..0000000 --- a/event/migrations/0008_auto_20190826_2322.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 2.2 on 2019-08-27 06:22 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('event', '0007_auto_20190826_2248'), - ] - - operations = [ - migrations.RenameField( - model_name='event', - old_name='is_published', - new_name='is_publish', - ), - migrations.AddField( - model_name='event', - name='is_approved', - field=models.BooleanField(default=False), - ), - ] diff --git a/event/migrations/0009_auto_20190928_1516.py b/event/migrations/0009_auto_20190928_1516.py deleted file mode 100644 index 3da2297..0000000 --- a/event/migrations/0009_auto_20190928_1516.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 2.2 on 2019-09-28 22:16 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('event', '0008_auto_20190826_2322'), - ] - - operations = [ - migrations.RemoveField( - model_name='event', - name='is_public', - ), - ] diff --git a/event/migrations/0010_event_user_types.py b/event/migrations/0010_event_user_types.py deleted file mode 100644 index 1c1a14a..0000000 --- a/event/migrations/0010_event_user_types.py +++ /dev/null @@ -1,34 +0,0 @@ -# Generated by Django 2.2 on 2019-09-30 04:13 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('users', '0048_auto_20190929_2057'), - ('event', '0009_auto_20190928_1516'), - ] - - def migrate_user_types(apps, schema_editor): - UserType = apps.get_model('users', 'UserType') - Event = apps.get_model('event', 'Event') - events = Event.objects.all() - for e in events: - if e.host_user is None or e.host_user.user_type is None or e.host_user.user_type.name == 'Undefined' \ - or e.host_user.user_type.name == 'Public': - e.user_types.add(UserType.objects.get(name__iexact='Public')) - elif e.host_user.user_type.name == 'Student': - e.user_types.add(UserType.objects.get(name__iexact='Student')) - elif e.host_user.user_type.name == 'Alumni': - e.user_types.add(UserType.objects.get(name__iexact='Alumni')) - else: - e.user_types.add(UserType.objects.get(name__iexact='Public')) - - operations = [ - migrations.AddField( - model_name='event', - name='user_types', - field=models.ManyToManyField(to='users.UserType'), - ), - migrations.RunPython(migrate_user_types, reverse_code=migrations.RunPython.noop) - ] diff --git a/event/migrations/__init__.py b/event/migrations/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/event/models.py b/event/models.py deleted file mode 100644 index 75ddd29..0000000 --- a/event/models.py +++ /dev/null @@ -1,43 +0,0 @@ -from django.db import models -from django.contrib.auth import get_user_model -from users.models import UserType - -User = get_user_model() - - -class EventType(models.Model): - name = models.CharField(max_length=20, null=False) - - def __str__(self): - return self.name if self.name is not None else '' - - -class Event(models.Model): - host_user = models.ForeignKey( - User, on_delete=models.SET_NULL, null=True, blank=True) - user_types = models.ManyToManyField(UserType) - title = models.CharField(max_length=50) - short_description = models.CharField(null=True, max_length=400) - header_image = models.FileField(blank=True, null=True) - details = models.TextField() - location_lat = models.FloatField(blank=True, null=True) - location_lon = models.FloatField(blank=True, null=True) - location_title = models.CharField(max_length=250, blank=True, null=True) - location_address = models.CharField(max_length=250, blank=True, null=True) - event_date_start = models.DateTimeField(blank=True, null=True) - event_date_end = models.DateTimeField(blank=True, null=True) - event_type = models.ForeignKey(EventType, on_delete=models.SET_NULL, null=True) - spot_count = models.IntegerField(null=True, blank=True) - created_at = models.DateTimeField(auto_now_add=True) - updated_at = models.DateTimeField(auto_now=True) - is_publish = models.BooleanField(default=False) - is_approved = models.BooleanField(default=False) - - class Meta: - ordering = ['-created_at'] - - -class EventAttendee(models.Model): - user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='event_attendee') - event = models.ForeignKey(Event, on_delete=models.CASCADE) - created_at = models.DateTimeField(auto_now_add=True) diff --git a/event/serializers.py b/event/serializers.py deleted file mode 100644 index 93981f2..0000000 --- a/event/serializers.py +++ /dev/null @@ -1,106 +0,0 @@ -import pytz -from rest_framework import serializers -from .models import EventType, Event, EventAttendee -from django.contrib.auth import get_user_model -from users.serializers import UserSerializer -User = get_user_model() - - -class EventTypeSerializer(serializers.ModelSerializer): - def create(self, validated_data): - return EventType.objects.create(**validated_data) - - class Meta: - model = EventType - fields = ('__all__') - - -class EventAttendeeSerializer(serializers.ModelSerializer): - user = UserSerializer(read_only=True) - - def create(self, validated_data): - return EventAttendee.objects.create(**validated_data) - - class Meta: - model = EventAttendee - fields = '__all__' - - -class EventSerializer(serializers.ModelSerializer): - host_user = UserSerializer(read_only=True) - spot_count = serializers.SerializerMethodField() - attendee_count = serializers.SerializerMethodField() - attended = serializers.SerializerMethodField() - attendee_list = serializers.SerializerMethodField() - event_type = serializers.SerializerMethodField() - mine = serializers.SerializerMethodField() - - def get_mine(self, obj): - return obj.host_user == self.context.get('user') - - def get_created_at(self, obj): - if obj.date is None: - return None - return obj.date.astimezone(pytz.timezone('US/Pacific')) - - def get_event_type(self, obj): - return EventTypeSerializer(instance=obj.event_type, many=False).data - - def get_attendee_list(self, obj): - return EventAttendeeSerializer(instance=EventAttendee.objects.filter(event=obj, user__is_demo=False), - many=True).data - - def get_attended(self, obj): - if EventAttendee.objects.filter(event=obj, user=self.context.get('user')).count() == 0: - return False - return True - - def get_spot_count(self, obj): - if obj.spot_count is None: - return None - return int(obj.spot_count) - EventAttendee.objects.filter(event=obj).count() - - def get_attendee_count(self, obj): - return EventAttendee.objects.filter(event=obj).count() - - def create(self, validated_data): - return Event.objects.create(**validated_data) - - class Meta: - model = Event - exclude = ['user_types'] - - -class EventSimpleSerializer(serializers.ModelSerializer): - host_user = UserSerializer(read_only=True) - spot_count = serializers.SerializerMethodField() - attendee_count = serializers.SerializerMethodField() - attended = serializers.SerializerMethodField() - event_type = serializers.SerializerMethodField() - - def get_created_at(self, obj): - if obj.date is None: - return None - return obj.date.astimezone(pytz.timezone('US/Pacific')) - - def get_event_type(self, obj): - return EventTypeSerializer(instance=obj.event_type, many=False).data - - def get_attended(self, obj): - if EventAttendee.objects.filter(event=obj, user=self.context.get('user')).count() == 0: - return False - return True - - def get_spot_count(self, obj): - if obj.spot_count is None: - return None - - def get_attendee_count(self, obj): - return EventAttendee.objects.filter(event=obj).count() - - def create(self, validated_data): - return Event.objects.create(**validated_data) - - class Meta: - model = Event - exclude = ['details', 'user_types'] \ No newline at end of file diff --git a/event/urls.py b/event/urls.py deleted file mode 100644 index 4a133b6..0000000 --- a/event/urls.py +++ /dev/null @@ -1,16 +0,0 @@ -from django.urls import path -from rest_framework.urlpatterns import format_suffix_patterns - -from event import views - -urlpatterns = [ - path('', views.events), - path('types/', views.types), - path('/', - views.event), - path('/attend/', - views.attend), - path('/leave/', - views.leave), -] -urlpatterns = format_suffix_patterns(urlpatterns) \ No newline at end of file diff --git a/event/views.py b/event/views.py deleted file mode 100644 index 367f0d1..0000000 --- a/event/views.py +++ /dev/null @@ -1,124 +0,0 @@ -import uuid -from datetime import datetime - -from django.contrib.auth import get_user_model -from django.http import JsonResponse -from django.views.decorators.csrf import csrf_exempt -from rest_framework.decorators import api_view -from django.db.models import Q - -from JH_RestAPI import pagination -from event.models import Event, EventType, EventAttendee -from event.serializers import EventSerializer, EventSimpleSerializer, EventTypeSerializer -from utils.error_codes import ResponseCodes -from utils.generic_json_creator import create_response -from utils.utils import get_boolean_from_request, send_notification_email_to_admins - -User = get_user_model() - - -@csrf_exempt -@api_view(["GET", "POST", "PUT", "DELETE"]) -def events(request): - if request.method == "GET": - attended = get_boolean_from_request(request, 'attended') - if not attended: - user_profile = request.user - queryset = Event.objects.filter(Q(is_approved=True) | Q(host_user=request.user), - Q(user_types__in=[user_profile.user_type]) | Q(host_user__is_staff=True)) - else: - attended_events = EventAttendee.objects.filter(user=request.user) - queryset = Event.objects.all().filter(id__in=[e.event.id for e in attended_events]) - queryset = queryset.filter(host_user__isnull=False) - paginator = pagination.CustomPagination() - event_list = paginator.paginate_queryset(queryset, request) - serialized_events = EventSimpleSerializer( - instance=event_list, many=True, context={'user': request.user, 'detailed': False}).data - return JsonResponse(create_response(data=serialized_events, paginator=paginator), safe=False) - elif request.method == "DELETE": - body = request.data - event = Event.objects.get(pk=body['event_id'], host_user=request.user) - event.delete() - return JsonResponse(create_response(data=None), safe=False) - else: - user_profile = request.user - if not user_profile.user_type.event_creation_enabled: - return JsonResponse(create_response(data=None, success=False, error_code=ResponseCodes.not_supported_user), - safe=False) - body = request.data - if request.method == "POST": - event = Event() - event.user_types.add(request.user.user_type) - else: - event = Event.objects.get(pk=body['event_id']) - event.updated_at = datetime.now() - - event.host_user = request.user - if 'title' in body: - event.title = body['title'] - if 'short_description' in body: - event.short_description = body['short_description'] - if 'details' in body: - event.details = body['details'] - if 'location_lat' in body: - event.location_lat = body['location_lat'] - if 'location_lon' in body: - event.location_lon = body['location_lon'] - if 'location_address' in body: - event.location_address = body['location_address'] - if 'event_date_start' in body: - event.event_date_start = body['event_date_start'] - if 'event_date_end' in body: - event.event_date_end = body['event_date_end'] - if 'event_type_id' in body: - event.event_type = EventType.objects.get(pk=body['event_type_id']) - if 'spot_count' in body: - event.spot_count = body['spot_count'] - if 'header_image' in body: - file = body['header_image'] - ext = file.name.split('.')[-1] - filename = "%s.%s" % (uuid.uuid4(), ext) - event.header_image.save(filename, file, save=True) - if 'is_publish' in body: - event.is_publish = get_boolean_from_request(request, 'is_publish') - event.is_approved = False - event.save() - send_notification_email_to_admins('event') - return JsonResponse(create_response(data={"id": event.id}), safe=False) - - -@csrf_exempt -@api_view(["GET"]) -def event(request, event_pk): - obj = Event.objects.get(pk=event_pk) - serialized_event = EventSerializer( - instance=obj, many=False, context={'user': request.user, 'detailed': True}).data - return JsonResponse(create_response(data=serialized_event), safe=False) - - -@csrf_exempt -@api_view(["POST"]) -def attend(request, event_pk): - obj = Event.objects.get(pk=event_pk) - attendance = EventAttendee() - attendance.user = request.user - attendance.event = obj - attendance.save() - return JsonResponse(create_response(data=None), safe=False) - - -@csrf_exempt -@api_view(["POST"]) -def leave(request, event_pk): - event_attendance = EventAttendee.objects.filter(user=request.user, event__pk=event_pk) - if event_attendance.count() > 0: - for event in event_attendance: - event.delete() - return JsonResponse(create_response(data=None), safe=False) - - -@csrf_exempt -@api_view(["GET"]) -def types(request): - event_types = EventType.objects.all() - return JsonResponse(create_response(data=EventTypeSerializer(instance=event_types, many=True).data), safe=False) \ No newline at end of file diff --git a/faq/migrations/0001_initial.py b/faq/migrations/0001_initial.py index 47f122a..4208104 100644 --- a/faq/migrations/0001_initial.py +++ b/faq/migrations/0001_initial.py @@ -1,10 +1,11 @@ -# Generated by Django 2.2 on 2019-04-28 01:51 +# Generated by Django 2.2 on 2019-10-03 23:41 -import django.db.models.deletion from django.db import migrations, models +import django.db.models.deletion class Migration(migrations.Migration): + initial = True dependencies = [ @@ -18,12 +19,11 @@ class Migration(migrations.Migration): ('title', models.CharField(max_length=250, verbose_name='faq title')), ('description', models.CharField(max_length=250, verbose_name='faq description')), ('is_published', models.BooleanField(default=True, verbose_name='is published')), - ('position', models.SmallIntegerField(default=0, verbose_name='position')), ], options={ 'verbose_name': 'faq', 'verbose_name_plural': 'faqs', - 'ordering': ['position'], + 'ordering': ['pk'], }, ), migrations.CreateModel( @@ -32,8 +32,7 @@ class Migration(migrations.Migration): ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('value', models.CharField(max_length=250, verbose_name='value')), ('position', models.SmallIntegerField(default=0, verbose_name='position')), - ('faq', - models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='items', to='faq.Faq')), + ('faq', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='items', to='faq.Faq')), ], options={ 'verbose_name': 'items', diff --git a/faq/migrations/0002_auto_20190429_1944.py b/faq/migrations/0002_auto_20190429_1944.py deleted file mode 100644 index 5dd8ff2..0000000 --- a/faq/migrations/0002_auto_20190429_1944.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 2.2 on 2019-04-29 19:44 - -from django.db import migrations - - -class Migration(migrations.Migration): - dependencies = [ - ('faq', '0001_initial'), - ] - - operations = [ - migrations.AlterModelOptions( - name='faq', - options={'ordering': ['pk'], 'verbose_name': 'faq', 'verbose_name_plural': 'faqs'}, - ), - migrations.RemoveField( - model_name='faq', - name='position', - ), - ] diff --git a/install.sh b/install.sh old mode 100644 new mode 100755 diff --git a/jobapps/__init__.py b/jobapps/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/jobapps/admin.py b/jobapps/admin.py deleted file mode 100644 index 2d33701..0000000 --- a/jobapps/admin.py +++ /dev/null @@ -1,40 +0,0 @@ -from django.contrib import admin - -from utils.export_csv import ExportCsv -from .models import JobApplication, ApplicationStatus, Source, GoogleMail, SourceType, Contact - - -# Register your models here. -@admin.register(JobApplication) -class JobApplicationAdmin(admin.ModelAdmin, ExportCsv): - list_display = ("user", "application_status", "position", - 'company_object', 'app_source', 'is_deleted', 'apply_date') - list_filter = ("user", "application_status", "position", - 'company_object', 'app_source', 'apply_date') - actions = ["export_as_csv"] - - -@admin.register(GoogleMail) -class ReviewAdmin(admin.ModelAdmin): - list_display = ("user", "job_post", "subject", "app_source") - list_filter = ("user", "job_post", "subject", "app_source") - - -@admin.register(ApplicationStatus) -class ApplicationStatusAdmin(admin.ModelAdmin): - list_display = ("value", "pos", "rejectable", "default") - - -@admin.register(Source) -class SourceAdmin(admin.ModelAdmin): - list_display = ("value", "system") - - -@admin.register(SourceType) -class SourceTypeAdmin(admin.ModelAdmin): - list_display = ("id", "value") - - -@admin.register(Contact) -class ContactAdmin(admin.ModelAdmin): - list_display = ("id", "first_name", "last_name", "created_date", "update_date") diff --git a/jobapps/migrations/0001_initial.py b/jobapps/migrations/0001_initial.py deleted file mode 100644 index ee9d144..0000000 --- a/jobapps/migrations/0001_initial.py +++ /dev/null @@ -1,51 +0,0 @@ -# Generated by Django 2.1.5 on 2019-01-29 07:13 - -import django.db.models.deletion -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - initial = True - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ] - - operations = [ - migrations.CreateModel( - name='ApplicationStatus', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('value', models.CharField(max_length=20)), - ], - ), - migrations.CreateModel( - name='JobApplication', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('jobTitle', models.CharField(max_length=200)), - ('company', models.CharField(max_length=200)), - ('companyLogo', models.CharField(blank=True, max_length=200, null=True)), - ('applyDate', models.DateTimeField(blank=True)), - ('msgId', models.CharField(max_length=200)), - ('source', models.CharField(default='', max_length=200)), - ('applicationStatus', - models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, - related_name='applicationStatus', to='jobapps.ApplicationStatus')), - ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, - to=settings.AUTH_USER_MODEL)), - ], - ), - migrations.CreateModel( - name='JobPostDetail', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('posterInformation', models.TextField(blank=True, null=True)), - ('decoratedJobPosting', models.TextField(blank=True, null=True)), - ('topCardV2', models.TextField(blank=True, null=True)), - ('job_post', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, - to='jobapps.JobApplication')), - ], - ), - ] diff --git a/jobapps/migrations/0002_googlemail.py b/jobapps/migrations/0002_googlemail.py deleted file mode 100644 index 3512892..0000000 --- a/jobapps/migrations/0002_googlemail.py +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by Django 2.1.5 on 2019-01-29 09:53 - -import django.db.models.deletion -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('jobapps', '0001_initial'), - ] - - operations = [ - migrations.CreateModel( - name='GoogleMail', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('subject', models.CharField(max_length=200)), - ('body', models.TextField(blank=True, null=True)), - ('date', models.CharField(max_length=50)), - ('job_post', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, - to='jobapps.JobApplication')), - ('user', models.ForeignKey(blank=True, on_delete=django.db.models.deletion.CASCADE, - to=settings.AUTH_USER_MODEL)), - ], - ), - ] diff --git a/jobapps/migrations/0003_jobapplication_isrejected.py b/jobapps/migrations/0003_jobapplication_isrejected.py deleted file mode 100644 index 3fb4228..0000000 --- a/jobapps/migrations/0003_jobapplication_isrejected.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 2.1.5 on 2019-02-01 00:17 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('jobapps', '0002_googlemail'), - ] - - operations = [ - migrations.AddField( - model_name='jobapplication', - name='isRejected', - field=models.BooleanField(default=False), - ), - ] diff --git a/jobapps/migrations/0004_googlemail_msgid.py b/jobapps/migrations/0004_googlemail_msgid.py deleted file mode 100644 index 4fd8d01..0000000 --- a/jobapps/migrations/0004_googlemail_msgid.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 2.1.5 on 2019-02-01 02:01 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('jobapps', '0003_jobapplication_isrejected'), - ] - - operations = [ - migrations.AddField( - model_name='googlemail', - name='msgId', - field=models.CharField(max_length=200, null=True), - ), - ] diff --git a/jobapps/migrations/0005_jobapplication_isdeleted.py b/jobapps/migrations/0005_jobapplication_isdeleted.py deleted file mode 100644 index 0f9c027..0000000 --- a/jobapps/migrations/0005_jobapplication_isdeleted.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 2.1.5 on 2019-02-01 05:08 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('jobapps', '0004_googlemail_msgid'), - ] - - operations = [ - migrations.AddField( - model_name='jobapplication', - name='isDeleted', - field=models.BooleanField(default=False), - ), - ] diff --git a/jobapps/migrations/0006_statushistory.py b/jobapps/migrations/0006_statushistory.py deleted file mode 100644 index f4274b5..0000000 --- a/jobapps/migrations/0006_statushistory.py +++ /dev/null @@ -1,27 +0,0 @@ -# Generated by Django 2.1.5 on 2019-02-10 10:33 - -import datetime - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('jobapps', '0005_jobapplication_isdeleted'), - ] - - operations = [ - migrations.CreateModel( - name='StatusHistory', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('update_date', models.DateTimeField(blank=True, default=datetime.datetime.now)), - ('application_status', - models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, - to='jobapps.ApplicationStatus')), - ('job_post', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, - to='jobapps.JobApplication')), - ], - ), - ] diff --git a/jobapps/migrations/0007_auto_20190210_1046.py b/jobapps/migrations/0007_auto_20190210_1046.py deleted file mode 100644 index 0c487cb..0000000 --- a/jobapps/migrations/0007_auto_20190210_1046.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 2.1.5 on 2019-02-10 10:46 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('jobapps', '0006_statushistory'), - ] - - operations = [ - migrations.AlterField( - model_name='statushistory', - name='application_status', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, - related_name='application_status', to='jobapps.ApplicationStatus'), - ), - ] diff --git a/jobapps/migrations/0008_auto_20190210_1048.py b/jobapps/migrations/0008_auto_20190210_1048.py deleted file mode 100644 index 5f4dbdd..0000000 --- a/jobapps/migrations/0008_auto_20190210_1048.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 2.1.5 on 2019-02-10 10:48 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('jobapps', '0007_auto_20190210_1046'), - ] - - operations = [ - migrations.AlterField( - model_name='statushistory', - name='application_status', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, - to='jobapps.ApplicationStatus'), - ), - ] diff --git a/jobapps/migrations/0009_auto_20190210_1049.py b/jobapps/migrations/0009_auto_20190210_1049.py deleted file mode 100644 index 0d9b8bf..0000000 --- a/jobapps/migrations/0009_auto_20190210_1049.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 2.1.5 on 2019-02-10 10:49 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('jobapps', '0008_auto_20190210_1048'), - ] - - operations = [ - migrations.AlterField( - model_name='statushistory', - name='application_status', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, - related_name='application_status', to='jobapps.ApplicationStatus'), - ), - ] diff --git a/jobapps/migrations/0010_auto_20190210_1051.py b/jobapps/migrations/0010_auto_20190210_1051.py deleted file mode 100644 index 03b1170..0000000 --- a/jobapps/migrations/0010_auto_20190210_1051.py +++ /dev/null @@ -1,25 +0,0 @@ -# Generated by Django 2.1.5 on 2019-02-10 10:51 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('jobapps', '0009_auto_20190210_1049'), - ] - - operations = [ - migrations.AlterField( - model_name='jobapplication', - name='applicationStatus', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, - related_name='jobapplication_applicationStatus', to='jobapps.ApplicationStatus'), - ), - migrations.AlterField( - model_name='statushistory', - name='application_status', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, - related_name='statushistory_applicationStatus', to='jobapps.ApplicationStatus'), - ), - ] diff --git a/jobapps/migrations/0011_auto_20190210_1053.py b/jobapps/migrations/0011_auto_20190210_1053.py deleted file mode 100644 index 671b1f8..0000000 --- a/jobapps/migrations/0011_auto_20190210_1053.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 2.1.5 on 2019-02-10 10:53 - -from django.db import migrations - - -class Migration(migrations.Migration): - dependencies = [ - ('jobapps', '0010_auto_20190210_1051'), - ] - - operations = [ - migrations.RenameField( - model_name='statushistory', - old_name='application_status', - new_name='applicationStatus', - ), - ] diff --git a/jobapps/migrations/0012_jobapplicationnote.py b/jobapps/migrations/0012_jobapplicationnote.py deleted file mode 100644 index 1f50f12..0000000 --- a/jobapps/migrations/0012_jobapplicationnote.py +++ /dev/null @@ -1,26 +0,0 @@ -# Generated by Django 2.1.5 on 2019-03-18 03:05 - -import datetime - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('jobapps', '0011_auto_20190210_1053'), - ] - - operations = [ - migrations.CreateModel( - name='JobApplicationNote', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('description', models.TextField(blank=True, null=True)), - ('created_date', models.DateTimeField(blank=True, default=datetime.datetime.now)), - ('update_date', models.DateTimeField(blank=True, null=True)), - ('job_post', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, - to='jobapps.JobApplication')), - ], - ), - ] diff --git a/jobapps/migrations/0013_auto_20190422_2324.py b/jobapps/migrations/0013_auto_20190422_2324.py deleted file mode 100644 index e67bc9e..0000000 --- a/jobapps/migrations/0013_auto_20190422_2324.py +++ /dev/null @@ -1,27 +0,0 @@ -# Generated by Django 2.1.5 on 2019-04-22 23:24 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('position', '0002_auto_20190422_2320'), - ('company', '0001_initial'), - ('jobapps', '0012_jobapplicationnote'), - ] - - operations = [ - migrations.AddField( - model_name='jobapplication', - name='companyObject', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.DO_NOTHING, - related_name='jobapplication_company', to='company.Company'), - ), - migrations.AddField( - model_name='jobapplication', - name='position', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.DO_NOTHING, - related_name='jobapplication_position', to='position.JobPosition'), - ), - ] diff --git a/jobapps/migrations/0014_prepopulate_company_and_position_tables.py b/jobapps/migrations/0014_prepopulate_company_and_position_tables.py deleted file mode 100644 index 949ffc2..0000000 --- a/jobapps/migrations/0014_prepopulate_company_and_position_tables.py +++ /dev/null @@ -1,52 +0,0 @@ -# Generated by Django 2.1.5 on 2019-04-22 23:24 -from __future__ import unicode_literals - -from django.db import migrations - -from utils.clearbit_company_checker import get_company_detail - - -class Migration(migrations.Migration): - - def populate_data(apps, schema_editor): - JobApplication = apps.get_model('jobapps', 'JobApplication') - JobPosition = apps.get_model('position', 'JobPosition') - Company = apps.get_model('company', 'Company') - for c in JobApplication.objects.all(): - # jt is current dummy job title in the db - jt = JobPosition.objects.all().filter(job_title=c.jobTitle) - if jt is None or len(jt) == 0: - jt = JobPosition(job_title=c.jobTitle) - jt.save() - c.position = jt - else: - c.position = jt[0] - # try to get company detail from clear bit - cd = get_company_detail(c.company) - if cd is None: - company_title = c.company - else: - company_title = cd['name'] - # check if the company details already exists in the db - jc = Company.objects.all().filter(cb_name=company_title) - if jc is None or len(jc) == 0: - # if company doesnt exist save it - if cd is None: - jc = Company(company=c.company, company_logo=c.companyLogo, cb_name=c.company, - cb_company_logo=c.companyLogo, cb_domain=None) - else: - jc = Company(company=c.company, company_logo=c.companyLogo, cb_name=cd['name'], - cb_company_logo=cd['logo'], cb_domain=cd['domain']) - jc.save() - c.companyObject = jc - else: - c.companyObject = jc[0] - c.save() - - dependencies = [ - ('jobapps', '0013_auto_20190422_2324'), - ] - - operations = [ - migrations.RunPython(populate_data, reverse_code=migrations.RunPython.noop) - ] diff --git a/jobapps/migrations/0015_auto_20190422_2356.py b/jobapps/migrations/0015_auto_20190422_2356.py deleted file mode 100644 index 9d9ebfa..0000000 --- a/jobapps/migrations/0015_auto_20190422_2356.py +++ /dev/null @@ -1,24 +0,0 @@ -# Generated by Django 2.1.5 on 2019-04-22 23:56 - -from django.db import migrations - - -class Migration(migrations.Migration): - dependencies = [ - ('jobapps', '0014_prepopulate_company_and_position_tables'), - ] - - operations = [ - migrations.RemoveField( - model_name='jobapplication', - name='company', - ), - migrations.RemoveField( - model_name='jobapplication', - name='companyLogo', - ), - migrations.RemoveField( - model_name='jobapplication', - name='jobTitle', - ), - ] diff --git a/jobapps/migrations/0016_prepopulate_company_and_position_tables2.py b/jobapps/migrations/0016_prepopulate_company_and_position_tables2.py deleted file mode 100644 index 37da8ac..0000000 --- a/jobapps/migrations/0016_prepopulate_company_and_position_tables2.py +++ /dev/null @@ -1,26 +0,0 @@ -# Generated by Django 2.1.5 on 2019-04-23 06:39 - -from django.db import migrations - -from utils.clearbit_company_checker import get_company_detail - - -class Migration(migrations.Migration): - - def populate_data(apps, schema_editor): - Company = apps.get_model('company', 'Company') - for c in Company.objects.all(): - cd = get_company_detail(c.company) - if cd is not None: - c.cb_name = cd['name'] - c.cb_company_logo = cd['logo'] - c.cb_domain = cd['domain'] - c.save() - - dependencies = [ - ('jobapps', '0015_auto_20190422_2356'), - ] - - operations = [ - migrations.RunPython(populate_data, reverse_code=migrations.RunPython.noop) - ] diff --git a/jobapps/migrations/0017_auto_20190426_0124.py b/jobapps/migrations/0017_auto_20190426_0124.py deleted file mode 100644 index e7d30a0..0000000 --- a/jobapps/migrations/0017_auto_20190426_0124.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 2.2 on 2019-04-26 01:24 - -import datetime - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('jobapps', '0016_prepopulate_company_and_position_tables2'), - ] - - operations = [ - migrations.AlterField( - model_name='jobapplicationnote', - name='update_date', - field=models.DateTimeField(blank=True, default=datetime.datetime.now, null=True), - ), - ] diff --git a/jobapps/migrations/0018_applicationstatus_default.py b/jobapps/migrations/0018_applicationstatus_default.py deleted file mode 100644 index 537f8da..0000000 --- a/jobapps/migrations/0018_applicationstatus_default.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 2.2 on 2019-04-26 02:10 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('jobapps', '0017_auto_20190426_0124'), - ] - - operations = [ - migrations.AddField( - model_name='applicationstatus', - name='default', - field=models.BooleanField(default=False), - ) - ] diff --git a/jobapps/migrations/0019_applicationstatus_arrange_default.py b/jobapps/migrations/0019_applicationstatus_arrange_default.py deleted file mode 100644 index 5092770..0000000 --- a/jobapps/migrations/0019_applicationstatus_arrange_default.py +++ /dev/null @@ -1,30 +0,0 @@ -# Generated by Django 2.2 on 2019-04-26 02:10 - -from django.db import migrations - - -class Migration(migrations.Migration): - - def check_default_status(apps, schema_editor): - ApplicationStatus = apps.get_model('jobapps', 'ApplicationStatus') - if ApplicationStatus.objects.filter(default=True).count() == 0: - if ApplicationStatus.objects.filter(value__iexact='Applied').count == 0: - status = ApplicationStatus(value='Applied', default=True) - status.save() - else: - status = ApplicationStatus.objects.filter(value='Applied') - if status.count() == 0: - status = ApplicationStatus(value="Applied") - else: - status = status[0] - status.default = True - status.save() - - dependencies = [ - ('jobapps', '0018_applicationstatus_default'), - ] - - operations = [ - migrations.RunPython(check_default_status, - reverse_code=migrations.RunPython.noop) - ] diff --git a/jobapps/migrations/0020_source.py b/jobapps/migrations/0020_source.py deleted file mode 100644 index 24714a5..0000000 --- a/jobapps/migrations/0020_source.py +++ /dev/null @@ -1,57 +0,0 @@ -# Generated by Django 2.2 on 2019-04-26 05:47 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - def migrate_sources(apps, schema_editor): - Source = apps.get_model('jobapps', 'Source') - JobApplication = apps.get_model('jobapps', 'JobApplication') - # Create parselable sources to DB - linkedIn = Source.objects.create(value='LinkedIn', - gmail_key='from:jobs-listings@linkedin.com AND subject:You applied for', - system=True) - hired = Source.objects.create(value='Hired.com', gmail_key='from:reply@hired.com AND subject:Interview Request', - system=True) - indeed = Source.objects.create(value='Indeed', - gmail_key='from:indeedapply@indeed.com AND subject:Indeed Application', - system=True) - vettery = Source.objects.create(value='Vettery', - gmail_key='from:@connect.vettery.com AND subject:Interview Request', - system=True) - - for c in JobApplication.objects.all(): - if c.source == 'LinkedIn': - c.app_source = linkedIn - if c.source == 'Hired.com': - c.app_source = hired - if c.source == 'Indeed': - c.app_source = indeed - if c.source == 'Vettery': - c.app_source = vettery - c.save() - - dependencies = [ - ('jobapps', '0019_applicationstatus_arrange_default'), - ] - - operations = [ - migrations.CreateModel( - name='Source', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('value', models.CharField(max_length=20)), - ('gmail_key', models.CharField(blank=True, max_length=100)), - ('system', models.BooleanField(default=False)), - ] - ), - migrations.AddField( - model_name='jobapplication', - name='app_source', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.DO_NOTHING, - related_name='jobapplication_source', to='jobapps.Source'), - ), - migrations.RunPython(migrate_sources, reverse_code=migrations.RunPython.noop) - ] diff --git a/jobapps/migrations/0021_remove_jobapplication_source.py b/jobapps/migrations/0021_remove_jobapplication_source.py deleted file mode 100644 index 26fe83e..0000000 --- a/jobapps/migrations/0021_remove_jobapplication_source.py +++ /dev/null @@ -1,16 +0,0 @@ -# Generated by Django 2.2 on 2019-04-26 05:59 - -from django.db import migrations - - -class Migration(migrations.Migration): - dependencies = [ - ('jobapps', '0020_source'), - ] - - operations = [ - migrations.RemoveField( - model_name='jobapplication', - name='source', - ), - ] diff --git a/jobapps/migrations/0022_remove_jobapplication_source.py b/jobapps/migrations/0022_remove_jobapplication_source.py deleted file mode 100644 index 497d93d..0000000 --- a/jobapps/migrations/0022_remove_jobapplication_source.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 2.2 on 2019-04-26 05:59 - -from django.db import migrations - - -class Migration(migrations.Migration): - - def populate_data(apps, schema_editor): - JobApplication = apps.get_model('jobapps', 'JobApplication') - Source = apps.get_model('jobapps', 'Source') - for j in JobApplication.objects.all(): - if j.app_source is None: - source = Source.objects.get(value="N/A") - j.app_source = source - j.save() - - dependencies = [ - ('jobapps', '0021_remove_jobapplication_source'), - ] - - operations = [ - migrations.RunPython(populate_data, reverse_code=migrations.RunPython.noop) - ] diff --git a/jobapps/migrations/0023_sourcetype.py b/jobapps/migrations/0023_sourcetype.py deleted file mode 100644 index a681580..0000000 --- a/jobapps/migrations/0023_sourcetype.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 2.2 on 2019-04-26 21:15 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('jobapps', '0022_remove_jobapplication_source'), - ] - - operations = [ - migrations.CreateModel( - name='SourceType', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('value', models.CharField(max_length=20)), - ], - ), - ] diff --git a/jobapps/migrations/0024_source_image.py b/jobapps/migrations/0024_source_image.py deleted file mode 100644 index 5743132..0000000 --- a/jobapps/migrations/0024_source_image.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 2.2 on 2019-04-30 22:31 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('jobapps', '0023_sourcetype'), - ] - - operations = [ - migrations.AddField( - model_name='source', - name='image', - field=models.CharField(blank=True, max_length=200, null=True), - ), - ] diff --git a/jobapps/migrations/0025_delete_jobpostdetail.py b/jobapps/migrations/0025_delete_jobpostdetail.py deleted file mode 100644 index db26940..0000000 --- a/jobapps/migrations/0025_delete_jobpostdetail.py +++ /dev/null @@ -1,15 +0,0 @@ -# Generated by Django 2.2 on 2019-04-30 23:56 - -from django.db import migrations - - -class Migration(migrations.Migration): - dependencies = [ - ('jobapps', '0024_source_image'), - ] - - operations = [ - migrations.DeleteModel( - name='JobPostDetail', - ), - ] diff --git a/jobapps/migrations/0026_auto_20190501_0453.py b/jobapps/migrations/0026_auto_20190501_0453.py deleted file mode 100644 index 39e6f9e..0000000 --- a/jobapps/migrations/0026_auto_20190501_0453.py +++ /dev/null @@ -1,43 +0,0 @@ -# Generated by Django 2.2 on 2019-05-01 04:53 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('jobapps', '0025_delete_jobpostdetail'), - ] - - operations = [ - migrations.AlterField( - model_name='jobapplication', - name='app_source', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, - related_name='jobapplication_source', to='jobapps.Source'), - ), - migrations.AlterField( - model_name='jobapplication', - name='applicationStatus', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, - related_name='jobapplication_applicationStatus', to='jobapps.ApplicationStatus'), - ), - migrations.AlterField( - model_name='jobapplication', - name='companyObject', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, - related_name='jobapplication_company', to='company.Company'), - ), - migrations.AlterField( - model_name='jobapplication', - name='position', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, - related_name='jobapplication_position', to='position.JobPosition'), - ), - migrations.AlterField( - model_name='statushistory', - name='applicationStatus', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, - related_name='statushistory_applicationStatus', to='jobapps.ApplicationStatus'), - ), - ] diff --git a/jobapps/migrations/0027_googlemail_app_source.py b/jobapps/migrations/0027_googlemail_app_source.py deleted file mode 100644 index f8848d4..0000000 --- a/jobapps/migrations/0027_googlemail_app_source.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 2.2 on 2019-05-10 20:37 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('jobapps', '0026_auto_20190501_0453'), - ] - - operations = [ - migrations.AddField( - model_name='googlemail', - name='app_source', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, - related_name='googlemail_source', to='jobapps.Source'), - ), - ] diff --git a/jobapps/migrations/0028_jobapplication_rejected_date.py b/jobapps/migrations/0028_jobapplication_rejected_date.py deleted file mode 100644 index 8b89a10..0000000 --- a/jobapps/migrations/0028_jobapplication_rejected_date.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 2.2 on 2019-05-28 06:02 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('jobapps', '0027_googlemail_app_source'), - ] - - operations = [ - migrations.AddField( - model_name='jobapplication', - name='rejected_date', - field=models.DateTimeField(blank=True, null=True), - ), - ] diff --git a/jobapps/migrations/0029_auto_20190528_1955.py b/jobapps/migrations/0029_auto_20190528_1955.py deleted file mode 100644 index c90f7d1..0000000 --- a/jobapps/migrations/0029_auto_20190528_1955.py +++ /dev/null @@ -1,29 +0,0 @@ -# Generated by Django 2.2 on 2019-05-28 19:55 - -import datetime - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('jobapps', '0028_jobapplication_rejected_date'), - ] - - operations = [ - migrations.AddField( - model_name='jobapplication', - name='created', - field=models.DateTimeField(blank=True, default=datetime.datetime.now, null=True), - ), - migrations.AddField( - model_name='jobapplication', - name='deleted_date', - field=models.DateTimeField(blank=True, null=True), - ), - migrations.AddField( - model_name='jobapplication', - name='updated_date', - field=models.DateTimeField(blank=True, null=True), - ), - ] diff --git a/jobapps/migrations/0030_auto_20190528_2029.py b/jobapps/migrations/0030_auto_20190528_2029.py deleted file mode 100644 index 0bd2dae..0000000 --- a/jobapps/migrations/0030_auto_20190528_2029.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 2.2 on 2019-05-28 20:29 - -from django.db import migrations - - -class Migration(migrations.Migration): - dependencies = [ - ('jobapps', '0029_auto_20190528_1955'), - ] - - operations = [ - migrations.AlterModelOptions( - name='applicationstatus', - options={'ordering': ['value']}, - ), - migrations.AlterModelOptions( - name='source', - options={'ordering': ['value']}, - ), - ] diff --git a/jobapps/migrations/0031_contact.py b/jobapps/migrations/0031_contact.py deleted file mode 100644 index a8e802d..0000000 --- a/jobapps/migrations/0031_contact.py +++ /dev/null @@ -1,39 +0,0 @@ -# Generated by Django 2.2 on 2019-05-28 20:57 - -import datetime - -import django.core.validators -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('company', '0002_auto_20190429_2110'), - ('position', '0003_auto_20190510_2037'), - ('jobapps', '0030_auto_20190528_2029'), - ] - - operations = [ - migrations.CreateModel( - name='Contact', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=50)), - ('phone_number', models.CharField(blank=True, max_length=17, validators=[ - django.core.validators.RegexValidator( - message="Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed.", - regex='^\\+?1?\\d{9,15}$')])), - ('linkedin_url', models.CharField(max_length=100)), - ('description', models.TextField(blank=True, null=True)), - ('created_date', models.DateTimeField(blank=True, default=datetime.datetime.now)), - ('update_date', models.DateTimeField(blank=True, default=datetime.datetime.now, null=True)), - ('company', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, - related_name='contact_company', to='company.Company')), - ('job_post', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, - to='jobapps.JobApplication')), - ('position', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, - related_name='contact_position', to='position.JobPosition')), - ], - ), - ] diff --git a/jobapps/migrations/0032_auto_20190528_2127.py b/jobapps/migrations/0032_auto_20190528_2127.py deleted file mode 100644 index a56f393..0000000 --- a/jobapps/migrations/0032_auto_20190528_2127.py +++ /dev/null @@ -1,21 +0,0 @@ -# Generated by Django 2.2 on 2019-05-28 21:27 - -import django.core.validators -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('jobapps', '0031_contact'), - ] - - operations = [ - migrations.AlterField( - model_name='contact', - name='phone_number', - field=models.CharField(blank=True, max_length=17, null=True, validators=[ - django.core.validators.RegexValidator( - message="Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed.", - regex='^\\+?1?\\d{9,15}$')]), - ), - ] diff --git a/jobapps/migrations/0033_auto_20190528_2128.py b/jobapps/migrations/0033_auto_20190528_2128.py deleted file mode 100644 index a1ce5fd..0000000 --- a/jobapps/migrations/0033_auto_20190528_2128.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 2.2 on 2019-05-28 21:28 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('jobapps', '0032_auto_20190528_2127'), - ] - - operations = [ - migrations.AlterField( - model_name='contact', - name='linkedin_url', - field=models.CharField(blank=True, max_length=100, null=True), - ), - ] diff --git a/jobapps/migrations/0034_auto_20190807_2149.py b/jobapps/migrations/0034_auto_20190807_2149.py deleted file mode 100644 index 007afbb..0000000 --- a/jobapps/migrations/0034_auto_20190807_2149.py +++ /dev/null @@ -1,32 +0,0 @@ -# Generated by Django 2.2 on 2019-08-07 21:49 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('jobapps', '0033_auto_20190528_2128'), - ] - - operations = [ - migrations.RemoveField( - model_name='contact', - name='name', - ), - migrations.AddField( - model_name='contact', - name='email', - field=models.CharField(blank=True, max_length=150, null=True), - ), - migrations.AddField( - model_name='contact', - name='first_name', - field=models.CharField(blank=True, max_length=50, null=True), - ), - migrations.AddField( - model_name='contact', - name='last_name', - field=models.CharField(blank=True, max_length=50, null=True), - ), - ] diff --git a/jobapps/migrations/0035_auto_20190821_0637.py b/jobapps/migrations/0035_auto_20190821_0637.py deleted file mode 100644 index f0745d8..0000000 --- a/jobapps/migrations/0035_auto_20190821_0637.py +++ /dev/null @@ -1,24 +0,0 @@ -# Generated by Django 2.2 on 2019-08-21 06:37 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('jobapps', '0034_auto_20190807_2149'), - ] - - operations = [ - migrations.RenameField( - model_name='jobapplication', - old_name='applicationStatus', - new_name='application_status', - ), - migrations.RenameField( - model_name='statushistory', - old_name='applicationStatus', - new_name='application_status', - ), - ] diff --git a/jobapps/migrations/0036_auto_20190821_0642.py b/jobapps/migrations/0036_auto_20190821_0642.py deleted file mode 100644 index fa9bd4e..0000000 --- a/jobapps/migrations/0036_auto_20190821_0642.py +++ /dev/null @@ -1,34 +0,0 @@ -# Generated by Django 2.2 on 2019-08-21 06:42 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('jobapps', '0035_auto_20190821_0637'), - ] - - operations = [ - migrations.RenameField( - model_name='googlemail', - old_name='msgId', - new_name='msg_id', - ), - migrations.RenameField( - model_name='jobapplication', - old_name='msgId', - new_name='msg_id', - ), - migrations.AlterField( - model_name='jobapplication', - name='application_status', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='jobapplication_application_status', to='jobapps.ApplicationStatus'), - ), - migrations.AlterField( - model_name='statushistory', - name='application_status', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='statushistory_application_status', to='jobapps.ApplicationStatus'), - ), - ] diff --git a/jobapps/migrations/0037_auto_20190821_0645.py b/jobapps/migrations/0037_auto_20190821_0645.py deleted file mode 100644 index 6219834..0000000 --- a/jobapps/migrations/0037_auto_20190821_0645.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2 on 2019-08-21 06:45 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('jobapps', '0036_auto_20190821_0642'), - ] - - operations = [ - migrations.RenameField( - model_name='jobapplication', - old_name='companyObject', - new_name='company_object', - ), - ] diff --git a/jobapps/migrations/0038_auto_20190821_0647.py b/jobapps/migrations/0038_auto_20190821_0647.py deleted file mode 100644 index e779843..0000000 --- a/jobapps/migrations/0038_auto_20190821_0647.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2 on 2019-08-21 06:47 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('jobapps', '0037_auto_20190821_0645'), - ] - - operations = [ - migrations.RenameField( - model_name='jobapplication', - old_name='applyDate', - new_name='apply_date', - ), - ] diff --git a/jobapps/migrations/0039_auto_20190821_0650.py b/jobapps/migrations/0039_auto_20190821_0650.py deleted file mode 100644 index 470a27b..0000000 --- a/jobapps/migrations/0039_auto_20190821_0650.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 2.2 on 2019-08-21 06:50 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('jobapps', '0038_auto_20190821_0647'), - ] - - operations = [ - migrations.RenameField( - model_name='jobapplication', - old_name='isDeleted', - new_name='is_deleted', - ), - migrations.RenameField( - model_name='jobapplication', - old_name='isRejected', - new_name='is_rejected', - ), - ] diff --git a/jobapps/migrations/0040_auto_20190916_1236.py b/jobapps/migrations/0040_auto_20190916_1236.py deleted file mode 100644 index c665ed1..0000000 --- a/jobapps/migrations/0040_auto_20190916_1236.py +++ /dev/null @@ -1,27 +0,0 @@ -# Generated by Django 2.2 on 2019-09-16 19:36 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('jobapps', '0039_auto_20190821_0650'), - ] - - operations = [ - migrations.AlterModelOptions( - name='applicationstatus', - options={'ordering': ['pos'], 'verbose_name': 'status', 'verbose_name_plural': 'statuses'}, - ), - migrations.AddField( - model_name='applicationstatus', - name='icon', - field=models.FileField(blank=True, null=True, upload_to=''), - ), - migrations.AddField( - model_name='applicationstatus', - name='pos', - field=models.SmallIntegerField(default='0', verbose_name='position'), - ), - ] diff --git a/jobapps/migrations/0041_applicationstatus_rejectable.py b/jobapps/migrations/0041_applicationstatus_rejectable.py deleted file mode 100644 index a979b04..0000000 --- a/jobapps/migrations/0041_applicationstatus_rejectable.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2 on 2019-09-16 21:43 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('jobapps', '0040_auto_20190916_1236'), - ] - - operations = [ - migrations.AddField( - model_name='applicationstatus', - name='rejectable', - field=models.BooleanField(default=True), - ), - ] diff --git a/jobapps/migrations/__init__.py b/jobapps/migrations/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/jobapps/tests.py b/jobapps/tests.py deleted file mode 100644 index a39b155..0000000 --- a/jobapps/tests.py +++ /dev/null @@ -1 +0,0 @@ -# Create your tests here. diff --git a/jobapps/urls.py b/jobapps/urls.py deleted file mode 100644 index 91236cb..0000000 --- a/jobapps/urls.py +++ /dev/null @@ -1,14 +0,0 @@ -from django.urls import path -from rest_framework.urlpatterns import format_suffix_patterns - -from jobapps import views - -urlpatterns = [ - path('statuses/', views.statuses), - path('sources/', views.sources), - path('', views.job_applications), - path('/statusHistory/', views.status_history), - path('/notes/', views.notes), - path('/contacts/', views.contacts), -] -urlpatterns = format_suffix_patterns(urlpatterns) diff --git a/major/migrations/0001_initial.py b/major/migrations/0001_initial.py index f076acb..48c2ee1 100644 --- a/major/migrations/0001_initial.py +++ b/major/migrations/0001_initial.py @@ -1,9 +1,10 @@ -# Generated by Django 2.2 on 2019-08-07 08:34 +# Generated by Django 2.2 on 2019-10-03 23:52 from django.db import migrations, models class Migration(migrations.Migration): + initial = True dependencies = [ diff --git a/metrics/__init__.py b/metrics/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/metrics/admin.py b/metrics/admin.py deleted file mode 100644 index 846f6b4..0000000 --- a/metrics/admin.py +++ /dev/null @@ -1 +0,0 @@ -# Register your models here. diff --git a/metrics/apps.py b/metrics/apps.py deleted file mode 100644 index 1e777e4..0000000 --- a/metrics/apps.py +++ /dev/null @@ -1,5 +0,0 @@ -from django.apps import AppConfig - - -class MetricsConfig(AppConfig): - name = 'metrics' diff --git a/metrics/migrations/__init__.py b/metrics/migrations/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/metrics/models.py b/metrics/models.py deleted file mode 100644 index 6b20219..0000000 --- a/metrics/models.py +++ /dev/null @@ -1 +0,0 @@ -# Create your models here. diff --git a/metrics/tests.py b/metrics/tests.py deleted file mode 100644 index a39b155..0000000 --- a/metrics/tests.py +++ /dev/null @@ -1 +0,0 @@ -# Create your tests here. diff --git a/metrics/urls.py b/metrics/urls.py deleted file mode 100644 index ca8fea8..0000000 --- a/metrics/urls.py +++ /dev/null @@ -1,12 +0,0 @@ -from django.urls import path -from rest_framework.urlpatterns import format_suffix_patterns - -from metrics import views - -urlpatterns = [ - path('personal/generic/', views.generic, name='personal/generic'), - path('personal/detailed/', views.detailed, name='personal/detailed'), - path('aggregated/generic/', views.agg_generic, name='aggregated/generic'), - path('aggregated/detailed/', views.agg_detailed, name='aggregated/detailed'), -] -urlpatterns = format_suffix_patterns(urlpatterns) diff --git a/metrics/views.py b/metrics/views.py deleted file mode 100644 index 85f4b03..0000000 --- a/metrics/views.py +++ /dev/null @@ -1,741 +0,0 @@ -import datetime - -from dateutil.relativedelta import relativedelta -from django.contrib.auth import get_user_model -from django.db.models import Count -from django.db.models import F -from django.db.models import Q -from django.http import JsonResponse -from django.views.decorators.csrf import csrf_exempt -from rest_framework.decorators import api_view - -from jobapps.models import ApplicationStatus -from jobapps.models import JobApplication -from jobapps.models import Source -from utils.error_codes import ResponseCodes -from utils.generic_json_creator import create_response -from utils.utils import get_boolean_from_request - - -@csrf_exempt -@api_view(["GET"]) -def generic(request): - response = [] - total_jobs_applied = JobApplication.objects.filter(user=request.user, is_deleted=False) - for graph in range(4): - item = {} - if graph == 0: - item['graph'] = {} - item['graph']['type'] = 'pie' - item['graph']['legend'] = [] - item['graph']['series'] = [] - item['title'] = 'Phone Screen Rate' - if total_jobs_applied.count() == 0: - item['value'] = '0%' - else: - item['value'] = str(round(total_jobs_applied.filter( - application_status__value='PHONE SCREEN').count() / total_jobs_applied.count() * 100, 2)) + '%' - item['description'] = '13% INCREASE from last month' - statuses = total_jobs_applied.filter(~Q(application_status=None)).values( - 'application_status').annotate(count=Count('pk')) - for status in statuses: - status_text = ApplicationStatus.objects.get( - pk=status['application_status']).value.upper() - item['graph']['legend'].append(status_text) - serie = {'name': status_text, 'value': status['count']} - if status_text == 'PHONE SCREEN': - serie['selected'] = True - item['graph']['series'].append(serie) - elif graph == 1: - item['graph'] = {} - item['graph']['type'] = 'pie' - item['graph']['legend'] = [] - item['graph']['series'] = [] - item['title'] = 'Onsite Interview Rate' - if total_jobs_applied.count() == 0: - item['value'] = '0%' - else: - item['value'] = str(round(total_jobs_applied.filter( - application_status__value='ONSITE INTERVIEW').count() / total_jobs_applied.count() * 100, 2)) + '%' - item['description'] = '4% DECREASE from last month' - statuses = total_jobs_applied.filter(~Q(application_status=None)).values( - 'application_status').annotate(count=Count('pk')) - for status in statuses: - status_text = ApplicationStatus.objects.get( - pk=status['application_status']).value.upper() - item['graph']['legend'].append(status_text) - serie = {'name': status_text, 'value': status['count']} - if status_text == 'ONSITE INTERVIEW': - serie['selected'] = True - item['graph']['series'].append(serie) - elif graph == 2: - item['graph'] = {} - item['graph']['type'] = 'line' - item['graph']['series'] = [] - item['title'] = 'Total Applied Jobs' - item['value'] = total_jobs_applied.count() - item['description'] = '21% INCREASE from last month' - - today = datetime.date.today() + relativedelta(days=+1) - last_year = datetime.date.today() + relativedelta(years=-2) - months = [] - for i in range(0, today.month): - d = today + relativedelta(months=-1 * i) - months.insert(0, d) - dec = today + relativedelta(months=-1 * today.month) - while len(months) != 12: - months.insert(0, dec) - dec = dec + relativedelta(months=-1) - apps_by_month = total_jobs_applied.filter(apply_date__range=[ - last_year, today]).values('apply_date__year', 'apply_date__month').annotate( - count=Count('pk')) - - serie = {'name': item['title'], 'type': 'line'} - data = [0] * 12 - for j in range(0, 12): - count = apps_by_month.filter( - apply_date__year=months[j].year, apply_date__month=months[j].month) - if count.count() > 0: - data[j] = count[0]['count'] - serie['data'] = data - item['graph']['series'].append(serie) - elif graph == 3: - item['graph'] = {} - item['graph']['type'] = 'line' - item['graph']['series'] = [] - item['title'] = 'Total Rejected Jobs' - item['value'] = str(total_jobs_applied.filter(is_rejected=True).count()) + '/' + str( - total_jobs_applied.count()) - item['description'] = '3% DECREASE from last month' - - today = datetime.date.today() + relativedelta(days=+1) - last_year = datetime.date.today() + relativedelta(years=-2) - months = [] - for i in range(0, today.month): - d = today + relativedelta(months=-1 * i) - months.insert(0, d) - dec = today + relativedelta(months=-1 * today.month) - while len(months) != 12: - months.insert(0, dec) - dec = dec + relativedelta(months=-1) - apps_by_month = total_jobs_applied.filter(apply_date__range=[ - last_year, today], is_rejected=True).values('apply_date__year', 'apply_date__month').annotate( - count=Count('pk')) - - serie = {'name': item['title'], 'type': 'line'} - data = [0] * 12 - for j in range(0, 12): - count = apps_by_month.filter( - rejected_date__year=months[j].year, rejected_date__month=months[j].month) - if count.count() > 0: - data[j] = count[0]['count'] - serie['data'] = data - item['graph']['series'].append(serie) - response.append(item) - return JsonResponse(create_response(data=response), safe=False) - - -@csrf_exempt -@api_view(["GET"]) -def detailed(request): - response = [] - for graph in range(4): - item = {} - if graph == 0: - item['graph'] = {} - item['graph']['type'] = 'bar' - item['graph']['series'] = [] - item['graph']['title'] = 'Monthly Applications' - item['list'] = {} - item['list']['data'] = [] - item['list']['title'] = 'Top Job Sources' - - system_sources = Source.objects.filter(system=True) - sources = ['Others'] - for s in system_sources: - sources.insert(0, s.value) - today = datetime.date.today() + relativedelta(days=+1) - last_year = datetime.date.today() + relativedelta(years=-1) - months = [] - months_string = [] - - for i in range(0, today.month): - d = today + relativedelta(months=-1 * i) - months.insert(0, d) - months_string.insert(0, d.strftime("%B")) - dec = today + relativedelta(months=-1 * today.month) - while len(months) != 12: - months.insert(0, dec) - months_string.insert(0, dec.strftime("%B")) - dec = dec + relativedelta(months=-1) - for i in sources: - if i != 'Others': - apps = JobApplication.objects.filter(user=request.user, app_source__value=i, - apply_date__range=[ - last_year, today], is_deleted=False) - apps_by_months = apps.values( - 'apply_date__year', 'apply_date__month').annotate(count=Count('pk')) - else: - apps = JobApplication.objects.filter(user=request.user, app_source__system=False, - apply_date__range=[ - last_year, today], is_deleted=False) - apps_by_months = apps.values( - 'apply_date__year', 'apply_date__month').annotate(count=Count('pk')) - item['list']['data'].append({'id': i, 'value': apps.count()}) - serie = {'name': i} - data = [0] * 12 - for j in range(0, 12): - count = apps_by_months.filter( - apply_date__year=months[j].year, apply_date__month=months[j].month) - if len(count) > 0: - data[j] = count[0]['count'] - serie['data'] = data - serie['type'] = "bar" - serie['stack'] = 'Source' - item['graph']['series'].append(serie) - - item['list']['data'].sort(key=lambda x: x['value'], reverse=True) - item['list']['total'] = JobApplication.objects.filter(user=request.user, apply_date__range=[ - last_year, today], is_deleted=False).count() - item['graph']['xAxis'] = months_string - elif graph == 1: - item['graph'] = {} - item['graph']['type'] = 'line' - item['graph']['series'] = [] - item['graph']['title'] = 'Status Change' - item['list'] = {} - item['list']['data'] = [] - item['list']['title'] = 'Top Job Statuses' - - today = datetime.date.today() + relativedelta(days=+1) - last_year = datetime.date.today() + relativedelta(years=-1) - months = [] - months_string = [] - - for i in range(0, today.month): - d = today + relativedelta(months=-1 * i) - months.insert(0, d) - months_string.insert(0, d.strftime("%B")) - dec = today + relativedelta(months=-1 * today.month) - while len(months) != 12: - months.insert(0, dec) - months_string.insert(0, dec.strftime("%B")) - dec = dec + relativedelta(months=-1) - - statuses = list(ApplicationStatus.objects.all()) - status_total = ApplicationStatus(value='Total') - statuses.append(status_total) - for status in statuses: - if status.value == 'Total': - apps = JobApplication.objects.filter(user=request.user, apply_date__range=[last_year, today], - is_deleted=False) - else: - apps = JobApplication.objects.filter(user=request.user, application_status=status, - apply_date__range=[ - last_year, today], is_deleted=False) - item['list']['data'].append({'id': status.value.upper(), 'value': apps.count()}) - apps = apps.values( - 'apply_date__year', 'apply_date__month').annotate(count=Count('pk')) - serie = {'name': status.value.upper()} - data = [0] * 12 - for j in range(0, 12): - count = apps.filter( - apply_date__year=months[j].year, apply_date__month=months[j].month) - if len(count) > 0: - data[j] = count[0]['count'] - serie['data'] = data - serie['type'] = "line" - item['graph']['series'].append(serie) - item['list']['data'].sort(key=lambda x: x['value'], reverse=True) - item['list']['total'] = JobApplication.objects.filter(user=request.user, apply_date__range=[ - last_year, today], is_deleted=False).count() - item['graph']['xAxis'] = months_string - elif graph == 2: - item['graph'] = {} - item['graph']['type'] = 'radar' - item['graph']['polar'] = [] - item['graph']['series'] = [] - item['graph']['title'] = 'Skill Analysis' - item['list'] = {} - item['list']['data'] = [] - item['list']['title'] = 'Top Skills' - - # dummy data - serie = {'value': [9, 8, 9, 7, 5, 3], 'name': 'Market Demand'} - item['graph']['series'].append(serie) - serie = {'value': [10, 8, 5, 7, 3, 2], 'name': 'Your Skills'} - item['graph']['series'].append(serie) - indicators = [] - indicator = {'text': 'Java', 'max': 10} - indicators.append(indicator) - indicator = {'text': 'Python', 'max': 10} - indicators.append(indicator) - indicator = {'text': 'R', 'max': 10} - indicators.append(indicator) - indicator = {'text': 'React Native', 'max': 10} - indicators.append(indicator) - indicator = {'text': 'GO', 'max': 10} - indicators.append(indicator) - indicator = {'text': 'React', 'max': 10} - indicators.append(indicator) - item['graph']['polar'].append({'indicator': indicators}) - - item['list']['data'].append({'id': 'GO', 'value': 27}) - item['list']['data'].append({'id': 'Java', 'value': 18}) - item['list']['data'].append({'id': 'React', 'value': 16}) - item['list']['data'].append({'id': 'R', 'value': 14}) - item['list']['data'].append({'id': 'Python', 'value': 12}) - item['list']['data'].append({'id': 'React Native', 'value': 8}) - - item['list']['total'] = 32 - elif graph == 3: - item['graph'] = {} - item['graph']['type'] = 'bar' - item['graph']['series'] = [] - item['graph']['title'] = 'Top Companies' - item['list'] = {} - item['list']['data'] = [] - item['list']['title'] = 'Top Companies' - - item['graph']['xAxis'] = [] - - top_companies = JobApplication.objects.filter(~Q(application_status=None), user=request.user, - is_deleted=False).values( - company=F('company_object__company')).annotate(count=Count('company_object')).order_by('-count') - if top_companies.count() > 10: - top_companies = top_companies[:10] - - total = 0 - for company in top_companies: - item['list']['data'].append({'id': company['company'], 'value': company['count']}) - total += company['count'] - item['list']['total'] = total - - statuses = ApplicationStatus.objects.all() - for status in statuses: - item['graph']['xAxis'].append(status.value.upper()) - for company in top_companies: - serie = {'name': company['company'], 'type': "bar", 'stack': 'Company'} - data = [0] * statuses.count() - for idx, status in enumerate(statuses): - data[idx] = JobApplication.objects.filter(~Q(application_status=None), user=request.user, - company_object__company=company['company'], - application_status=status).count() - serie['data'] = data - item['graph']['series'].append(serie) - - response.append(item) - return JsonResponse(create_response(data=response), safe=False) - - -@csrf_exempt -@api_view(["GET"]) -def agg_detailed(request): - response = [] - user_profile = request.user - User = get_user_model() - filter_by_college = False - public = get_boolean_from_request(request, 'public') - if user_profile.user_type.name == 'Student' and not public: - college_users = User.objects.filter( - id__in=[p.id for p in User.objects.filter(college=user_profile.college, user_type__name__iexact='Student', is_demo=False)]) - filter_by_college = True - elif user_profile.user_type.name == 'Alumni' and not public: - college_users = User.objects.filter( - id__in=[p.id for p in User.objects.filter(college=user_profile.college, user_type__name__iexact='Alumni', is_demo=False)]) - filter_by_college = True - - if not user_profile.user_type.college_specific_metrics_enabled and not public: - return JsonResponse(create_response(data=None, success=False, error_code=ResponseCodes.not_supported_user), - safe=False) - - for graph in range(4): - item = {} - if graph == 0: - item['graph'] = {} - item['graph']['type'] = 'bar' - item['graph']['series'] = [] - item['graph']['title'] = 'Top Companies Applied' - item['list'] = {} - item['list']['data'] = [] - item['list']['title'] = 'Top Companies Applied' - - today = datetime.date.today() + relativedelta(days=+1) - last_year = datetime.date.today() + relativedelta(years=-1) - months = [] - months_string = [] - - if filter_by_college: - distinct_jobapps = JobApplication.objects.filter(user__in=college_users).distinct('company_object', 'user') - else: - distinct_jobapps = JobApplication.objects.filter(user__is_demo=False).distinct('company_object', 'user') - # ~Q(application_status__pk = 2) indicates not 'To Apply' statuses in the prod DB. - top_companies = JobApplication.objects.filter(~Q(application_status=None), ~Q(application_status__pk=2), - apply_date__range=[ - last_year, today], - is_deleted=False).values( - company=F('company_object__company')).annotate(count=Count('company_object')).filter( - id__in=distinct_jobapps).order_by('-count') - - for i in range(0, today.month): - d = today + relativedelta(months=-1 * i) - months.insert(0, d) - months_string.insert(0, d.strftime("%B")) - dec = today + relativedelta(months=-1 * today.month) - while len(months) != 12: - months.insert(0, dec) - months_string.insert(0, dec.strftime("%B")) - dec = dec + relativedelta(months=-1) - - item['graph']['xAxis'] = months_string - - if top_companies.count() > 10: - top_companies = top_companies[:10] - - total = 0 - for company in top_companies: - serie = {'name': company['company'], 'type': 'bar'} - data = [0] * 12 - for j in range(0, 12): - count = JobApplication.objects.filter(company_object__company=company['company'], - apply_date__year=months[j].year, - apply_date__month=months[j].month, - is_deleted=False, - id__in=distinct_jobapps) - data[j] = count.count() - serie['data'] = data - serie['stack'] = 'Company' - item['graph']['series'].append(serie) - item['list']['data'].append({'id': company['company'], 'value': company['count']}) - total += company['count'] - item['list']['total'] = total - - elif graph == 1: - item['graph'] = {} - item['graph']['type'] = 'line' - item['graph']['series'] = [] - item['graph']['title'] = 'Peak Season' - item['list'] = {} - item['list']['data'] = [] - item['list']['title'] = 'Peak Season' - - today = datetime.date.today() + relativedelta(days=+1) - last_year = datetime.date.today() + relativedelta(years=-1) - months = [] - months_string = [] - - for i in range(0, today.month): - d = today + relativedelta(months=-1 * i) - months.insert(0, d) - months_string.insert(0, d.strftime("%B")) - dec = today + relativedelta(months=-1 * today.month) - while len(months) != 12: - months.insert(0, dec) - months_string.insert(0, dec.strftime("%B")) - dec = dec + relativedelta(months=-1) - - item['graph']['xAxis'] = months_string - - system_sources = Source.objects.filter(system=True) - sources = ['Others', 'Total'] - for s in system_sources: - sources.insert(0, s.value) - - for i in sources: - if i == 'Total': - if filter_by_college: - apps = JobApplication.objects.filter(user__in=college_users, apply_date__range=[last_year, today], - is_deleted=False) - else: - apps = JobApplication.objects.filter(apply_date__range=[last_year, today], is_deleted=False, user__is_demo=False) - apps_by_months = apps.values( - 'apply_date__year', 'apply_date__month').annotate(count=Count('pk')) - elif i != 'Others': - if filter_by_college: - apps = JobApplication.objects.filter(user__in=college_users, app_source__value=i, - apply_date__range=[ - last_year, today], is_deleted=False) - else: - apps = JobApplication.objects.filter(app_source__value=i, apply_date__range=[ - last_year, today], is_deleted=False, user__is_demo=False) - apps_by_months = apps.values( - 'apply_date__year', 'apply_date__month').annotate(count=Count('pk')) - else: - if filter_by_college: - apps = JobApplication.objects.filter(user__in=college_users, app_source__system=False, - apply_date__range=[ - last_year, today], is_deleted=False) - else: - apps = JobApplication.objects.filter(app_source__system=False, apply_date__range=[ - last_year, today], is_deleted=False, user__is_demo=False) - apps_by_months = apps.values( - 'apply_date__year', 'apply_date__month').annotate(count=Count('pk')) - - serie = {'name': i} - data = [0] * 12 - for j in range(0, 12): - count = apps_by_months.filter( - apply_date__year=months[j].year, apply_date__month=months[j].month) - if len(count) > 0: - data[j] = count[0]['count'] - serie['data'] = data - serie['type'] = "line" - # serie['stack'] = 'Source' - item['graph']['series'].append(serie) - - total = 0 - for idx, month in enumerate(months): - if filter_by_college: - apps = JobApplication.objects.filter(user__in=college_users, apply_date__year=month.year, - apply_date__month=month.month, - is_deleted=False) - else: - apps = JobApplication.objects.filter(apply_date__year=month.year, apply_date__month=month.month, - is_deleted=False, user__is_demo=False) - item['list']['data'].append( - {'id': months_string[idx] + ' ' + str(month.year), 'value': apps.count()}) - total += apps.count() - item['list']['data'].sort(key=lambda x: x['value'], reverse=True) - item['list']['total'] = total - elif graph == 2: - item['graph'] = {} - item['graph']['type'] = 'radar' - item['graph']['polar'] = [] - item['graph']['series'] = [] - item['graph']['title'] = 'Skill Analysis' - item['list'] = {} - item['list']['data'] = [] - item['list']['title'] = 'Top Skills' - - # dummy data - serie = {'value': [9, 8, 9, 7, 5, 3], 'name': 'Market Demand'} - item['graph']['series'].append(serie) - serie = {'value': [10, 8, 5, 7, 3, 2], 'name': 'Overall Skills'} - item['graph']['series'].append(serie) - indicators = [] - indicator = {'text': 'Java', 'max': 10} - indicators.append(indicator) - indicator = {'text': 'Python', 'max': 10} - indicators.append(indicator) - indicator = {'text': 'R', 'max': 10} - indicators.append(indicator) - indicator = {'text': 'React Native', 'max': 10} - indicators.append(indicator) - indicator = {'text': 'GO', 'max': 10} - indicators.append(indicator) - indicator = {'text': 'React', 'max': 10} - indicators.append(indicator) - item['graph']['polar'].append({'indicator': indicators}) - - item['list']['data'].append({'id': 'Java', 'value': 27}) - item['list']['data'].append({'id': 'GO', 'value': 18}) - item['list']['data'].append({'id': 'React', 'value': 16}) - item['list']['data'].append({'id': 'R', 'value': 14}) - item['list']['data'].append({'id': 'Python', 'value': 12}) - item['list']['data'].append({'id': 'React Native', 'value': 8}) - - item['list']['total'] = 32 - elif graph == 3: - item['graph'] = {} - item['graph']['type'] = 'bar' - item['graph']['series'] = [] - item['graph']['title'] = 'Top Positions Applied' - item['list'] = {} - item['list']['data'] = [] - item['list']['title'] = 'Top Positions Applied' - - today = datetime.date.today() + relativedelta(days=+1) - last_year = datetime.date.today() + relativedelta(years=-1) - months = [] - months_string = [] - - if filter_by_college: - distinct_positions = JobApplication.objects.filter(user__in=college_users).distinct('position', 'user') - else: - distinct_positions = JobApplication.objects.filter(user__is_demo=False).distinct('position', 'user') - # ~Q(application_status__pk = 2) indicates not 'To Apply' statuses in the prod DB. - top_positions = JobApplication.objects.filter(~Q(application_status=None), ~Q(application_status__pk=2), - apply_date__range=[ - last_year, today], - is_deleted=False).values( - position_=F('position__job_title')).annotate(count=Count('position')).filter( - id__in=distinct_positions).order_by('-count').order_by('-count') - - for i in range(0, today.month): - d = today + relativedelta(months=-1 * i) - months.insert(0, d) - months_string.insert(0, d.strftime("%B")) - dec = today + relativedelta(months=-1 * today.month) - while len(months) != 12: - months.insert(0, dec) - months_string.insert(0, dec.strftime("%B")) - dec = dec + relativedelta(months=-1) - - item['graph']['xAxis'] = months_string - - if top_positions.count() > 10: - top_positions = top_positions[:10] - - total = 0 - for position in top_positions: - serie = {'name': position['position_'], 'type': 'bar'} - data = [0] * 12 - for j in range(0, 12): - count = JobApplication.objects.filter(~Q(application_status=None), ~Q(application_status__pk=2), - position__job_title=position['position_'], - apply_date__year=months[j].year, - apply_date__month=months[j].month, - is_deleted=False, - id__in=distinct_positions) - data[j] = count.count() - serie['data'] = data - item['graph']['series'].append(serie) - serie['stack'] = 'Company' - item['list']['data'].append({'id': position['position_'], 'value': position['count']}) - total += position['count'] - item['list']['total'] = total - - response.append(item) - return JsonResponse(create_response(data=response), safe=False) - - -@csrf_exempt -@api_view(["GET"]) -def agg_generic(request): - response = [] - user_profile = request.user - User = get_user_model() - filter_by_college = False - public = get_boolean_from_request(request, 'public') - if user_profile.user_type.name == 'Student' and not public: - college_users = get_user_model().objects.filter( - id__in=[p.id for p in User.objects.filter(college=user_profile.college, user_type__name__iexact='Student', is_demo=False)]) - filter_by_college = True - total_jobs_applied = JobApplication.objects.filter(user__in=college_users, user__is_demo=False, is_deleted=False) - elif user_profile.user_type.name == 'Alumni' and not public: - college_users = get_user_model().objects.filter( - id__in=[p.id for p in User.objects.filter(college=user_profile.college, user_type__name__iexact='Alumni', is_demo=False)]) - filter_by_college = True - total_jobs_applied = JobApplication.objects.filter(user__in=college_users, user__is_demo=False, is_deleted=False) - else: - if not user_profile.user_type.college_specific_metrics_enabled and not public: - return JsonResponse(create_response(data=None, success=False, error_code=ResponseCodes.not_supported_user), safe=False) - total_jobs_applied = JobApplication.objects.filter(is_deleted=False, user__is_demo=False) - for graph in range(4): - item = dict(graph={}) - if graph == 0: - item['graph']['type'] = 'pie' - item['graph']['legend'] = [] - item['graph']['series'] = [] - item['title'] = 'Phone Screen Rate' - if total_jobs_applied.count() == 0: - item['value'] = '0%' - else: - item['value'] = str(round(total_jobs_applied.filter( - application_status__value='PHONE SCREEN').count() / total_jobs_applied.count() * 100, 2)) + '%' - item['description'] = '13% INCREASE from last month' - statuses = total_jobs_applied.filter(~Q(application_status=None)).values( - 'application_status').annotate(count=Count('pk')) - for status in statuses: - status_text = ApplicationStatus.objects.get( - pk=status['application_status']).value.upper() - item['graph']['legend'].append(status_text) - serie = {'name': status_text, 'value': status['count']} - if status_text == 'PHONE SCREEN': - serie['selected'] = True - item['graph']['series'].append(serie) - elif graph == 1: - item['graph']['type'] = 'pie' - item['graph']['legend'] = [] - item['graph']['series'] = [] - item['title'] = 'Onsite Interview Rate' - if total_jobs_applied.count() == 0: - item['value'] = '0%' - else: - item['value'] = str(round(total_jobs_applied.filter( - application_status__value='ONSITE INTERVIEW').count() / total_jobs_applied.count() * 100, 2)) + '%' - item['description'] = '4% DECREASE from last month' - statuses = total_jobs_applied.filter(~Q(application_status=None)).values( - 'application_status').annotate(count=Count('pk')) - for status in statuses: - status_text = ApplicationStatus.objects.get( - pk=status['application_status']).value.upper() - item['graph']['legend'].append(status_text) - serie = {'name': status_text, 'value': status['count']} - if status_text == 'ONSITE INTERVIEW': - serie['selected'] = True - item['graph']['series'].append(serie) - elif graph == 2: - item['graph']['type'] = 'line' - item['graph']['series'] = [] - item['title'] = 'Total Applied Jobs' - item['value'] = total_jobs_applied.count() - item['description'] = '21% INCREASE from last month' - - today = datetime.date.today() + relativedelta(days=+1) - last_year = datetime.date.today() + relativedelta(years=-2) - months = [] - for i in range(0, today.month): - d = today + relativedelta(months=-1 * i) - months.insert(0, d) - dec = today + relativedelta(months=-1 * today.month) - while len(months) != 12: - months.insert(0, dec) - dec = dec + relativedelta(months=-1) - apps_by_month = total_jobs_applied.filter(apply_date__range=[ - last_year, today]).values('apply_date__year', 'apply_date__month').annotate( - count=Count('pk')) - - serie = {'name': item['title'], 'type': 'line'} - data = [0] * 12 - for j in range(0, 12): - count = apps_by_month.filter( - apply_date__year=months[j].year, apply_date__month=months[j].month) - if count.count() > 0: - data[j] = count[0]['count'] - serie['data'] = data - item['graph']['series'].append(serie) - elif graph == 3: - item['graph']['type'] = 'line' - item['graph']['series'] = [] - item['title'] = 'Total Users' - User = get_user_model() - if filter_by_college: - total_user = college_users - else: - total_user = User.objects.filter(is_demo=False) - total_user_count = total_user.count() - item['value'] = total_user_count - total_application = total_jobs_applied.count() - total_average = total_application / total_user_count - item['description'] = 'Average ' + str(round(total_average, 2)) + ' & ' + 'Total ' + str( - total_application) + ' Jobs' - - today = datetime.date.today() + relativedelta(days=+1) - last_year = datetime.date.today() + relativedelta(years=-2) - months = [] - for i in range(0, today.month): - d = today + relativedelta(months=-1 * i) - months.insert(0, d) - dec = today + relativedelta(months=-1 * today.month) - while len(months) != 12: - months.insert(0, dec) - dec = dec + relativedelta(months=-1) - apps_by_month = total_user.filter(date_joined__range=[ - last_year, today]).values('date_joined__year', 'date_joined__month').annotate( - count=Count('pk')) - - serie = {'name': item['title'], 'type': 'line'} - data = [0] * 12 - for j in range(0, 12): - count = apps_by_month.filter( - date_joined__year=months[j].year, date_joined__month=months[j].month) - if count.count() > 0: - if j == 0: - data[j] = count[0]['count'] - else: - data[j] = data[j - 1] + count[0]['count'] - serie['data'] = data - item['graph']['series'].append(serie) - response.append(item) - return JsonResponse(create_response(data=response), safe=False) diff --git a/notifications/migrations/0001_initial.py b/notifications/migrations/0001_initial.py index f2ee783..0ce9946 100644 --- a/notifications/migrations/0001_initial.py +++ b/notifications/migrations/0001_initial.py @@ -1,9 +1,10 @@ -# Generated by Django 2.2 on 2019-04-23 20:53 +# Generated by Django 2.2 on 2019-10-03 23:52 from django.db import migrations, models class Migration(migrations.Migration): + initial = True dependencies = [ @@ -19,5 +20,8 @@ class Migration(migrations.Migration): ('image', models.CharField(blank=True, max_length=200, null=True)), ('created_at', models.DateTimeField(auto_now_add=True)), ], + options={ + 'ordering': ['-created_at'], + }, ), ] diff --git a/notifications/migrations/0002_auto_20190429_1944.py b/notifications/migrations/0002_auto_20190429_1944.py deleted file mode 100644 index c47f6fc..0000000 --- a/notifications/migrations/0002_auto_20190429_1944.py +++ /dev/null @@ -1,16 +0,0 @@ -# Generated by Django 2.2 on 2019-04-29 19:44 - -from django.db import migrations - - -class Migration(migrations.Migration): - dependencies = [ - ('notifications', '0001_initial'), - ] - - operations = [ - migrations.AlterModelOptions( - name='notification', - options={'ordering': ['-created_at']}, - ), - ] diff --git a/poll/__init__.py b/poll/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/poll/admin.py b/poll/admin.py deleted file mode 100644 index 5993199..0000000 --- a/poll/admin.py +++ /dev/null @@ -1,25 +0,0 @@ -from django.contrib import admin - -from .models import * - - -class PollItemInline(admin.TabularInline): - model = Item - extra = 0 - max_num = 15 - - -class PollAdmin(admin.ModelAdmin): - list_display = ('title', 'date', 'vote_count', 'is_published') - inlines = [PollItemInline, ] - - -admin.site.register(Poll, PollAdmin) - - -class VoteAdmin(admin.ModelAdmin): - list_display = ('poll', 'ip', 'user', 'datetime') - list_filter = ('poll', 'datetime') - - -admin.site.register(Vote, VoteAdmin) diff --git a/poll/apps.py b/poll/apps.py deleted file mode 100644 index 37c595a..0000000 --- a/poll/apps.py +++ /dev/null @@ -1,5 +0,0 @@ -from django.apps import AppConfig - - -class PollConfig(AppConfig): - name = 'poll' diff --git a/poll/migrations/0001_initial.py b/poll/migrations/0001_initial.py deleted file mode 100644 index 0fbcd9f..0000000 --- a/poll/migrations/0001_initial.py +++ /dev/null @@ -1,69 +0,0 @@ -# Generated by Django 2.1.5 on 2019-04-19 04:06 - -import datetime - -import django.db.models.deletion -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - initial = True - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ] - - operations = [ - migrations.CreateModel( - name='Item', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('value', models.CharField(max_length=250, verbose_name='value')), - ('pos', models.SmallIntegerField(default='0', verbose_name='position')), - ], - options={ - 'verbose_name': 'answer', - 'verbose_name_plural': 'answers', - 'ordering': ['pos'], - }, - ), - migrations.CreateModel( - name='Poll', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('title', models.CharField(max_length=250, verbose_name='question')), - ('date', models.DateField(default=datetime.date.today, verbose_name='date')), - ('is_published', models.BooleanField(default=True, verbose_name='is published')), - ], - options={ - 'verbose_name': 'poll', - 'verbose_name_plural': 'polls', - 'ordering': ['-date'], - }, - ), - migrations.CreateModel( - name='Vote', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('ip', models.GenericIPAddressField(verbose_name="user's IP")), - ('datetime', models.DateTimeField(auto_now_add=True)), - ('item', - models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='item', to='poll.Item', - verbose_name='voted item')), - ('poll', - models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='poll.Poll', verbose_name='poll')), - ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, - to=settings.AUTH_USER_MODEL, verbose_name='user')), - ], - options={ - 'verbose_name': 'vote', - 'verbose_name_plural': 'votes', - }, - ), - migrations.AddField( - model_name='item', - name='poll', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='items', to='poll.Poll'), - ), - ] diff --git a/poll/migrations/0002_auto_20190423_0546.py b/poll/migrations/0002_auto_20190423_0546.py deleted file mode 100644 index f349fce..0000000 --- a/poll/migrations/0002_auto_20190423_0546.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 2.1.5 on 2019-04-23 05:46 - -import datetime - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('poll', '0001_initial'), - ] - - operations = [ - migrations.AlterField( - model_name='poll', - name='date', - field=models.DateTimeField(default=datetime.datetime.now, verbose_name='date'), - ), - ] diff --git a/poll/migrations/__init__.py b/poll/migrations/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/poll/models.py b/poll/models.py deleted file mode 100644 index 0839a28..0000000 --- a/poll/models.py +++ /dev/null @@ -1,90 +0,0 @@ -# -*- coding: utf-8 -*- - -from __future__ import unicode_literals - -import datetime - -from django.contrib.auth import get_user_model -from django.db import models -from django.db.models.manager import Manager -from django.utils.encoding import python_2_unicode_compatible -from django.utils.translation import gettext as _ - -User = get_user_model() - - -class PublishedManager(Manager): - def get_query_set(self): - return super(PublishedManager, self).get_query_set().filter(is_published=True) - - -@python_2_unicode_compatible -class Poll(models.Model): - title = models.CharField(max_length=250, verbose_name=_('question')) - date = models.DateTimeField(verbose_name=_('date'), default=datetime.datetime.now) - is_published = models.BooleanField(default=True, verbose_name=_('is published')) - - objects = models.Manager() - published = PublishedManager() - - class Meta: - ordering = ['-date'] - verbose_name = _('poll') - verbose_name_plural = _('polls') - - def __str__(self): - return self.title - - def get_vote_count(self): - return Vote.objects.filter(poll=self).count() - - vote_count = property(fget=get_vote_count) - - def get_cookie_name(self): - return 'poll_%s' % self.pk - - -@python_2_unicode_compatible -class Item(models.Model): - poll = models.ForeignKey(Poll, related_name='items', on_delete=models.CASCADE) - value = models.CharField(max_length=250, verbose_name=_('value')) - pos = models.SmallIntegerField(default='0', verbose_name=_('position')) - - class Meta: - verbose_name = _('answer') - verbose_name_plural = _('answers') - ordering = ['pos'] - - def __str__(self): - return u'%s' % (self.value,) - - def get_vote_count(self): - return Vote.objects.filter(item=self).count() - - vote_count = property(fget=get_vote_count) - - -@python_2_unicode_compatible -class Vote(models.Model): - poll = models.ForeignKey(Poll, on_delete=models.CASCADE, verbose_name=_('poll')) - item = models.ForeignKey(Item, related_name='item', on_delete=models.CASCADE, verbose_name=_('voted item')) - ip = models.GenericIPAddressField(verbose_name=_('user\'s IP')) - user = models.ForeignKey(User, on_delete=models.SET_NULL, blank=True, null=True, - verbose_name=_('user')) - datetime = models.DateTimeField(auto_now_add=True) - - class Meta: - verbose_name = _('vote') - verbose_name_plural = _('votes') - - def __str__(self): - User = get_user_model() - if isinstance(User, str): - User = get_user_model() - else: - User = get_user_model() - - if isinstance(self.user, User): - username_field = getattr(User, 'USERNAME_FIELD', 'username') - return getattr(User, username_field, '') - return self.ip diff --git a/poll/serializers.py b/poll/serializers.py deleted file mode 100644 index 3c55c75..0000000 --- a/poll/serializers.py +++ /dev/null @@ -1,42 +0,0 @@ -import pytz -from rest_framework import serializers - -from .models import Item -from .models import Poll -from .models import Vote - - -class ItemSerializer(serializers.ModelSerializer): - def create(self, validated_data): - return Item.objects.create(**validated_data) - - class Meta: - model = Item - fields = ('id', 'value', 'pos') - - -class PollSerializer(serializers.ModelSerializer): - items = ItemSerializer(instance=serializers.PrimaryKeyRelatedField(many=True, read_only=True), many=True) - - def create(self, validated_data): - return Poll.objects.create(**validated_data) - - def get_date(self, obj): - if obj.date is None: - return None - return obj.date.astimezone(pytz.timezone('US/Pacific')) - - class Meta: - model = Poll - fields = ('id', 'title', 'date', 'is_published', 'items') - - -class VoteSerializer(serializers.ModelSerializer): - item = ItemSerializer(read_only=True) - - def create(self, validated_data): - return Vote.objects.create(**validated_data) - - class Meta: - model = Vote - fields = ('id', 'item') diff --git a/poll/tests.py b/poll/tests.py deleted file mode 100644 index a39b155..0000000 --- a/poll/tests.py +++ /dev/null @@ -1 +0,0 @@ -# Create your tests here. diff --git a/poll/urls.py b/poll/urls.py deleted file mode 100644 index 7efc6d8..0000000 --- a/poll/urls.py +++ /dev/null @@ -1,13 +0,0 @@ -from django.urls import path -from rest_framework.urlpatterns import format_suffix_patterns - -from poll import views - -urlpatterns = [ - path('', views.polls), - path('/vote/', - views.vote), - path('/result/', - views.result), -] -urlpatterns = format_suffix_patterns(urlpatterns) diff --git a/poll/views.py b/poll/views.py deleted file mode 100644 index b430a0b..0000000 --- a/poll/views.py +++ /dev/null @@ -1,62 +0,0 @@ -from django.db.models import Q -from django.http import JsonResponse -from django.views.decorators.csrf import csrf_exempt -from rest_framework.decorators import api_view - -from utils.error_codes import ResponseCodes -from utils.generic_json_creator import create_response -from .models import Poll, Item, Vote -from .serializers import PollSerializer, VoteSerializer - - -@csrf_exempt -@api_view(["POST"]) -def vote(request, poll_pk): - try: - poll = Poll.objects.get(pk=poll_pk) - except: - return JsonResponse( - create_response(data=None, success=False, error_code=ResponseCodes.poll_answer_couldnt_found), safe=False) - - body = request.data - item_pk = body['item_id'] - if not item_pk: - return JsonResponse( - create_response(data=None, success=False, error_code=ResponseCodes.missing_item_id_parameter), safe=False) - - try: - item = Item.objects.get(pk=item_pk) - except: - return JsonResponse( - create_response(data=None, success=False, error_code=ResponseCodes.poll_answer_couldnt_found), safe=False) - - Vote.objects.create( - poll=poll, - ip=request.META['REMOTE_ADDR'], - user=request.user, - item=item, - ) - - return JsonResponse(create_response(data=None), safe=False) - - -@csrf_exempt -@api_view(["GET"]) -def polls(request): - poll = Poll.objects.filter(~Q(vote__user=request.user)) - list = PollSerializer(instance=poll, many=True).data - return JsonResponse(create_response(data=list), safe=False) - - -@csrf_exempt -@api_view(["GET"]) -def result(request, poll_pk): - try: - poll = Poll.objects.get(pk=poll_pk) - except Poll.DoesNotExists: - return JsonResponse( - create_response(data=None, success=False, error_code=ResponseCodes.poll_answer_couldnt_found), safe=False) - - votes = Vote.objects.filter(poll=poll) - - return JsonResponse(create_response(data=VoteSerializer(instance=votes, many=True).data), safe=False) diff --git a/position/migrations/0001_initial.py b/position/migrations/0001_initial.py index 14ace28..75f8755 100644 --- a/position/migrations/0001_initial.py +++ b/position/migrations/0001_initial.py @@ -1,9 +1,10 @@ -# Generated by Django 2.1.5 on 2019-04-22 23:09 +# Generated by Django 2.2 on 2019-10-03 23:52 from django.db import migrations, models class Migration(migrations.Migration): + initial = True dependencies = [ @@ -11,10 +12,13 @@ class Migration(migrations.Migration): operations = [ migrations.CreateModel( - name='JobApplication', + name='JobPosition', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('jobTitle', models.CharField(max_length=200, null=True)), + ('job_title', models.CharField(max_length=200)), ], + options={ + 'ordering': ['job_title'], + }, ), ] diff --git a/position/migrations/0002_auto_20190422_2320.py b/position/migrations/0002_auto_20190422_2320.py deleted file mode 100644 index 93ba8e3..0000000 --- a/position/migrations/0002_auto_20190422_2320.py +++ /dev/null @@ -1,21 +0,0 @@ -# Generated by Django 2.1.5 on 2019-04-22 23:20 - -from django.db import migrations - - -class Migration(migrations.Migration): - dependencies = [ - ('position', '0001_initial'), - ] - - operations = [ - migrations.RenameModel( - old_name='JobApplication', - new_name='JobPosition', - ), - migrations.RenameField( - model_name='jobposition', - old_name='jobTitle', - new_name='job_title', - ), - ] diff --git a/position/migrations/0002_positiondetail.py b/position/migrations/0002_positiondetail.py new file mode 100644 index 0000000..698917b --- /dev/null +++ b/position/migrations/0002_positiondetail.py @@ -0,0 +1,40 @@ +# Generated by Django 2.2.5 on 2019-11-07 01:22 + +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('utils', '0002_import_country_data_from_json'), + ('position', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='PositionDetail', + fields=[ + ('id', models.AutoField(auto_created=True, + primary_key=True, serialize=False, verbose_name='ID')), + ('responsibilities', models.TextField()), + ('requirements', models.TextField()), + ('department', models.CharField(max_length=200)), + ('job_type', models.CharField(max_length=200)), + ('city', models.CharField(max_length=200)), + ('is_deleted', models.BooleanField(default=False)), + ('created_date', models.DateTimeField( + default=django.utils.timezone.now, null=True)), + ('updated_date', models.DateTimeField(null=True)), + ('company', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, + related_name='positiondetail_company', to='company.Company')), + ('country', models.ForeignKey( + null=True, on_delete=django.db.models.deletion.SET_NULL, to='utils.Country')), + ('job', models.ForeignKey( + null=True, on_delete=django.db.models.deletion.SET_NULL, to='position.JobPosition')), + ('state', models.ForeignKey( + null=True, on_delete=django.db.models.deletion.SET_NULL, to='utils.State')), + ], + ), + ] diff --git a/position/migrations/0003_auto_20190510_2037.py b/position/migrations/0003_auto_20190510_2037.py deleted file mode 100644 index 0bf85c7..0000000 --- a/position/migrations/0003_auto_20190510_2037.py +++ /dev/null @@ -1,16 +0,0 @@ -# Generated by Django 2.2 on 2019-05-10 20:37 - -from django.db import migrations - - -class Migration(migrations.Migration): - dependencies = [ - ('position', '0002_auto_20190422_2320'), - ] - - operations = [ - migrations.AlterModelOptions( - name='jobposition', - options={'ordering': ['job_title']}, - ), - ] diff --git a/position/migrations/0003_auto_20191115_2023.py b/position/migrations/0003_auto_20191115_2023.py new file mode 100644 index 0000000..b8ff829 --- /dev/null +++ b/position/migrations/0003_auto_20191115_2023.py @@ -0,0 +1,23 @@ +# Generated by Django 2.2.5 on 2019-11-16 04:23 + +from django.db import migrations, models +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('position', '0002_positiondetail'), + ] + + operations = [ + migrations.AlterModelOptions( + name='positiondetail', + options={'ordering': ['updated_date']}, + ), + migrations.AlterField( + model_name='positiondetail', + name='updated_date', + field=models.DateTimeField(default=django.utils.timezone.now, null=True), + ), + ] diff --git a/position/migrations/0004_auto_20190924_1146.py b/position/migrations/0004_auto_20190924_1146.py deleted file mode 100644 index fada3ae..0000000 --- a/position/migrations/0004_auto_20190924_1146.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 2.2 on 2019-09-24 18:46 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('position', '0003_auto_20190510_2037'), - ] - - operations = [ - migrations.AlterField( - model_name='jobposition', - name='job_title', - field=models.CharField(default=111, max_length=200), - preserve_default=False, - ), - ] diff --git a/position/models.py b/position/models.py index 11bb1db..74adeaa 100644 --- a/position/models.py +++ b/position/models.py @@ -1,4 +1,8 @@ from django.db import models +from django.utils import timezone +from utils.models import Country +from utils.models import State +from company.models import Company class JobPosition(models.Model): @@ -9,3 +13,27 @@ class Meta: def __str__(self): return self.job_title if self.job_title is not None else '' + + +class PositionDetail(models.Model): + job = models.ForeignKey( + JobPosition, on_delete=models.SET_NULL, null=True, blank=False) + responsibilities = models.TextField(blank=False) + requirements = models.TextField(blank=False) + department = models.CharField(max_length=200, blank=False) + job_type = models.CharField(max_length=200, blank=False) + city = models.CharField(max_length=200, blank=False) + country = models.ForeignKey( + Country, on_delete=models.SET_NULL, null=True, blank=False) + state = models.ForeignKey( + State, on_delete=models.SET_NULL, null=True, blank=False) + company = models.ForeignKey( + Company, on_delete=models.SET_NULL, null=True, related_name='%(class)s_company', blank=False) + is_deleted = models.BooleanField(default=False) + created_date = models.DateTimeField( + default=timezone.now, null=True, blank=False) + updated_date = models.DateTimeField( + default=timezone.now, null=True, blank=False) + + class Meta: + ordering = ['updated_date'] diff --git a/position/serializers.py b/position/serializers.py index 33680e2..c0e3519 100644 --- a/position/serializers.py +++ b/position/serializers.py @@ -1,6 +1,7 @@ from rest_framework import serializers -from .models import JobPosition +from .models import JobPosition, PositionDetail +from utils.serializers import StateSerializer, CountrySerializer class JobPositionSerializer(serializers.ModelSerializer): @@ -10,3 +11,16 @@ def create(self, validated_data): class Meta: model = JobPosition fields = ('__all__') + + +class PositionDetailSerializer(serializers.ModelSerializer): + job = JobPositionSerializer(many=False, read_only=True) + state = StateSerializer(many=False, read_only=True) + country = CountrySerializer(many=False, read_only=True) + + def create(self, validated_data): + return PositionDetail.objects.create(**validated_data) + + class Meta: + model = PositionDetail + fields = ('__all__') diff --git a/position/urls.py b/position/urls.py index b5354c0..b70cdc6 100644 --- a/position/urls.py +++ b/position/urls.py @@ -5,5 +5,6 @@ urlpatterns = [ path('', views.positions), + path('company', views.company_positions) ] urlpatterns = format_suffix_patterns(urlpatterns) diff --git a/position/views.py b/position/views.py index 3cf6f98..3d1eb09 100644 --- a/position/views.py +++ b/position/views.py @@ -3,21 +3,108 @@ from rest_framework.decorators import api_view from utils.generic_json_creator import create_response -from .models import JobPosition -from .serializers import JobPositionSerializer +from .models import JobPosition, PositionDetail +from .serializers import JobPositionSerializer, PositionDetailSerializer +from utils.models import Country, State +from company.utils import get_or_create_company +from company.models import Company +from JH_RestAPI import pagination @csrf_exempt @api_view(["GET"]) def positions(request): - q = request.GET.get('q') - if q is None: - positions = JobPosition.objects.all() - else: - positions = JobPosition.objects.filter(job_title__icontains=q) - if request.GET.get('count') is not None: - cnt = int(request.GET.get('count')) - positions = positions[:cnt] - serialized_positions = JobPositionSerializer( - instance=positions, many=True).data - return JsonResponse(create_response(data=serialized_positions, paginator=None), safe=False) + body = request.data + if request.method == "GET": + q = request.GET.get('q') + if q is None: + positions = JobPosition.objects.all() + else: + positions = JobPosition.objects.filter(job_title__icontains=q) + if request.GET.get('count') is not None: + cnt = int(request.GET.get('count')) + positions = positions[:cnt] + serialized_positions = JobPositionSerializer( + instance=positions, many=True).data + return JsonResponse(create_response(data=serialized_positions, paginator=None), safe=False) + + +@csrf_exempt +@api_view(["GET", "POST", "PATCH", "DELETE"]) +def company_positions(request): + body = request.data + if request.method == "GET": + company_id = request.GET.get('id') + q = request.GET.get('q') + department = request.GET.get('department') + job_type = request.GET.get('type') + if q is not None: + jobs = JobPosition.objects.filter(job_title__icontains=q) + positions = PositionDetail.objects.filter( + company_id=company_id, is_deleted=False, job__in=jobs).order_by("-updated_date") + else: + positions = PositionDetail.objects.filter( + company_id=company_id, is_deleted=False).order_by("-updated_date") + if department is not None: + positions = positions.filter(department=department) + if job_type is not None: + positions = positions.filter(job_type=job_type) + paginator = pagination.CustomPagination() + positions = paginator.paginate_queryset(positions, request) + serialized_positions = PositionDetailSerializer( + instance=positions, many=True).data + return JsonResponse(create_response(data=serialized_positions, paginator=paginator), safe=False) + elif request.method == "POST": + job_title = body["job_title"] + responsibilities = body["responsibilities"] + requirements = body["requirements"] + department = body["department"] + job_type = body["job_type"] + city = body["city"] + company_id = int(body["company_id"]) + job = JobPosition.objects.get(job_title=job_title) + state = State.objects.get(pk=body["state_id"]) + country = Country.objects.get(pk=body["country_id"]) + company = Company.objects.get(pk=body["company_id"]) + + new_position = PositionDetail(job=job, responsibilities=responsibilities, requirements=requirements, + department=department, job_type=job_type, city=city, country=country, state=state, company=company) + new_position.save() + return JsonResponse( + create_response( + data=PositionDetailSerializer(instance=new_position, many=False, context={'user': request.user}).data), + safe=False) + elif request.method == "DELETE": + position_id = body["position_id"] + position = PositionDetail.objects.get(pk=position_id) + position.is_deleted = True + position.save() + return JsonResponse(create_response(data=None), safe=False) + elif request.method == "PATCH": + position_id = body["position_id"] + position = PositionDetail.objects.get(pk=position_id) + responsibilities = body.get('responsibilities') + requirements = body.get('requirements') + department = body.get('department') + job_type = body.get('job_type') + city = body.get('city') + state_id = body.get('state_id') + country_id = body.get('country_id') + + if responsibilities is not None: + position.responsibilities = responsibilities + if requirements is not None: + position.requirements = requirements + if department is not None: + position.department = department + if job_type is not None: + position.job_type = job_type + if city is not None: + position.city = city + if state_id is not None: + position.state_id = state_id + if country_id is not None: + position.country_id = country_id + + position.save() + return JsonResponse(create_response(data=PositionDetailSerializer(instance=position, many=False, context={'user': request.user}).data), safe=False) diff --git a/blog/__init__.py b/positionapps/__init__.py similarity index 100% rename from blog/__init__.py rename to positionapps/__init__.py diff --git a/positionapps/admin.py b/positionapps/admin.py new file mode 100644 index 0000000..4ad95e8 --- /dev/null +++ b/positionapps/admin.py @@ -0,0 +1,30 @@ +from django.contrib import admin + +from utils.export_csv import ExportCsv +from .models import PositionApplication, ApplicationStatus, Contact, Feedback + + +# Register your models here. +@admin.register(PositionApplication) +class PositionApplicationAdmin(admin.ModelAdmin, ExportCsv): + list_display = ("user", "first_name", "last_name", "application_status", "position", + 'company_object', 'is_deleted', 'apply_date') + list_filter = ("user", "application_status", "position", + 'company_object', 'apply_date') + actions = ["export_as_csv"] + + +@admin.register(ApplicationStatus) +class ApplicationStatusAdmin(admin.ModelAdmin): + list_display = ("value", "pos", "rejectable", "default") + + +@admin.register(Contact) +class ContactAdmin(admin.ModelAdmin): + list_display = ("id", "created_date", "updated_date") + + +@admin.register(Feedback) +class FeedbackAdmin(admin.ModelAdmin): + list_display = ("id", "interviewer", "rate", "description", + "interview_date", "created_date", "updated_date") diff --git a/jobapps/apps.py b/positionapps/apps.py similarity index 72% rename from jobapps/apps.py rename to positionapps/apps.py index 9fafbee..e44c5c3 100644 --- a/jobapps/apps.py +++ b/positionapps/apps.py @@ -2,4 +2,4 @@ class JobappsConfig(AppConfig): - name = 'jobapps' + name = 'positionapps' diff --git a/positionapps/migrations/0001_initial.py b/positionapps/migrations/0001_initial.py new file mode 100644 index 0000000..85370ac --- /dev/null +++ b/positionapps/migrations/0001_initial.py @@ -0,0 +1,112 @@ +# Generated by Django 2.2 on 2019-10-09 18:19 + +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 = [ + ('position', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='ApplicationStatus', + fields=[ + ('id', models.AutoField(auto_created=True, + primary_key=True, serialize=False, verbose_name='ID')), + ('value', models.CharField(max_length=20)), + ('icon', models.FileField(blank=True, null=True, upload_to='')), + ('pos', models.SmallIntegerField( + default='0', verbose_name='position')), + ('rejectable', models.BooleanField(default=True)), + ('default', models.BooleanField(default=False)), + ], + options={ + 'verbose_name': 'status', + 'verbose_name_plural': 'statuses', + 'ordering': ['pos'], + }, + ), + migrations.CreateModel( + name='PositionApplication', + fields=[ + ('id', models.AutoField(auto_created=True, + primary_key=True, serialize=False, verbose_name='ID')), + ('first_name', models.CharField( + blank=True, max_length=50, null=True)), + ('last_name', models.CharField(blank=True, max_length=50, null=True)), + ('user', models.ForeignKey( + blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ('apply_date', models.DateTimeField(blank=True)), + ('rejected_date', models.DateTimeField(blank=True, null=True)), + ('deleted_date', models.DateTimeField(blank=True, null=True)), + ('is_rejected', models.BooleanField(default=False)), + ('is_deleted', models.BooleanField(default=False)), + ('application_status', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, + related_name='positionapplication_application_status', to='positionapps.ApplicationStatus')), + ('company_object', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, + related_name='positionapplication_company', to='company.Company')), + ('position', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, + related_name='positionapplication_position', to='position.JobPosition')), + ('created_date', models.DateTimeField( + blank=True, default=django.utils.timezone.now, null=True)), + ('updated_date', models.DateTimeField(blank=True, null=True)), + ], + ), + migrations.CreateModel( + name='StatusHistory', + fields=[ + ('id', models.AutoField(auto_created=True, + primary_key=True, serialize=False, verbose_name='ID')), + ('updated_date', models.DateTimeField( + blank=True, default=django.utils.timezone.now)), + ('application_status', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, + related_name='statushistory_application_status', to='positionapps.ApplicationStatus')), + ('pos_app', models.ForeignKey(blank=True, null=True, + on_delete=django.db.models.deletion.CASCADE, to='positionapps.PositionApplication')), + ], + ), + migrations.CreateModel( + name='Contact', + fields=[ + ('id', models.AutoField(auto_created=True, + primary_key=True, serialize=False, verbose_name='ID')), + ('email', models.CharField(blank=True, max_length=150, null=True)), + ('phone_number', models.CharField(blank=True, max_length=17, null=True, validators=[django.core.validators.RegexValidator( + message="Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed.", regex='^\\+?1?\\d{9,15}$')])), + ('linkedin_url', models.CharField( + blank=True, max_length=100, null=True)), + ('description', models.TextField(blank=True, null=True)), + ('created_date', models.DateTimeField( + blank=True, default=django.utils.timezone.now)), + ('updated_date', models.DateTimeField( + blank=True, default=django.utils.timezone.now, null=True)), + ('company', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, + related_name='contact_company', to='company.Company')), + ('pos_app', models.ForeignKey( + blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='positionapps.PositionApplication')), + ('position', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, + related_name='contact_position', to='position.JobPosition')) + ], + ), + migrations.CreateModel( + name='PositionApplicationNote', + fields=[ + ('id', models.AutoField(auto_created=True, + primary_key=True, serialize=False, verbose_name='ID')), + ('description', models.TextField(blank=True, null=True)), + ('created_date', models.DateTimeField( + blank=True, default=django.utils.timezone.now)), + ('updated_date', models.DateTimeField( + blank=True, default=django.utils.timezone.now, null=True)), + ('pos_app', models.ForeignKey(blank=True, null=True, + on_delete=django.db.models.deletion.CASCADE, to='positionapps.PositionApplication')), + ], + ) + ] diff --git a/positionapps/migrations/0002_auto_20191123_1232.py b/positionapps/migrations/0002_auto_20191123_1232.py new file mode 100644 index 0000000..9394dff --- /dev/null +++ b/positionapps/migrations/0002_auto_20191123_1232.py @@ -0,0 +1,28 @@ +# Generated by Django 2.2.5 on 2019-11-23 20:32 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('positionapps', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='contact', + name='position', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='contact_position', to='position.PositionDetail'), + ), + migrations.RemoveField( + model_name='positionapplication', + name='position', + ), + migrations.AddField( + model_name='positionapplication', + name='position', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='positionapplication_position', to='position.PositionDetail'), + ), + ] diff --git a/positionapps/migrations/0003_feedback.py b/positionapps/migrations/0003_feedback.py new file mode 100644 index 0000000..d214359 --- /dev/null +++ b/positionapps/migrations/0003_feedback.py @@ -0,0 +1,29 @@ +# Generated by Django 2.2.5 on 2019-11-26 03:18 + +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('positionapps', '0002_auto_20191123_1232'), + ] + + operations = [ + migrations.CreateModel( + name='Feedback', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('interviewer', models.CharField(blank=True, max_length=50, null=True)), + ('interview_round', models.CharField(blank=True, max_length=50, null=True)), + ('rate', models.IntegerField(blank=True, null=True)), + ('description', models.TextField(blank=True, null=True)), + ('interview_date', models.DateTimeField(blank=True, null=True)), + ('created_date', models.DateTimeField(blank=True, default=django.utils.timezone.now)), + ('updated_date', models.DateTimeField(blank=True, default=django.utils.timezone.now, null=True)), + ('pos_app', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='positionapps.PositionApplication')), + ], + ), + ] diff --git a/blog/migrations/__init__.py b/positionapps/migrations/__init__.py similarity index 100% rename from blog/migrations/__init__.py rename to positionapps/migrations/__init__.py diff --git a/jobapps/models.py b/positionapps/models.py similarity index 53% rename from jobapps/models.py rename to positionapps/models.py index 666e8fe..3da582a 100644 --- a/jobapps/models.py +++ b/positionapps/models.py @@ -1,4 +1,4 @@ -from datetime import datetime +from django.utils import timezone from django.contrib.auth import get_user_model from django.core.validators import RegexValidator @@ -6,7 +6,7 @@ from django.utils.translation import gettext as _ from company.models import Company -from position.models import JobPosition +from position.models import PositionDetail User = get_user_model() @@ -28,81 +28,47 @@ def __str__(self): return self.value if self.value is not None else '' -class Source(models.Model): - value = models.CharField(max_length=20) - gmail_key = models.CharField(max_length=100, blank=True) - system = models.BooleanField(default=False) - image = models.CharField(null=True, max_length=200, blank=True) - - class Meta: - ordering = ['value'] - - def __str__(self): - return self.value if self.value is not None else '' - - -class JobApplication(models.Model): +class PositionApplication(models.Model): user = models.ForeignKey( User, on_delete=models.CASCADE, null=True, blank=True) application_status = models.ForeignKey( ApplicationStatus, on_delete=models.SET_NULL, null=True, blank=True, related_name='%(class)s_application_status') position = models.ForeignKey( - JobPosition, on_delete=models.SET_NULL, null=True, related_name='%(class)s_position') + PositionDetail, on_delete=models.SET_NULL, null=True, related_name='%(class)s_position') company_object = models.ForeignKey( Company, on_delete=models.SET_NULL, null=True, related_name='%(class)s_company') + first_name = models.CharField(max_length=50, null=True, blank=True) + last_name = models.CharField(max_length=50, null=True, blank=True) apply_date = models.DateTimeField(blank=True) - msg_id = models.CharField(max_length=200) - app_source = models.ForeignKey( - Source, on_delete=models.SET_NULL, null=True, related_name='%(class)s_source') rejected_date = models.DateTimeField(null=True, blank=True) deleted_date = models.DateTimeField(null=True, blank=True) - created = models.DateTimeField(default=datetime.now, null=True, blank=True) - updated_date = models.DateTimeField(null=True, blank=True) is_rejected = models.BooleanField(default=False) is_deleted = models.BooleanField(default=False) + created_date = models.DateTimeField( + default=timezone.now, null=True, blank=True) + updated_date = models.DateTimeField(null=True, blank=True) class StatusHistory(models.Model): - job_post = models.ForeignKey( - JobApplication, on_delete=models.CASCADE, null=True, blank=True) + pos_app = models.ForeignKey( + PositionApplication, on_delete=models.CASCADE, null=True, blank=True) application_status = models.ForeignKey( ApplicationStatus, on_delete=models.SET_NULL, null=True, blank=True, related_name='%(class)s_application_status') - update_date = models.DateTimeField(default=datetime.now, blank=True) + updated_date = models.DateTimeField(default=timezone.now, blank=True) -class GoogleMail(models.Model): - user = models.ForeignKey(User, on_delete=models.CASCADE, null=False, blank=True) - job_post = models.ForeignKey( - JobApplication, on_delete=models.CASCADE, null=True, blank=True) - app_source = models.ForeignKey( - Source, on_delete=models.SET_NULL, null=True, related_name='%(class)s_source') - subject = models.CharField(max_length=200) - body = models.TextField(null=True, blank=True) - date = models.CharField(max_length=50) - msg_id = models.CharField(max_length=200, null=True) - - -class JobApplicationNote(models.Model): - job_post = models.ForeignKey( - JobApplication, on_delete=models.CASCADE, null=True, blank=True) +class PositionApplicationNote(models.Model): + pos_app = models.ForeignKey( + PositionApplication, on_delete=models.CASCADE, null=True, blank=True) description = models.TextField(null=True, blank=True) - created_date = models.DateTimeField(default=datetime.now, blank=True) - update_date = models.DateTimeField( - default=datetime.now, null=True, blank=True) - - -class SourceType(models.Model): - value = models.CharField(max_length=20, null=False) - - def __str__(self): - return self.value if self.value is not None else '' + created_date = models.DateTimeField(default=timezone.now, blank=True) + updated_date = models.DateTimeField( + default=timezone.now, null=True, blank=True) class Contact(models.Model): - job_post = models.ForeignKey( - JobApplication, on_delete=models.CASCADE, null=True, blank=True) - first_name = models.CharField(max_length=50, null=True, blank=True) - last_name = models.CharField(max_length=50, null=True, blank=True) + pos_app = models.ForeignKey( + PositionApplication, on_delete=models.CASCADE, null=True, blank=True) email = models.CharField(max_length=150, null=True, blank=True) phone_regex = RegexValidator( regex=r'^\+?1?\d{9,15}$', @@ -111,10 +77,23 @@ class Contact(models.Model): validators=[phone_regex], max_length=17, blank=True, null=True) # validators should be a list linkedin_url = models.CharField(max_length=100, blank=True, null=True) position = models.ForeignKey( - JobPosition, on_delete=models.SET_NULL, null=True, related_name='%(class)s_position') + PositionDetail, on_delete=models.SET_NULL, null=True, related_name='%(class)s_position') company = models.ForeignKey( Company, on_delete=models.SET_NULL, null=True, related_name='%(class)s_company') description = models.TextField(null=True, blank=True) - created_date = models.DateTimeField(default=datetime.now, blank=True) - update_date = models.DateTimeField( - default=datetime.now, null=True, blank=True) + created_date = models.DateTimeField(default=timezone.now, blank=True) + updated_date = models.DateTimeField( + default=timezone.now, null=True, blank=True) + + +class Feedback(models.Model): + pos_app = models.ForeignKey( + PositionApplication, on_delete=models.CASCADE, null=True, blank=True) + interviewer = models.CharField(max_length=50, null=True, blank=True) + interview_round = models.CharField(max_length=50, null=True, blank=True) + rate = models.IntegerField(null=True, blank=True) + description = models.TextField(null=True, blank=True) + interview_date = models.DateTimeField(null=True, blank=True) + created_date = models.DateTimeField(default=timezone.now, blank=True) + updated_date = models.DateTimeField( + default=timezone.now, null=True, blank=True) diff --git a/jobapps/serializers.py b/positionapps/serializers.py similarity index 51% rename from jobapps/serializers.py rename to positionapps/serializers.py index 910d567..84c26c4 100644 --- a/jobapps/serializers.py +++ b/positionapps/serializers.py @@ -2,13 +2,13 @@ from rest_framework import serializers from company.serializers import CompanySerializer -from position.serializers import JobPositionSerializer +from position.serializers import PositionDetailSerializer from .models import ApplicationStatus -from .models import GoogleMail -from .models import JobApplication -from .models import JobApplicationNote, SourceType -from .models import Source, Contact +from .models import PositionApplication +from .models import PositionApplicationNote +from .models import Contact from .models import StatusHistory +from .models import Feedback class ApplicationStatusSerializer(serializers.ModelSerializer): @@ -20,44 +20,10 @@ class Meta: fields = ('__all__') -class SourceTypeSerializer(serializers.ModelSerializer): - def create(self, validated_data): - return SourceType.objects.create(**validated_data) - - class Meta: - model = SourceType - fields = ('__all__') - - -class GoogleMailSerializer(serializers.ModelSerializer): - def create(self, validated_data): - return GoogleMail.objects.create(**validated_data) - - class Meta: - model = GoogleMail - fields = ('subject', 'body', 'date') - - -class SourceSerializer(serializers.ModelSerializer): - def create(self, validated_data): - return Source.objects.create(**validated_data) - - class Meta: - model = Source - fields = ('id', 'value', 'image') - - -class JobApplicationSerializer(serializers.ModelSerializer): +class PositionApplicationSerializer(serializers.ModelSerializer): application_status = ApplicationStatusSerializer(read_only=True) - position = JobPositionSerializer(read_only=True) + position = PositionDetailSerializer(read_only=True) company_object = serializers.SerializerMethodField() - app_source = SourceSerializer(read_only=True) - editable = serializers.SerializerMethodField() - - def get_editable(self, obj): - if obj.msg_id is not None and obj.msg_id != '': - return False - return True def get_company_object(self, obj): context = self.context @@ -65,34 +31,34 @@ def get_company_object(self, obj): return CompanySerializer(instance=obj.company_object, many=False, context=context).data def create(self, validated_data): - return JobApplication.objects.create(**validated_data) + return PositionApplication.objects.create(**validated_data) class Meta: - model = JobApplication + model = PositionApplication fields = ( - 'id', 'editable', 'application_status', 'position', 'company_object', 'apply_date', 'app_source', 'is_rejected') + 'id', 'first_name', 'last_name', 'application_status', 'position', 'company_object', 'apply_date', 'is_rejected') -class JobApplicationNoteSerializer(serializers.ModelSerializer): +class PositionApplicationNoteSerializer(serializers.ModelSerializer): created_date = serializers.SerializerMethodField() - update_date = serializers.SerializerMethodField() + updated_date = serializers.SerializerMethodField() def get_created_date(self, obj): if obj.created_date is None: return None return obj.created_date.astimezone(pytz.timezone('US/Pacific')) - def get_update_date(self, obj): - if obj.update_date is None: + def get_updated_date(self, obj): + if obj.updated_date is None: return None - return obj.update_date.astimezone(pytz.timezone('US/Pacific')) + return obj.updated_date.astimezone(pytz.timezone('US/Pacific')) def create(self, validated_data): - return JobApplicationNote.objects.create(**validated_data) + return PositionApplication.objects.create(**validated_data) class Meta: - model = JobApplicationNote - fields = ('id', 'description', 'created_date', 'update_date') + model = PositionApplicationNote + fields = ('id', 'description', 'created_date', 'updated_date') class StatusHistorySerializer(serializers.ModelSerializer): @@ -103,7 +69,7 @@ def create(self, validated_data): class Meta: model = StatusHistory - fields = ('application_status', 'update_date') + fields = ('application_status', 'updated_date') class ContactSerializer(serializers.ModelSerializer): @@ -126,5 +92,14 @@ def create(self, validated_data): class Meta: model = Contact fields = ( - 'id', 'first_name', 'last_name', 'phone_number', 'linkedin_url', 'description', 'created_date', 'update_date', 'position', + 'id', 'phone_number', 'linkedin_url', 'description', 'created_date', 'updated_date', 'position', 'company', 'email') + + +class FeedbackSerializer(serializers.ModelSerializer): + def create(self, validated_data): + return Feedback.objects.create(**validated_data) + + class Meta: + model = Feedback + fields = ('__all__') diff --git a/alumni/tests.py b/positionapps/tests.py similarity index 100% rename from alumni/tests.py rename to positionapps/tests.py diff --git a/positionapps/urls.py b/positionapps/urls.py new file mode 100644 index 0000000..5aefd0c --- /dev/null +++ b/positionapps/urls.py @@ -0,0 +1,14 @@ +from django.urls import path +from rest_framework.urlpatterns import format_suffix_patterns + +from positionapps import views + +urlpatterns = [ + path('statuses/', views.statuses), + path('', views.position_applications), + path('/statusHistory/', views.status_history), + path('/notes/', views.notes), + path('/contacts/', views.contacts), + path('/feedbacks/', views.feedbacks), +] +urlpatterns = format_suffix_patterns(urlpatterns) diff --git a/jobapps/views.py b/positionapps/views.py similarity index 62% rename from jobapps/views.py rename to positionapps/views.py index 000ce34..c086495 100644 --- a/jobapps/views.py +++ b/positionapps/views.py @@ -1,4 +1,5 @@ -from datetime import datetime +from datetime import datetime as dt +from django.utils import timezone from django.contrib.auth import get_user_model from django.http import JsonResponse @@ -7,25 +8,23 @@ from company.utils import get_or_create_company from position.utils import get_or_insert_position +from position.models import PositionDetail from utils import utils from utils.error_codes import ResponseCodes from utils.generic_json_creator import create_response -from .models import JobApplication, Contact, ApplicationStatus, StatusHistory -from .models import JobApplicationNote -from .models import Source -from alumni.serializers import AlumniSerializer +from .models import PositionApplication, Contact, ApplicationStatus, StatusHistory, Feedback, PositionApplicationNote from .serializers import ApplicationStatusSerializer -from .serializers import JobApplicationNoteSerializer -from .serializers import JobApplicationSerializer, ContactSerializer -from .serializers import SourceSerializer +from .serializers import PositionApplicationNoteSerializer +from .serializers import PositionApplicationSerializer, ContactSerializer from .serializers import StatusHistorySerializer +from .serializers import FeedbackSerializer User = get_user_model() @csrf_exempt @api_view(["GET", "POST", "PUT", "PATCH", "DELETE"]) -def job_applications(request): +def position_applications(request): body = request.data if 'recaptcha_token' in body and utils.verify_recaptcha(None, body['recaptcha_token'], 'add_job') == ResponseCodes.verify_recaptcha_failed: @@ -38,44 +37,43 @@ def job_applications(request): if timestamp is None: return JsonResponse(create_response(data=None, success=False, error_code=ResponseCodes.invalid_parameters)) profile = request.user - time = datetime.fromtimestamp(int(timestamp)) - user_job_apps = JobApplication.objects.filter(created__gte=time) - job_application_list = JobApplicationSerializer(instance=user_job_apps, many=True, context={ + time = dt.fromtimestamp(int(timestamp)) + user_job_apps = PositionApplication.objects.filter( + created_date__gte=time) + job_application_list = PositionApplicationSerializer(instance=user_job_apps, many=True, context={ 'user': request.user}).data - response = {'data': job_application_list, 'synching': profile.synching} + response = {'data': job_application_list, + 'synching': profile.synching} return JsonResponse(create_response(data=response), safe=False) status_id = request.GET.get('status_id') if status_id is not None: - user_job_apps = JobApplication.objects.filter( + user_job_apps = PositionApplication.objects.filter( application_status__id=status_id, user__id=request.user.id, is_deleted=False).order_by('-apply_date') else: - user_job_apps = JobApplication.objects.filter( + user_job_apps = PositionApplication.objects.filter( user_id=request.user.id, is_deleted=False).order_by('-apply_date') - job_applications_list = JobApplicationSerializer(instance=user_job_apps, many=True, context={ + job_applications_list = PositionApplicationSerializer(instance=user_job_apps, many=True, context={ 'user': request.user}).data return JsonResponse(create_response(data=job_applications_list), safe=False) elif request.method == "POST": - job_title = body['job_title'] + position_id = body['position_id'] company = body['company'] application_date = body['application_date'] status = int(body['status_id']) - source = body['source'] + first_name = body['first_name'] + last_name = body['last_name'] - jt = get_or_insert_position(job_title) + jt = PositionDetail.objects.get(pk=position_id) jc = get_or_create_company(company) - if Source.objects.filter(value__iexact=source).count() == 0: - source = Source.objects.create(value=source) - else: - source = Source.objects.get(value__iexact=source) - - job_application = JobApplication(position=jt, company_object=jc, apply_date=application_date, - msg_id='', app_source=source, user=request.user) - job_application.application_status = ApplicationStatus.objects.get(pk=status) + job_application = PositionApplication( + position=jt, company_object=jc, first_name=first_name, last_name=last_name, apply_date=application_date, user=request.user) + job_application.application_status = ApplicationStatus.objects.get( + pk=status) job_application.save() return JsonResponse( create_response( - data=JobApplicationSerializer(instance=job_application, many=False, context={'user': request.user}).data), + data=PositionApplicationSerializer(instance=job_application, many=False, context={'user': request.user}).data), safe=False) elif request.method == "PUT": status_id = body.get('status_id') @@ -90,7 +88,8 @@ def job_applications(request): elif rejected is None and status_id is None: return JsonResponse(create_response(success=False, error_code=ResponseCodes.record_not_found), safe=False) else: - user_job_apps = JobApplication.objects.filter(pk__in=job_application_ids) + user_job_apps = PositionApplication.objects.filter( + pk__in=job_application_ids) if user_job_apps.count() == 0: return JsonResponse(create_response(success=False, error_code=ResponseCodes.record_not_found), safe=False) else: @@ -99,7 +98,8 @@ def job_applications(request): if status_id is None: user_job_app.is_rejected = rejected else: - new_status = ApplicationStatus.objects.filter(pk=status_id) + new_status = ApplicationStatus.objects.filter( + pk=status_id) if new_status.count() == 0: return JsonResponse( create_response(data=None, success=False, @@ -112,11 +112,11 @@ def job_applications(request): user_job_app.application_status = new_status[0] user_job_app.is_rejected = rejected status_history = StatusHistory( - job_post=user_job_app, application_status=new_status[0]) + pos_app=user_job_app, application_status=new_status[0]) status_history.save() if rejected is not None: - user_job_app.rejected_date = datetime.now() - user_job_app.updated_date = datetime.now() + user_job_app.rejected_date = timezone.now() + user_job_app.updated_date = timezone.now() user_job_app.save() return JsonResponse(create_response(data=None), safe=False) elif request.method == "PATCH": @@ -124,14 +124,11 @@ def job_applications(request): if job_app_id is None: return JsonResponse(create_response(data=None, success=False, error_code=ResponseCodes.record_not_found), safe=False) - user_job_app = JobApplication.objects.get(pk=job_app_id) + user_job_app = PositionApplication.objects.get(pk=job_app_id) if user_job_app.user != request.user: return JsonResponse(create_response(data=None, success=False, error_code=ResponseCodes.record_not_found), safe=False) - if user_job_app.msg_id is not None and user_job_app.msg_id != '': - return JsonResponse(create_response(data=None, success=False, error_code=ResponseCodes.record_not_found), - safe=False) job_title = body.get('job_title') company = body.get('company') @@ -144,16 +141,10 @@ def job_applications(request): user_job_app.position = get_or_insert_position(job_title) if company is not None: user_job_app.company_object = get_or_create_company(company) - if source is not None: - if Source.objects.filter(value__iexact=source).count() == 0: - source = Source.objects.create(value=source) - else: - source = Source.objects.get(value__iexact=source) - user_job_app.app_source = source - user_job_app.updated_date = datetime.now() + user_job_app.updated_date = timezone.now() user_job_app.save() return JsonResponse(create_response( - data=JobApplicationSerializer(instance=user_job_app, many=False, context={'user': request.user}).data), + data=PositionApplicationSerializer(instance=user_job_app, many=False, context={'user': request.user}).data), safe=False) elif request.method == "DELETE": job_application_ids = [] @@ -161,13 +152,14 @@ def job_applications(request): job_application_ids = body['jobapp_ids'] if 'jobapp_id' in body: job_application_ids.append(body['jobapp_id']) - if len(job_application_ids) == 0 or JobApplication.objects.filter(pk__in=job_application_ids).count() == 0: + if len(job_application_ids) == 0 or PositionApplication.objects.filter(pk__in=job_application_ids).count() == 0: return JsonResponse(create_response(success=False, error_code=ResponseCodes.record_not_found), safe=False) else: - user_job_apps = JobApplication.objects.filter(pk__in=job_application_ids) + user_job_apps = PositionApplication.objects.filter( + pk__in=job_application_ids) for user_job_app in user_job_apps: if user_job_app.user == request.user: - user_job_app.deleted_date = datetime.now() + user_job_app.deleted_date = timezone.now() user_job_app.is_deleted = True user_job_app.save() return JsonResponse(create_response(data=None), safe=False) @@ -177,60 +169,49 @@ def job_applications(request): @api_view(["GET"]) def statuses(request): statuses_list = ApplicationStatus.objects.all() - statuses_list = ApplicationStatusSerializer(instance=statuses_list, many=True).data + statuses_list = ApplicationStatusSerializer( + instance=statuses_list, many=True).data return JsonResponse(create_response(data=statuses_list), safe=False) @csrf_exempt @api_view(["GET"]) -def sources(request): - source_list = SourceSerializer(instance=Source.objects.all(), many=True).data - return JsonResponse(create_response(data=source_list), safe=False) - - -@csrf_exempt -@api_view(["GET"]) -def status_history(request, job_app_pk): - if job_app_pk is None: +def status_history(request, pos_app_pk): + if pos_app_pk is None: return JsonResponse(create_response(data=None, success=False, error_code=ResponseCodes.invalid_parameters), safe=False) else: - statuses_list = StatusHistory.objects.filter(job_post__pk=job_app_pk) - statuses_list = StatusHistorySerializer(instance=statuses_list, many=True).data + statuses_list = StatusHistory.objects.filter(pos_app__pk=pos_app_pk) + statuses_list = StatusHistorySerializer( + instance=statuses_list, many=True).data return JsonResponse(create_response(data=statuses_list), safe=False) @csrf_exempt @api_view(["GET", "POST", "PUT", "DELETE"]) -def contacts(request, job_app_pk): +def contacts(request, pos_app_pk): body = request.data if request.method == "GET": data = {} - if job_app_pk is None: + if pos_app_pk is None: return JsonResponse(create_response(data=None, success=False, error_code=ResponseCodes.invalid_parameters), safe=False) else: - contacts_list = Contact.objects.filter(job_post__pk=job_app_pk) - contacts_list = ContactSerializer(instance=contacts_list, many=True).data + contacts_list = Contact.objects.filter(pos_app_pk=pos_app_pk) + contacts_list = ContactSerializer( + instance=contacts_list, many=True).data data['contacts'] = contacts_list user_profile = request.user - if not user_profile.user_type.alumni_listing_enabled: - alumni = [] - else: - jobapp = JobApplication.objects.get(pk=job_app_pk) - alumni_list = User.objects.filter(college=user_profile.college, company=jobapp.company_object, - user_type__name__iexact='Alumni') - alumni = AlumniSerializer( - instance=alumni_list, many=True, context={'user': request.user}).data - data['alumni'] = alumni + jobapp = PositionApplication.objects.get(pk=pos_app_pk) + return JsonResponse(create_response(data=data, success=True, error_code=ResponseCodes.success), safe=False) elif request.method == "POST": first_name = body.get('first_name') last_name = body.get('last_name') - if job_app_pk is None or first_name is None or last_name is None: + if pos_app_pk is None or first_name is None or last_name is None: return JsonResponse(create_response(data=None, success=False, error_code=ResponseCodes.invalid_parameters), safe=False) - user_job_app = JobApplication.objects.get(pk=job_app_pk) + user_job_app = PositionApplication.objects.get(pk=pos_app_pk) if user_job_app.user == request.user: phone_number = body.get('phone_number') linkedin_url = body.get('linkedin_url') @@ -247,7 +228,7 @@ def contacts(request, job_app_pk): jc = get_or_create_company(company) contact = Contact( - job_post=user_job_app, first_name=first_name, last_name=last_name, phone_number=phone_number, + pos_app=user_job_app, first_name=first_name, last_name=last_name, phone_number=phone_number, linkedin_url=linkedin_url, description=description, email=email, position=jt, company=jc) @@ -257,7 +238,8 @@ def contacts(request, job_app_pk): return JsonResponse(create_response(data=data), safe=False) else: return JsonResponse( - create_response(data=None, success=False, error_code=ResponseCodes.record_not_found), + create_response(data=None, success=False, + error_code=ResponseCodes.record_not_found), safe=False) elif request.method == "PUT": contact_id = body.get('contact_id') @@ -265,13 +247,7 @@ def contacts(request, job_app_pk): return JsonResponse(create_response(data=None, success=False, error_code=ResponseCodes.invalid_parameters), safe=False) contact = Contact.objects.get(pk=contact_id) - if contact.job_post.user == request.user: - first_name = body.get('first_name') - if first_name is not None: - contact.first_name = first_name - last_name = body.get('last_name') - if last_name is not None: - contact.last_name = last_name + if contact.pos_app.user == request.user: email = body.get('email') if email is not None: contact.email = email @@ -291,7 +267,7 @@ def contacts(request, job_app_pk): if company is not None: contact.company = get_or_create_company(company) - contact.update_date = datetime.now() + contact.updated_date = timezone.now() contact.save() data = ContactSerializer( instance=contact, many=False).data @@ -299,7 +275,8 @@ def contacts(request, job_app_pk): safe=False) else: return JsonResponse( - create_response(data=None, success=False, error_code=ResponseCodes.record_not_found), + create_response(data=None, success=False, + error_code=ResponseCodes.record_not_found), safe=False) elif request.method == "DELETE": contact_id = body.get('contact_id') @@ -312,7 +289,7 @@ def contacts(request, job_app_pk): return JsonResponse(create_response(data=None, success=False, error_code=ResponseCodes.record_not_found), safe=False) user_job_app_contact = user_job_app_contact[0] - if user_job_app_contact.job_post.user == request.user: + if user_job_app_contact.pos_app.user == request.user: user_job_app_contact.delete() return JsonResponse(create_response(data=None, success=True, error_code=ResponseCodes.success), safe=False) else: @@ -322,36 +299,37 @@ def contacts(request, job_app_pk): @csrf_exempt @api_view(["GET", "POST", "PUT", "DELETE"]) -def notes(request, job_app_pk): +def notes(request, pos_app_pk): body = request.data if 'recaptcha_token' in body and utils.verify_recaptcha(None, body['recaptcha_token'], 'jobapp_note') == ResponseCodes.verify_recaptcha_failed: return JsonResponse( - create_response(data=None, success=False, error_code=ResponseCodes.verify_recaptcha_failed), + create_response(data=None, success=False, + error_code=ResponseCodes.verify_recaptcha_failed), safe=False) if request.method == "GET": - if job_app_pk is None: + if pos_app_pk is None: return JsonResponse(create_response(data=None, success=False, error_code=ResponseCodes.invalid_parameters), safe=False) else: - notes_list = JobApplicationNote.objects.filter( - job_post__pk=job_app_pk).order_by('-update_date', '-created_date') - notes_list = JobApplicationNoteSerializer( + notes_list = PositionApplicationNote.objects.filter( + pos_app__pk=pos_app_pk).order_by('-updated_date', '-created_date') + notes_list = PositionApplicationNoteSerializer( instance=notes_list, many=True).data return JsonResponse(create_response(data=notes_list, success=True, error_code=ResponseCodes.success), safe=False) elif request.method == "POST": description = body['description'] - if job_app_pk is None or description is None: + if pos_app_pk is None or description is None: return JsonResponse(create_response(data=None, success=False, error_code=ResponseCodes.invalid_parameters), safe=False) else: - user_job_app = JobApplication.objects.get(pk=job_app_pk) + user_job_app = PositionApplication.objects.get(pk=pos_app_pk) if user_job_app.user == request.user: - note = JobApplicationNote( - job_post=user_job_app, description=description) + note = PositionApplicationNote( + pos_app=user_job_app, description=description) note.save() - data = JobApplicationNoteSerializer( + data = PositionApplicationNoteSerializer( instance=note, many=False).data return JsonResponse(create_response(data=data, success=True, error_code=ResponseCodes.success), safe=False) @@ -365,12 +343,12 @@ def notes(request, job_app_pk): return JsonResponse( create_response(data=None, success=False, error_code=ResponseCodes.invalid_parameters), safe=False) else: - note = JobApplicationNote.objects.get(pk=jobapp_note_id) - if note.job_post.user == request.user: + note = PositionApplicationNote.objects.get(pk=jobapp_note_id) + if note.pos_app.user == request.user: note.description = description - note.update_date = datetime.now() + note.updated_date = timezone.now() note.save() - data = JobApplicationNoteSerializer( + data = PositionApplicationNoteSerializer( instance=note, many=False).data return JsonResponse(create_response(data=data, success=True, error_code=ResponseCodes.success), safe=False) @@ -383,12 +361,84 @@ def notes(request, job_app_pk): return JsonResponse( create_response(data=None, success=False, error_code=ResponseCodes.invalid_parameters), safe=False) else: - user_job_app_note = JobApplicationNote.objects.get( + user_job_app_note = PositionApplicationNote.objects.get( pk=jobapp_note_id) - if user_job_app_note.job_post.user == request.user: + if user_job_app_note.pos_app.user == request.user: user_job_app_note.delete() return JsonResponse(create_response(data=None, success=True, error_code=ResponseCodes.success), safe=False) else: return JsonResponse( - create_response(data=None, success=False, error_code=ResponseCodes.record_not_found), + create_response(data=None, success=False, + error_code=ResponseCodes.record_not_found), safe=False) + + +@csrf_exempt +@api_view(["GET", "POST", "PUT", "DELETE"]) +def feedbacks(request, pos_app_pk): + body = request.data + if request.method == "GET": + if pos_app_pk is None: + return JsonResponse(create_response(data=None, success=False, error_code=ResponseCodes.invalid_parameters), + safe=False) + else: + feedbacks_list = Feedback.objects.filter( + pos_app__pk=pos_app_pk).order_by('-updated_date', '-created_date') + feedbacks_list = FeedbackSerializer( + instance=feedbacks_list, many=True).data + return JsonResponse(create_response(data=feedbacks_list, success=True, error_code=ResponseCodes.success), + safe=False) + elif request.method == "POST": + if pos_app_pk is None: + return JsonResponse(create_response(data=None, success=False, error_code=ResponseCodes.invalid_parameters), + safe=False) + else: + pos_app = PositionApplication.objects.get(pk=pos_app_pk) + interviewer = body.get('interviewer') + interview_round = body.get('interview_round') + rate = body.get('rate') + description = body.get('description') + interview_date = body.get('interview_date') + feedback = Feedback(pos_app=pos_app, interviewer=interviewer, interview_round=interview_round, + rate=rate, description=description, interview_date=interview_date) + feedback.save() + data = FeedbackSerializer(instance=feedback, many=False).data + return JsonResponse(create_response(data=data, success=True, error_code=ResponseCodes.success), safe=False) + elif request.method == "PUT": + if pos_app_pk is None: + return JsonResponse(create_response(data=None, success=False, error_code=ResponseCodes.invalid_parameters), + safe=False) + else: + feedback_id = body.get('feedback_id') + if feedback_id is None: + return JsonResponse( + create_response(data=None, success=False, error_code=ResponseCodes.invalid_parameters), safe=False) + else: + interviewer = body.get('interviewer') + interview_round = body.get('interview_round') + rate = body.get('rate') + description = body.get('description') + interview_date = body.get('interview_date') + feedback = Feedback.objects.get(pk=feedback_id) + if interviewer is not None: + feedback.interviewer = interviewer + if interview_round is not None: + feedback.interview_round = interview_round + if rate is not None: + feedback.rate = rate + if description is not None: + feedback.description = description + if interview_date is not None: + feedback.interview_date = interview_date + feedback.save() + data = FeedbackSerializer(instance=feedback, many=False).data + return JsonResponse(create_response(data=data, success=True, error_code=ResponseCodes.success), safe=False) + elif request.method == "DELETE": + feedback_id = body.get('feedback_id') + if feedback_id is None: + return JsonResponse( + create_response(data=None, success=False, error_code=ResponseCodes.invalid_parameters), safe=False) + else: + feedback = Feedback.objects.get(pk=feedback_id) + feedback.delete() + return JsonResponse(create_response(data=None, success=True, error_code=ResponseCodes.success), safe=False) diff --git a/review/__init__.py b/review/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/review/admin.py b/review/admin.py deleted file mode 100644 index 1e03c60..0000000 --- a/review/admin.py +++ /dev/null @@ -1,19 +0,0 @@ -from django.contrib import admin - -from utils.export_csv import ExportCsv -from .models import Review, CompanyEmploymentAuth, EmploymentAuth - - -@admin.register(Review) -class ReviewAdmin(admin.ModelAdmin, ExportCsv): - list_display = ("company", "position", "user", 'created_date', "is_published") - list_filter = ("company", "position", "user", 'created_date', "is_published") - actions = ["export_as_csv"] - - -@admin.register(EmploymentAuth) -class EmploymentAuthAdmin(admin.ModelAdmin): - list_display = ("id", "value") - - -admin.site.register(CompanyEmploymentAuth) diff --git a/review/apps.py b/review/apps.py deleted file mode 100644 index 5de2983..0000000 --- a/review/apps.py +++ /dev/null @@ -1,5 +0,0 @@ -from django.apps import AppConfig - - -class ReviewConfig(AppConfig): - name = 'review' diff --git a/review/migrations/0001_initial.py b/review/migrations/0001_initial.py deleted file mode 100644 index 91e1bda..0000000 --- a/review/migrations/0001_initial.py +++ /dev/null @@ -1,54 +0,0 @@ -# Generated by Django 2.2 on 2019-04-26 21:15 - -import datetime - -import django.core.validators -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - initial = True - - dependencies = [ - ('jobapps', '0023_sourcetype'), - ('users', '0010_employmentauth'), - ('company', '0001_initial'), - ('position', '0002_auto_20190422_2320'), - ] - - operations = [ - migrations.CreateModel( - name='Review', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('pros', models.TextField(blank=True, null=True)), - ('cons', models.TextField(blank=True, null=True)), - ('interview_notes', models.TextField(blank=True, null=True)), - ('overall_company_experience', models.IntegerField(blank=True, null=True, validators=[ - django.core.validators.MaxValueValidator(5), django.core.validators.MinValueValidator(0)])), - ('interview_difficulty', models.IntegerField(blank=True, null=True, - validators=[django.core.validators.MaxValueValidator(1), - django.core.validators.MinValueValidator(0)])), - ('overall_interview_experience', models.IntegerField(blank=True, null=True, validators=[ - django.core.validators.MaxValueValidator(1), django.core.validators.MinValueValidator(0)])), - ('anonymous', models.BooleanField(default=False)), - ('created_date', models.DateTimeField(blank=True, default=datetime.datetime.now)), - ('update_date', models.DateTimeField(blank=True, default=datetime.datetime.now, null=True)), - ('is_published', models.BooleanField(default=False)), - ('is_deleted', models.BooleanField(default=False)), - ('company', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, - to='company.Company')), - ('emp_auth', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, - to='users.EmploymentAuth')), - ('emp_status', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, - to='users.EmploymentStatus')), - ('jobapp', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, - to='jobapps.JobApplication')), - ('position', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, - to='position.JobPosition')), - ('source_type', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, - to='jobapps.SourceType')), - ], - ), - ] diff --git a/review/migrations/0002_auto_20190426_2307.py b/review/migrations/0002_auto_20190426_2307.py deleted file mode 100644 index da62405..0000000 --- a/review/migrations/0002_auto_20190426_2307.py +++ /dev/null @@ -1,22 +0,0 @@ -# Generated by Django 2.2 on 2019-04-26 23:07 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('users', '0010_employmentauth'), - ('review', '0001_initial'), - ] - - operations = [ - migrations.RemoveField( - model_name='review', - name='emp_auth', - ), - migrations.AddField( - model_name='review', - name='emp_auth', - field=models.ManyToManyField(to='users.EmploymentAuth'), - ), - ] diff --git a/review/migrations/0003_auto_20190426_2324.py b/review/migrations/0003_auto_20190426_2324.py deleted file mode 100644 index 6a75a23..0000000 --- a/review/migrations/0003_auto_20190426_2324.py +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by Django 2.2 on 2019-04-26 23:24 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('users', '0010_employmentauth'), - ('review', '0002_auto_20190426_2307'), - ] - - operations = [ - migrations.RemoveField( - model_name='review', - name='emp_auth', - ), - migrations.CreateModel( - name='CompanyEmploymentAuth', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('value', models.BooleanField(default=False)), - ('employment_auth', - models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to='users.EmploymentAuth')), - ('review', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to='review.Review')), - ], - ), - ] diff --git a/review/migrations/0004_auto_20190429_0014.py b/review/migrations/0004_auto_20190429_0014.py deleted file mode 100644 index cb06f92..0000000 --- a/review/migrations/0004_auto_20190429_0014.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 2.2 on 2019-04-29 00:14 - -import django.core.validators -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('review', '0003_auto_20190426_2324'), - ] - - operations = [ - migrations.AlterField( - model_name='review', - name='overall_interview_experience', - field=models.IntegerField(blank=True, null=True, validators=[django.core.validators.MaxValueValidator(5), - django.core.validators.MinValueValidator(0)]), - ), - ] diff --git a/review/migrations/0006_auto_20190429_1944.py b/review/migrations/0006_auto_20190429_1944.py deleted file mode 100644 index 736a477..0000000 --- a/review/migrations/0006_auto_20190429_1944.py +++ /dev/null @@ -1,16 +0,0 @@ -# Generated by Django 2.2 on 2019-04-29 19:44 - -from django.db import migrations - - -class Migration(migrations.Migration): - dependencies = [ - ('review', '0005_auto_20190429_0046'), - ] - - operations = [ - migrations.AlterModelOptions( - name='review', - options={'ordering': ['-created_date']}, - ), - ] diff --git a/review/migrations/0007_auto_20190501_0453.py b/review/migrations/0007_auto_20190501_0453.py deleted file mode 100644 index a6b45d2..0000000 --- a/review/migrations/0007_auto_20190501_0453.py +++ /dev/null @@ -1,54 +0,0 @@ -# Generated by Django 2.2 on 2019-05-01 04:53 - -import django.db.models.deletion -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('review', '0006_auto_20190429_1944'), - ] - - operations = [ - migrations.AlterField( - model_name='companyemploymentauth', - name='employment_auth', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='users.EmploymentAuth'), - ), - migrations.AlterField( - model_name='companyemploymentauth', - name='review', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='review.Review'), - ), - migrations.AlterField( - model_name='review', - name='company', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, - to='company.Company'), - ), - migrations.AlterField( - model_name='review', - name='emp_status', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, - to='users.EmploymentStatus'), - ), - migrations.AlterField( - model_name='review', - name='position', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, - to='position.JobPosition'), - ), - migrations.AlterField( - model_name='review', - name='source_type', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, - to='jobapps.SourceType'), - ), - migrations.AlterField( - model_name='review', - name='user', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, - to=settings.AUTH_USER_MODEL), - ), - ] diff --git a/review/migrations/0008_auto_20190501_2320.py b/review/migrations/0008_auto_20190501_2320.py deleted file mode 100644 index 912e3a7..0000000 --- a/review/migrations/0008_auto_20190501_2320.py +++ /dev/null @@ -1,25 +0,0 @@ -# Generated by Django 2.2 on 2019-05-01 23:20 - -import django.core.validators -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('review', '0007_auto_20190501_0453'), - ] - - operations = [ - migrations.AlterField( - model_name='review', - name='interview_difficulty', - field=models.IntegerField(blank=True, null=True, validators=[django.core.validators.MaxValueValidator(5), - django.core.validators.MinValueValidator(0)]), - ), - migrations.AlterField( - model_name='review', - name='overall_interview_experience', - field=models.IntegerField(blank=True, null=True, validators=[django.core.validators.MaxValueValidator(1), - django.core.validators.MinValueValidator(0)]), - ), - ] diff --git a/review/migrations/0009_auto_20190812_2227.py b/review/migrations/0009_auto_20190812_2227.py deleted file mode 100644 index 7207b01..0000000 --- a/review/migrations/0009_auto_20190812_2227.py +++ /dev/null @@ -1,24 +0,0 @@ -# Generated by Django 2.2 on 2019-08-12 22:27 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('review', '0008_auto_20190501_2320'), - ] - - operations = [ - migrations.AlterField( - model_name='review', - name='company', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='company.Company'), - ), - migrations.AlterField( - model_name='review', - name='position', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='position.JobPosition'), - ), - ] diff --git a/review/migrations/0010_auto_20190911_1158.py b/review/migrations/0010_auto_20190911_1158.py deleted file mode 100644 index 1cef59a..0000000 --- a/review/migrations/0010_auto_20190911_1158.py +++ /dev/null @@ -1,35 +0,0 @@ -# Generated by Django 2.2 on 2019-09-11 18:58 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('review', '0009_auto_20190812_2227'), - ] - - def move_data(apps, schema_editor): - UsersEmploymentAuth = apps.get_model('users', 'EmploymentAuth') - ReviewEmploymentAuth = apps.get_model('review', 'EmploymentAuth') - for ue in UsersEmploymentAuth.objects.all(): - re = ReviewEmploymentAuth() - re.value = ue.value - re.save() - - operations = [ - migrations.CreateModel( - name='EmploymentAuth', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('value', models.CharField(max_length=20)), - ], - ), - migrations.RunPython(move_data, reverse_code=migrations.RunPython.noop), - migrations.AlterField( - model_name='companyemploymentauth', - name='employment_auth', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='review.EmploymentAuth'), - ), - ] diff --git a/review/migrations/__init__.py b/review/migrations/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/review/models.py b/review/models.py deleted file mode 100644 index 79fb532..0000000 --- a/review/models.py +++ /dev/null @@ -1,56 +0,0 @@ -from datetime import datetime - -from django.contrib.auth import get_user_model -from django.core.validators import MaxValueValidator, MinValueValidator -from django.db import models - -from company.models import Company -from jobapps.models import SourceType -from position.models import JobPosition -from users.models import EmploymentStatus - -User = get_user_model() - - -class EmploymentAuth(models.Model): - value = models.CharField(max_length=20, null=False) - - def __str__(self): - return self.value if self.value is not None else '' - - -class Review(models.Model): - company = models.ForeignKey(Company, on_delete=models.CASCADE, null=True, blank=True) - position = models.ForeignKey(JobPosition, on_delete=models.CASCADE, null=True, blank=True) - user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True) - pros = models.TextField(null=True, blank=True) - cons = models.TextField(null=True, blank=True) - emp_status = models.ForeignKey(EmploymentStatus, on_delete=models.SET_NULL, null=True, blank=True) - interview_notes = models.TextField(null=True, blank=True) - source_type = models.ForeignKey(SourceType, on_delete=models.SET_NULL, null=True, blank=True) - overall_company_experience = models.IntegerField(validators=[ - MaxValueValidator(5), - MinValueValidator(0) - ], null=True, blank=True) - interview_difficulty = models.IntegerField(validators=[ - MaxValueValidator(5), - MinValueValidator(0) - ], null=True, blank=True) - overall_interview_experience = models.IntegerField(validators=[ - MaxValueValidator(1), - MinValueValidator(0) - ], null=True, blank=True) - anonymous = models.BooleanField(default=False, null=False, blank=False) - created_date = models.DateTimeField(default=datetime.now, blank=True) - update_date = models.DateTimeField(default=datetime.now, null=True, blank=True) - is_published = models.BooleanField(default=False) - is_deleted = models.BooleanField(default=False) - - class Meta: - ordering = ['-created_date'] - - -class CompanyEmploymentAuth(models.Model): - review = models.ForeignKey(Review, on_delete=models.CASCADE) - employment_auth = models.ForeignKey(EmploymentAuth, on_delete=models.CASCADE) - value = models.BooleanField(default=False) diff --git a/review/serializers.py b/review/serializers.py deleted file mode 100644 index cdf9472..0000000 --- a/review/serializers.py +++ /dev/null @@ -1,63 +0,0 @@ -import pytz -from rest_framework import serializers - -from jobapps.serializers import SourceTypeSerializer -from users.serializers import EmploymentStatusSerializer -from .models import Review, CompanyEmploymentAuth, EmploymentAuth - - -class EmploymentAuthSerializer(serializers.ModelSerializer): - - def create(self, validated_data): - return EmploymentAuth.objects.create(**validated_data) - - class Meta: - model = EmploymentAuth - fields = ('__all__') - - -class CompanyEmploymentAuthSerializer(serializers.ModelSerializer): - employment_auth = EmploymentAuthSerializer(read_only=True) - - def create(self, validated_data): - return CompanyEmploymentAuth.objects.create(**validated_data) - - class Meta: - model = CompanyEmploymentAuth - fields = ('id', 'value', 'employment_auth') - - -class ReviewSerializer(serializers.ModelSerializer): - emp_auths = serializers.SerializerMethodField() - emp_status = EmploymentStatusSerializer(read_only=True) - source_type = SourceTypeSerializer(read_only=True) - username = serializers.SerializerMethodField() - - def get_username(self, obj): - username = 'Anonymous' - if not obj.anonymous and obj.user is not None: - username = obj.user.username - return username - - def get_emp_auths(self, obj): - auths = CompanyEmploymentAuth.objects.filter(review=obj) - return CompanyEmploymentAuthSerializer(instance=auths, many=True).data - - def get_created_date(self, obj): - if obj.created_date is None: - return None - return obj.created_date.astimezone(pytz.timezone('US/Pacific')) - - def get_update_date(self, obj): - if obj.update_date is None: - return None - return obj.update_date.astimezone(pytz.timezone('US/Pacific')) - - def create(self, validated_data): - return Review.objects.create(**validated_data) - - class Meta: - model = Review - fields = ('id', 'emp_auths', 'emp_status', 'source_type', 'username', 'pros', 'cons', 'interview_notes', - 'overall_company_experience', 'interview_difficulty', 'overall_interview_experience', 'anonymous', - 'created_date', 'update_date', 'is_published') diff --git a/review/tests.py b/review/tests.py deleted file mode 100644 index eba26d2..0000000 --- a/review/tests.py +++ /dev/null @@ -1,2 +0,0 @@ -# Create your tests here. -# We need some unit tests. diff --git a/review/urls.py b/review/urls.py deleted file mode 100644 index 170bfa3..0000000 --- a/review/urls.py +++ /dev/null @@ -1,11 +0,0 @@ -from django.urls import path -from rest_framework.urlpatterns import format_suffix_patterns - -from review import views - -urlpatterns = [ - path('', views.reviews), - path('sourceTypes/', views.source_types), - path('employmentAuthorizations/', views.employment_authorizations), -] -urlpatterns = format_suffix_patterns(urlpatterns) diff --git a/review/views.py b/review/views.py deleted file mode 100644 index fb0c411..0000000 --- a/review/views.py +++ /dev/null @@ -1,143 +0,0 @@ -from django.db.models import Q -from django.http import JsonResponse -from django.views.decorators.csrf import csrf_exempt -from rest_framework.decorators import api_view -from datetime import datetime - -from company.models import Company -from company.serializers import CompanySerializer -from jobapps.models import SourceType -from jobapps.serializers import SourceSerializer -from position.models import JobPosition -from review.models import EmploymentAuth, EmploymentStatus -from utils import utils -from utils.error_codes import ResponseCodes -from utils.generic_json_creator import create_response -from utils.utils import send_notification_email_to_admins, get_boolean_from_request -from .models import Review, CompanyEmploymentAuth -from .serializers import ReviewSerializer, EmploymentAuthSerializer - - -@csrf_exempt -@api_view(["GET", "POST", "PUT"]) -def reviews(request): - body = request.data - user = request.user - if 'recaptcha_token' in body and utils.verify_recaptcha(user, body['recaptcha_token'], - 'review') == ResponseCodes.verify_recaptcha_failed: - return JsonResponse(create_response(data=None, success=False, error_code=ResponseCodes.verify_recaptcha_failed), - safe=False) - - if request.method == "GET": - company_id = request.GET.get('company_id') - position_id = request.GET.get('position_id') - all_reviews = get_boolean_from_request(request, 'all_reviews') - review_id = request.GET.get('review_id') - if review_id is not None: - reviews_list = Review.objects.filter(pk=review_id, user=request.user) - if reviews_list.count() == 0: - return JsonResponse( - create_response(data=None, success=False, error_code=ResponseCodes.record_not_found), - safe=False) - return JsonResponse(create_response(data=ReviewSerializer(instance=reviews_list[0], many=False).data), - safe=False) - elif company_id is None and position_id is None: - return JsonResponse(create_response(data=None, success=False, error_code=ResponseCodes.invalid_parameters), - safe=False) - if company_id is None: - reviews_list = Review.objects.filter(Q(is_published=True) | Q( - user=request.user), position__pk=position_id) - elif position_id is None: - reviews_list = Review.objects.filter(Q(is_published=True) | Q( - user=request.user), company__pk=company_id) - else: - if all_reviews: - reviews_list = Review.objects.filter( - is_published=True, position__pk=position_id, company__pk=company_id) - else: - reviews_list = Review.objects.filter( - user=request.user, position__pk=position_id, company__pk=company_id) - if reviews_list.count() > 0: - return JsonResponse(create_response(data=ReviewSerializer(instance=reviews_list[0], many=False).data), - safe=False) - else: - return JsonResponse(create_response(data=None), safe=False) - return JsonResponse(create_response(data=ReviewSerializer(instance=reviews_list, many=True).data), safe=False) - else: - if 'company_id' not in body or 'position_id' not in body: - return JsonResponse(create_response(data=None, success=False, error_code=ResponseCodes.invalid_parameters), - safe=False) - - company = Company.objects.get(pk=body['company_id']) - position = JobPosition.objects.get(pk=body['position_id']) - if request.method == "PUT": - review = Review.objects.get(pk=body['review_id']) - if review.user.pk != user.pk: - return JsonResponse(create_response(data=None, success=False, error_code=ResponseCodes.record_not_found), - safe=False) - review.update_date = datetime.now() - elif request.method == "POST": - review = Review() - review.company = company - review.position = position - review.user = request.user - if 'pros' in body: - review.pros = body['pros'] - if 'cons' in body: - review.cons = body['cons'] - if 'interview_notes' in body: - review.interview_notes = body['interview_notes'] - if 'overall_company_experience' in body: - review.overall_company_experience = body['overall_company_experience'] - if 'interview_difficulty' in body: - review.interview_difficulty = body['interview_difficulty'] - if 'overall_interview_experience' in body: - review.overall_interview_experience = body['overall_interview_experience'] - if 'anonymous' in body: - review.anonymous = body['anonymous'] - if 'emp_auths' in body: - for a in body['emp_auths']: - if 'value' in a: - auth = EmploymentAuth.objects.get(pk=a['id']) - review.save() - if CompanyEmploymentAuth.objects.filter(review=review, employment_auth=auth).count() == 0: - c_auth = CompanyEmploymentAuth( - review=review, employment_auth=auth, value=a['value']) - c_auth.save() - else: - c_auth = CompanyEmploymentAuth.objects.get( - review=review, employment_auth=auth) - c_auth.value = a['value'] - c_auth.save() - if 'emp_status_id' in body: - review.emp_status = EmploymentStatus.objects.get( - pk=body['emp_status_id']) - if 'source_type_id' in body: - review.source_type = SourceType.objects.get(pk=body['source_type_id']) - - # publish review if there is no content to approve - if 'pros' not in body and 'cons' not in body and 'interview_notes' not in body: - review.is_published = True - else: - review.is_published = False - send_notification_email_to_admins('review') - - review.save() - response = {'review': ReviewSerializer(instance=review, many=False).data, - 'company': CompanySerializer(instance=company, many=False, context={ - 'user': request.user, 'position': position}).data} - return JsonResponse(create_response(data=response), safe=False) - - -@csrf_exempt -@api_view(["GET"]) -def source_types(request): - sources = SourceType.objects.all() - return JsonResponse(create_response(data=SourceSerializer(instance=sources, many=True).data), safe=False) - - -@csrf_exempt -@api_view(["GET"]) -def employment_authorizations(request): - statuses = EmploymentAuth.objects.all() - return JsonResponse(create_response(data=EmploymentAuthSerializer(instance=statuses, many=True).data), safe=False) diff --git a/start.sh b/start.sh index c03afba..0c0b369 100755 --- a/start.sh +++ b/start.sh @@ -1,3 +1,3 @@ #!/usr/bin/env bash -python3 manage.py runserver 0.0.0.0:8000 & +python3 manage.py runserver 0.0.0.0:8001 & python3 manage.py process_tasks \ No newline at end of file diff --git a/users/migrations/0001_initial.py b/users/migrations/0001_initial.py index 3e0d028..5593867 100644 --- a/users/migrations/0001_initial.py +++ b/users/migrations/0001_initial.py @@ -1,17 +1,24 @@ -# Generated by Django 2.2 on 2019-04-26 09:03 +# Generated by Django 2.2 on 2019-10-03 23:52 +from django.conf import settings import django.contrib.auth.models import django.contrib.auth.validators -import django.utils.timezone -from django.conf import settings +import django.core.validators from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone class Migration(migrations.Migration): + initial = True dependencies = [ ('auth', '0011_update_proxy_permissions'), + ('major', '0001_initial'), + ('position', '0001_initial'), + ('college', '0001_initial'), + ('utils', '0001_initial'), ] operations = [ @@ -21,31 +28,34 @@ class Migration(migrations.Migration): ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('password', models.CharField(max_length=128, verbose_name='password')), ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), - ('is_superuser', models.BooleanField(default=False, - help_text='Designates that this user has all permissions without explicitly assigning them.', - verbose_name='superuser status')), - ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, - help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', - max_length=150, unique=True, - validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], - verbose_name='username')), + ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), + ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')), ('first_name', models.CharField(blank=True, max_length=30, verbose_name='first name')), ('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')), - ('is_staff', models.BooleanField(default=False, - help_text='Designates whether the user can log into this admin site.', - verbose_name='staff status')), - ('is_active', models.BooleanField(default=True, - help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', - verbose_name='active')), + ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')), + ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')), ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')), ('email', models.EmailField(max_length=254, unique=True, verbose_name='email address')), - ('groups', models.ManyToManyField(blank=True, - help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', - related_name='user_set', related_query_name='user', to='auth.Group', - verbose_name='groups')), - ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', - related_name='user_set', related_query_name='user', - to='auth.Permission', verbose_name='user permissions')), + ('is_email_public', models.BooleanField(default=True)), + ('approved', models.BooleanField(default=False)), + ('activation_key', models.TextField(blank=True, null=True)), + ('key_expires', models.DateTimeField(blank=True, null=True)), + ('forgot_password_key', models.TextField(blank=True, null=True)), + ('forgot_password_key_expires', models.DateTimeField(blank=True, null=True)), + ('gmail_last_update_time', models.IntegerField(default=0)), + ('is_gmail_read_ok', models.BooleanField(default=True)), + ('signup_flow_completed', models.BooleanField(default=False)), + ('synching', models.BooleanField(default=False)), + ('is_demo', models.BooleanField(default=False)), + ('gender', models.CharField(choices=[('M', 'Male'), ('F', 'Female'), ('N', 'None')], default='N', max_length=1)), + ('dob', models.DateField(blank=True, null=True)), + ('student_email', models.EmailField(blank=True, max_length=254, verbose_name='student email address')), + ('phone_number', models.CharField(blank=True, max_length=17, validators=[django.core.validators.RegexValidator(message="Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed.", regex='^\\+?1?\\d{9,15}$')])), + ('profile_photo', models.FileField(blank=True, null=True, upload_to='')), + ('grad_year', models.IntegerField(blank=True, null=True)), + ('college', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='college.College')), + ('company', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='company.Company')), + ('country', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='utils.Country')), ], options={ 'verbose_name': 'user', @@ -58,14 +68,67 @@ class Migration(migrations.Migration): ], ), migrations.CreateModel( - name='Profile', + name='EmploymentStatus', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('gmail_last_update_time', models.IntegerField(default=0)), - ('is_gmail_read_ok', models.BooleanField(default=True)), - ('linkedin_info', models.TextField(blank=True, null=True)), - ( - 'user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ('value', models.CharField(default='N/A', max_length=20)), + ], + ), + migrations.CreateModel( + name='UserType', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=20)), + ('alumni_listing_enabled', models.BooleanField(default=False)), + ('blog_creation_enabled', models.BooleanField(default=False)), + ('event_creation_enabled', models.BooleanField(default=False)), + ('college_specific_metrics_enabled', models.BooleanField(default=False)), ], ), + migrations.CreateModel( + name='Feedback', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('from_demo_account', models.BooleanField(default=False)), + ('text', models.TextField(blank=True, null=True)), + ('star', models.IntegerField(blank=True, null=True, validators=[django.core.validators.MaxValueValidator(5), django.core.validators.MinValueValidator(0)])), + ('created_date', models.DateTimeField(auto_now_add=True, null=True)), + ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.AddField( + model_name='user', + name='emp_status', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='users.EmploymentStatus'), + ), + migrations.AddField( + model_name='user', + name='groups', + field=models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups'), + ), + migrations.AddField( + model_name='user', + name='job_position', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='position.JobPosition'), + ), + migrations.AddField( + model_name='user', + name='major', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='major.Major'), + ), + migrations.AddField( + model_name='user', + name='state', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='utils.State'), + ), + migrations.AddField( + model_name='user', + name='user_permissions', + field=models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions'), + ), + migrations.AddField( + model_name='user', + name='user_type', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='users.UserType'), + ), ] diff --git a/users/migrations/0002_auto_20190426_1055.py b/users/migrations/0002_auto_20190426_1055.py deleted file mode 100644 index db84e6c..0000000 --- a/users/migrations/0002_auto_20190426_1055.py +++ /dev/null @@ -1,40 +0,0 @@ -# Generated by Django 2.2 on 2019-04-26 10:55 - -import django.core.validators -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('users', '0001_initial'), - ] - - operations = [ - migrations.AddField( - model_name='profile', - name='dob', - field=models.DateTimeField(blank=True, null=True), - ), - migrations.AddField( - model_name='profile', - name='gender', - field=models.CharField(choices=[('M', 'Male'), ('F', 'Female'), ('N', 'None')], default='N', max_length=1), - ), - migrations.AddField( - model_name='profile', - name='itu_email', - field=models.EmailField(blank=True, max_length=254, verbose_name='email address'), - ), - migrations.AddField( - model_name='profile', - name='phone_number', - field=models.CharField(blank=True, max_length=17, validators=[django.core.validators.RegexValidator( - message="Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed.", - regex='^\\+?1?\\d{9,15}$')]), - ), - migrations.AddField( - model_name='profile', - name='profile_photo', - field=models.CharField(blank=True, max_length=200), - ), - ] diff --git a/users/migrations/0043_usertype.py b/users/migrations/0002_usertype.py similarity index 61% rename from users/migrations/0043_usertype.py rename to users/migrations/0002_usertype.py index a657802..f218345 100644 --- a/users/migrations/0043_usertype.py +++ b/users/migrations/0002_usertype.py @@ -7,7 +7,7 @@ class Migration(migrations.Migration): dependencies = [ - ('users', '0042_user_is_email_public'), + ('users', '0001_initial'), ] def create_user_types(apps, schema_editor): @@ -21,6 +21,8 @@ def create_user_types(apps, schema_editor): student.save() alumni = UserType(name='Alumni') alumni.save() + alumni = UserType(name='Employer') + alumni.save() users = User.objects.all() for user in users: @@ -35,17 +37,5 @@ def create_user_types(apps, schema_editor): user.save() operations = [ - migrations.CreateModel( - name='UserType', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=20)), - ], - ), - migrations.AddField( - model_name='user', - name='type', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='users.UserType'), - ), - migrations.RunPython(create_user_types, reverse_code=migrations.RunPython.noop) + #migrations.RunPython(create_user_types, reverse_code=migrations.RunPython.noop) ] diff --git a/users/migrations/0003_auto_20190426_1059.py b/users/migrations/0003_auto_20190426_1059.py deleted file mode 100644 index a45879f..0000000 --- a/users/migrations/0003_auto_20190426_1059.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 2.2 on 2019-04-26 10:59 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('users', '0002_auto_20190426_1055'), - ] - - operations = [ - migrations.AlterField( - model_name='profile', - name='itu_email', - field=models.EmailField(blank=True, max_length=254, verbose_name='itu email address'), - ), - ] diff --git a/users/migrations/0004_employmentstatus.py b/users/migrations/0004_employmentstatus.py deleted file mode 100644 index ae8f6ee..0000000 --- a/users/migrations/0004_employmentstatus.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 2.2 on 2019-04-26 11:22 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('users', '0003_auto_20190426_1059'), - ] - - operations = [ - migrations.CreateModel( - name='EmploymentStatus', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('value', models.CharField(max_length=20, null=True)), - ], - ), - ] diff --git a/users/migrations/0005_profile_emp_status.py b/users/migrations/0005_profile_emp_status.py deleted file mode 100644 index 9ca4178..0000000 --- a/users/migrations/0005_profile_emp_status.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 2.2 on 2019-04-26 11:28 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('users', '0004_employmentstatus'), - ] - - operations = [ - migrations.AddField( - model_name='profile', - name='emp_status', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, - to='users.EmploymentStatus'), - ), - ] diff --git a/users/migrations/0006_auto_20190426_1136.py b/users/migrations/0006_auto_20190426_1136.py deleted file mode 100644 index f94eb93..0000000 --- a/users/migrations/0006_auto_20190426_1136.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 2.2 on 2019-04-26 11:36 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('users', '0005_profile_emp_status'), - ] - - operations = [ - migrations.AlterField( - model_name='employmentstatus', - name='value', - field=models.CharField(default='N/A', max_length=20), - ), - ] diff --git a/users/migrations/0007_auto_20190426_1225.py b/users/migrations/0007_auto_20190426_1225.py deleted file mode 100644 index 66b3724..0000000 --- a/users/migrations/0007_auto_20190426_1225.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 2.2 on 2019-04-26 12:25 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('users', '0006_auto_20190426_1136'), - ] - - operations = [ - migrations.AlterField( - model_name='profile', - name='dob', - field=models.DateField(blank=True, null=True), - ), - ] diff --git a/users/migrations/0008_feedback.py b/users/migrations/0008_feedback.py deleted file mode 100644 index ff1428d..0000000 --- a/users/migrations/0008_feedback.py +++ /dev/null @@ -1,24 +0,0 @@ -# Generated by Django 2.2 on 2019-04-26 12:42 - -import django.db.models.deletion -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('users', '0007_auto_20190426_1225'), - ] - - operations = [ - migrations.CreateModel( - name='Feedback', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('text', models.TextField(blank=True, null=True)), - ('star', models.IntegerField(blank=True, null=True)), - ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, - to=settings.AUTH_USER_MODEL)), - ], - ), - ] diff --git a/users/migrations/0009_auto_20190426_2024.py b/users/migrations/0009_auto_20190426_2024.py deleted file mode 100644 index 6c28282..0000000 --- a/users/migrations/0009_auto_20190426_2024.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 2.2 on 2019-04-26 20:24 - -import django.core.validators -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('users', '0008_feedback'), - ] - - operations = [ - migrations.AlterField( - model_name='feedback', - name='star', - field=models.IntegerField(blank=True, null=True, validators=[django.core.validators.MaxValueValidator(5), - django.core.validators.MinValueValidator(0)]), - ), - ] diff --git a/users/migrations/0010_employmentauth.py b/users/migrations/0010_employmentauth.py deleted file mode 100644 index 2394354..0000000 --- a/users/migrations/0010_employmentauth.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 2.2 on 2019-04-26 21:15 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('users', '0009_auto_20190426_2024'), - ] - - operations = [ - migrations.CreateModel( - name='EmploymentAuth', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('value', models.CharField(max_length=20)), - ], - ), - ] diff --git a/users/migrations/0011_auto_20190501_0453.py b/users/migrations/0011_auto_20190501_0453.py deleted file mode 100644 index dd667eb..0000000 --- a/users/migrations/0011_auto_20190501_0453.py +++ /dev/null @@ -1,26 +0,0 @@ -# Generated by Django 2.2 on 2019-05-01 04:53 - -import django.db.models.deletion -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('users', '0010_employmentauth'), - ] - - operations = [ - migrations.AlterField( - model_name='feedback', - name='user', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, - to=settings.AUTH_USER_MODEL), - ), - migrations.AlterField( - model_name='profile', - name='emp_status', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, - to='users.EmploymentStatus'), - ), - ] diff --git a/users/migrations/0012_profile_profile_updated.py b/users/migrations/0012_profile_profile_updated.py deleted file mode 100644 index e1ca40d..0000000 --- a/users/migrations/0012_profile_profile_updated.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 2.2 on 2019-05-02 00:06 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('users', '0011_auto_20190501_0453'), - ] - - operations = [ - migrations.AddField( - model_name='profile', - name='profile_updated', - field=models.BooleanField(default=False), - ), - ] diff --git a/users/migrations/0013_user_approved.py b/users/migrations/0013_user_approved.py deleted file mode 100644 index a26ae63..0000000 --- a/users/migrations/0013_user_approved.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 2.2 on 2019-05-02 00:25 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('users', '0012_profile_profile_updated'), - ] - - operations = [ - migrations.AddField( - model_name='user', - name='approved', - field=models.BooleanField(default=False), - ), - ] diff --git a/users/migrations/0014_auto_20190502_0129.py b/users/migrations/0014_auto_20190502_0129.py deleted file mode 100644 index 5f5f5f0..0000000 --- a/users/migrations/0014_auto_20190502_0129.py +++ /dev/null @@ -1,22 +0,0 @@ -# Generated by Django 2.2 on 2019-05-02 01:29 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('users', '0013_user_approved'), - ] - - operations = [ - migrations.AddField( - model_name='profile', - name='activation_key', - field=models.CharField(max_length=40, null=True), - ), - migrations.AddField( - model_name='profile', - name='key_expires', - field=models.DateTimeField(null=True), - ), - ] diff --git a/users/migrations/0015_auto_20190502_0137.py b/users/migrations/0015_auto_20190502_0137.py deleted file mode 100644 index cdc77af..0000000 --- a/users/migrations/0015_auto_20190502_0137.py +++ /dev/null @@ -1,30 +0,0 @@ -# Generated by Django 2.2 on 2019-05-02 01:37 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('users', '0014_auto_20190502_0129'), - ] - - operations = [ - migrations.RemoveField( - model_name='profile', - name='activation_key', - ), - migrations.RemoveField( - model_name='profile', - name='key_expires', - ), - migrations.AddField( - model_name='user', - name='activation_key', - field=models.CharField(max_length=40, null=True), - ), - migrations.AddField( - model_name='user', - name='key_expires', - field=models.DateTimeField(null=True), - ), - ] diff --git a/users/migrations/0016_auto_20190502_0138.py b/users/migrations/0016_auto_20190502_0138.py deleted file mode 100644 index 393454c..0000000 --- a/users/migrations/0016_auto_20190502_0138.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 2.2 on 2019-05-02 01:38 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('users', '0015_auto_20190502_0137'), - ] - - operations = [ - migrations.AlterField( - model_name='user', - name='activation_key', - field=models.TextField(null=True), - ), - ] diff --git a/users/migrations/0017_auto_20190502_0408.py b/users/migrations/0017_auto_20190502_0408.py deleted file mode 100644 index b62380d..0000000 --- a/users/migrations/0017_auto_20190502_0408.py +++ /dev/null @@ -1,22 +0,0 @@ -# Generated by Django 2.2 on 2019-05-02 04:08 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('users', '0016_auto_20190502_0138'), - ] - - operations = [ - migrations.AddField( - model_name='user', - name='change_password_key', - field=models.TextField(null=True), - ), - migrations.AddField( - model_name='user', - name='change_password_key_expires', - field=models.DateTimeField(null=True), - ), - ] diff --git a/users/migrations/0018_auto_20190502_0413.py b/users/migrations/0018_auto_20190502_0413.py deleted file mode 100644 index a6e5d96..0000000 --- a/users/migrations/0018_auto_20190502_0413.py +++ /dev/null @@ -1,22 +0,0 @@ -# Generated by Django 2.2 on 2019-05-02 04:13 - -from django.db import migrations - - -class Migration(migrations.Migration): - dependencies = [ - ('users', '0017_auto_20190502_0408'), - ] - - operations = [ - migrations.RenameField( - model_name='user', - old_name='change_password_key', - new_name='forgot_password_key', - ), - migrations.RenameField( - model_name='user', - old_name='change_password_key_expires', - new_name='forgot_password_key_expires', - ), - ] diff --git a/users/migrations/0019_auto_20190502_0649.py b/users/migrations/0019_auto_20190502_0649.py deleted file mode 100644 index 43bd26f..0000000 --- a/users/migrations/0019_auto_20190502_0649.py +++ /dev/null @@ -1,32 +0,0 @@ -# Generated by Django 2.2 on 2019-05-02 06:49 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('users', '0018_auto_20190502_0413'), - ] - - operations = [ - migrations.AlterField( - model_name='user', - name='activation_key', - field=models.TextField(blank=True, null=True), - ), - migrations.AlterField( - model_name='user', - name='forgot_password_key', - field=models.TextField(blank=True, null=True), - ), - migrations.AlterField( - model_name='user', - name='forgot_password_key_expires', - field=models.DateTimeField(blank=True, null=True), - ), - migrations.AlterField( - model_name='user', - name='key_expires', - field=models.DateTimeField(blank=True, null=True), - ), - ] diff --git a/users/migrations/0020_auto_20190511_2341.py b/users/migrations/0020_auto_20190511_2341.py deleted file mode 100644 index 9b395eb..0000000 --- a/users/migrations/0020_auto_20190511_2341.py +++ /dev/null @@ -1,21 +0,0 @@ -# Generated by Django 2.2 on 2019-05-11 23:41 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('users', '0019_auto_20190502_0649'), - ] - - operations = [ - migrations.RemoveField( - model_name='profile', - name='profile_updated', - ), - migrations.AddField( - model_name='profile', - name='first_login', - field=models.BooleanField(default=True), - ), - ] diff --git a/users/migrations/0021_auto_20190511_2344.py b/users/migrations/0021_auto_20190511_2344.py deleted file mode 100644 index 253e413..0000000 --- a/users/migrations/0021_auto_20190511_2344.py +++ /dev/null @@ -1,21 +0,0 @@ -# Generated by Django 2.2 on 2019-05-11 23:44 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('users', '0020_auto_20190511_2341'), - ] - - operations = [ - migrations.RemoveField( - model_name='profile', - name='itu_email', - ), - migrations.AddField( - model_name='profile', - name='student_email', - field=models.EmailField(blank=True, max_length=254, verbose_name='student email address'), - ), - ] diff --git a/users/migrations/0022_auto_20190517_1924.py b/users/migrations/0022_auto_20190517_1924.py deleted file mode 100644 index e0e4de5..0000000 --- a/users/migrations/0022_auto_20190517_1924.py +++ /dev/null @@ -1,22 +0,0 @@ -# Generated by Django 2.2 on 2019-05-17 19:24 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('users', '0021_auto_20190511_2344'), - ] - - operations = [ - migrations.RenameField( - model_name='profile', - old_name='profile_photo', - new_name='profile_photo_social', - ), - migrations.AddField( - model_name='profile', - name='profile_photo_custom', - field=models.FileField(blank=True, null=True, upload_to=''), - ), - ] diff --git a/users/migrations/0023_profile_synching.py b/users/migrations/0023_profile_synching.py deleted file mode 100644 index 1f5b79f..0000000 --- a/users/migrations/0023_profile_synching.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 2.2 on 2019-05-28 21:49 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('users', '0022_auto_20190517_1924'), - ] - - operations = [ - migrations.AddField( - model_name='profile', - name='synching', - field=models.BooleanField(default=False), - ), - ] diff --git a/users/migrations/0024_profile_user_type.py b/users/migrations/0024_profile_user_type.py deleted file mode 100644 index 6f64a14..0000000 --- a/users/migrations/0024_profile_user_type.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 2.2 on 2019-08-03 20:47 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('users', '0023_profile_synching'), - ] - - operations = [ - migrations.AddField( - model_name='profile', - name='user_type', - field=models.IntegerField(default=0), - ), - ] diff --git a/users/migrations/0025_remove_profile_linkedin_info.py b/users/migrations/0025_remove_profile_linkedin_info.py deleted file mode 100644 index 249ff1b..0000000 --- a/users/migrations/0025_remove_profile_linkedin_info.py +++ /dev/null @@ -1,16 +0,0 @@ -# Generated by Django 2.2 on 2019-08-04 02:08 - -from django.db import migrations - - -class Migration(migrations.Migration): - dependencies = [ - ('users', '0024_profile_user_type'), - ] - - operations = [ - migrations.RemoveField( - model_name='profile', - name='linkedin_info', - ), - ] diff --git a/users/migrations/0026_auto_20190804_0324.py b/users/migrations/0026_auto_20190804_0324.py deleted file mode 100644 index db4c9ad..0000000 --- a/users/migrations/0026_auto_20190804_0324.py +++ /dev/null @@ -1,45 +0,0 @@ -# Generated by Django 2.2 on 2019-08-04 03:24 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('college', '0004_auto_20190804_0034'), - ('company', '0002_auto_20190429_2110'), - ('position', '0003_auto_20190510_2037'), - ('users', '0025_remove_profile_linkedin_info'), - ] - - operations = [ - migrations.AddField( - model_name='profile', - name='college', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, - to='college.College'), - ), - migrations.AddField( - model_name='profile', - name='company', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, - to='company.Company'), - ), - migrations.AddField( - model_name='profile', - name='grad_year', - field=models.IntegerField(blank=True, max_length=4, null=True), - ), - migrations.AddField( - model_name='profile', - name='job_position', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, - to='position.JobPosition'), - ), - migrations.AddField( - model_name='profile', - name='major', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, - to='college.Major'), - ), - ] diff --git a/users/migrations/0027_auto_20190804_0324.py b/users/migrations/0027_auto_20190804_0324.py deleted file mode 100644 index a1685fe..0000000 --- a/users/migrations/0027_auto_20190804_0324.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 2.2 on 2019-08-04 03:24 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('users', '0026_auto_20190804_0324'), - ] - - operations = [ - migrations.AlterField( - model_name='profile', - name='grad_year', - field=models.IntegerField(blank=True, null=True), - ), - ] diff --git a/users/migrations/0028_auto_20190805_2126.py b/users/migrations/0028_auto_20190805_2126.py deleted file mode 100644 index 9a056c6..0000000 --- a/users/migrations/0028_auto_20190805_2126.py +++ /dev/null @@ -1,26 +0,0 @@ -# Generated by Django 2.2 on 2019-08-05 21:26 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('utils', '0004_import_country_data_from_json'), - ('users', '0027_auto_20190804_0324'), - ] - - operations = [ - migrations.AddField( - model_name='profile', - name='country', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, - to='utils.Country'), - ), - migrations.AddField( - model_name='profile', - name='state', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, - to='utils.State'), - ), - ] diff --git a/users/migrations/0029_remove_profile_first_login.py b/users/migrations/0029_remove_profile_first_login.py deleted file mode 100644 index 703cf57..0000000 --- a/users/migrations/0029_remove_profile_first_login.py +++ /dev/null @@ -1,16 +0,0 @@ -# Generated by Django 2.2 on 2019-08-06 06:52 - -from django.db import migrations - - -class Migration(migrations.Migration): - dependencies = [ - ('users', '0028_auto_20190805_2126'), - ] - - operations = [ - migrations.RemoveField( - model_name='profile', - name='first_login', - ), - ] diff --git a/users/migrations/0030_auto_20190806_0715.py b/users/migrations/0030_auto_20190806_0715.py deleted file mode 100644 index 4895221..0000000 --- a/users/migrations/0030_auto_20190806_0715.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2 on 2019-08-06 07:15 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('users', '0029_remove_profile_first_login'), - ] - - operations = [ - migrations.AlterField( - model_name='profile', - name='user_type', - field=models.IntegerField( - choices=[(0, 'NONE'), (1, 'PUBLIC'), (2, 'STUDENT'), (3, 'ALUMNI'), (4, 'CAREER SERVICE')], default=0), - ), - ] diff --git a/users/migrations/0031_auto_20190807_0533.py b/users/migrations/0031_auto_20190807_0533.py deleted file mode 100644 index 8012ab9..0000000 --- a/users/migrations/0031_auto_20190807_0533.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 2.2 on 2019-08-07 05:33 - -import django.core.files.storage -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('users', '0030_auto_20190806_0715'), - ] - - operations = [ - migrations.AlterField( - model_name='profile', - name='profile_photo_custom', - field=models.FileField(blank=True, null=True, storage=django.core.files.storage.FileSystemStorage( - location='/Users/hellsayenci/Documents/web_projects/JobHax/JobHaxBackend/JH_RestAPI/media/user'), - upload_to=''), - ), - ] diff --git a/users/migrations/0032_auto_20190807_0601.py b/users/migrations/0032_auto_20190807_0601.py deleted file mode 100644 index 7a21ff7..0000000 --- a/users/migrations/0032_auto_20190807_0601.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 2.2 on 2019-08-07 06:01 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('users', '0031_auto_20190807_0533'), - ] - - operations = [ - migrations.AlterField( - model_name='profile', - name='profile_photo_custom', - field=models.FileField(blank=True, null=True, upload_to=''), - ), - ] diff --git a/users/migrations/0033_auto_20190807_0847.py b/users/migrations/0033_auto_20190807_0847.py deleted file mode 100644 index a3b69b7..0000000 --- a/users/migrations/0033_auto_20190807_0847.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 2.2 on 2019-08-07 08:47 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('major', '0001_initial'), - ('users', '0032_auto_20190807_0601'), - ] - - operations = [ - migrations.AlterField( - model_name='profile', - name='major', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, - to='major.Major'), - ), - ] diff --git a/users/migrations/0034_feedback_created_date.py b/users/migrations/0034_feedback_created_date.py deleted file mode 100644 index 4620bfa..0000000 --- a/users/migrations/0034_feedback_created_date.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2 on 2019-08-20 05:43 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0033_auto_20190807_0847'), - ] - - operations = [ - migrations.AddField( - model_name='feedback', - name='created_date', - field=models.DateTimeField(auto_now_add=True, null=True), - ), - ] diff --git a/users/migrations/0035_delete_employmentauth.py b/users/migrations/0035_delete_employmentauth.py deleted file mode 100644 index 37a85dd..0000000 --- a/users/migrations/0035_delete_employmentauth.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 2.2 on 2019-09-11 18:58 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('review', '0010_auto_20190911_1158'), - ('users', '0034_feedback_created_date'), - ] - - operations = [ - migrations.DeleteModel( - name='EmploymentAuth', - ), - ] diff --git a/users/migrations/0036_auto_20190916_1253.py b/users/migrations/0036_auto_20190916_1253.py deleted file mode 100644 index 0179d5c..0000000 --- a/users/migrations/0036_auto_20190916_1253.py +++ /dev/null @@ -1,136 +0,0 @@ -# Generated by Django 2.2 on 2019-09-16 19:53 - -import django.core.validators -from django.db import migrations, models -import django.db.models.deletion -from django.contrib.auth import get_user_model - - -class Migration(migrations.Migration): - - dependencies = [ - ('college', '0005_delete_major'), - ('utils', '0004_import_country_data_from_json'), - ('company', '0002_auto_20190429_2110'), - ('position', '0003_auto_20190510_2037'), - ('major', '0001_initial'), - ('users', '0035_delete_employmentauth'), - ] - - def move_data(apps, schema_editor): - Profile = apps.get_model('users', 'Profile') - for profile in Profile.objects.all(): - user = profile.user - user.gmail_last_update_time = profile.gmail_last_update_time - user.user_type = profile.user_type - user.is_gmail_read_ok = profile.is_gmail_read_ok - user.synching = profile.synching - user.gender = profile.gender - user.dob = profile.dob - user.student_email = profile.student_email - user.phone_number = profile.phone_number - user.profile_photo_social = profile.profile_photo_social - user.profile_photo_custom = profile.profile_photo_custom - user.emp_status = profile.emp_status - user.college = profile.college - user.major = profile.major - user.grad_year = profile.grad_year - user.company = profile.company - user.job_position = profile.job_position - user.country = profile.country - user.state = profile.state - user.save() - - operations = [ - migrations.AddField( - model_name='user', - name='college', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='college.College'), - ), - migrations.AddField( - model_name='user', - name='company', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='company.Company'), - ), - migrations.AddField( - model_name='user', - name='country', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='utils.Country'), - ), - migrations.AddField( - model_name='user', - name='dob', - field=models.DateField(blank=True, null=True), - ), - migrations.AddField( - model_name='user', - name='emp_status', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='users.EmploymentStatus'), - ), - migrations.AddField( - model_name='user', - name='gender', - field=models.CharField(choices=[('M', 'Male'), ('F', 'Female'), ('N', 'None')], default='N', max_length=1), - ), - migrations.AddField( - model_name='user', - name='gmail_last_update_time', - field=models.IntegerField(default=0), - ), - migrations.AddField( - model_name='user', - name='grad_year', - field=models.IntegerField(blank=True, null=True), - ), - migrations.AddField( - model_name='user', - name='is_gmail_read_ok', - field=models.BooleanField(default=True), - ), - migrations.AddField( - model_name='user', - name='job_position', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='position.JobPosition'), - ), - migrations.AddField( - model_name='user', - name='major', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='major.Major'), - ), - migrations.AddField( - model_name='user', - name='phone_number', - field=models.CharField(blank=True, max_length=17, validators=[django.core.validators.RegexValidator(message="Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed.", regex='^\\+?1?\\d{9,15}$')]), - ), - migrations.AddField( - model_name='user', - name='profile_photo_custom', - field=models.FileField(blank=True, null=True, upload_to=''), - ), - migrations.AddField( - model_name='user', - name='profile_photo_social', - field=models.CharField(blank=True, max_length=200), - ), - migrations.AddField( - model_name='user', - name='state', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='utils.State'), - ), - migrations.AddField( - model_name='user', - name='student_email', - field=models.EmailField(blank=True, max_length=254, verbose_name='student email address'), - ), - migrations.AddField( - model_name='user', - name='synching', - field=models.BooleanField(default=False), - ), - migrations.AddField( - model_name='user', - name='user_type', - field=models.IntegerField(choices=[(0, 'NONE'), (1, 'PUBLIC'), (2, 'STUDENT'), (3, 'ALUMNI'), (4, 'CAREER SERVICE')], default=0), - ), - migrations.RunPython(move_data, reverse_code=migrations.RunPython.noop), - ] diff --git a/users/migrations/0037_delete_profile.py b/users/migrations/0037_delete_profile.py deleted file mode 100644 index f1e26f9..0000000 --- a/users/migrations/0037_delete_profile.py +++ /dev/null @@ -1,15 +0,0 @@ -# Generated by Django 2.2 on 2019-09-16 20:21 -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0036_auto_20190916_1253'), - ] - - operations = [ - migrations.DeleteModel( - name='Profile', - ), - ] diff --git a/users/migrations/0038_auto_20190916_1353.py b/users/migrations/0038_auto_20190916_1353.py deleted file mode 100644 index 9b2bfef..0000000 --- a/users/migrations/0038_auto_20190916_1353.py +++ /dev/null @@ -1,35 +0,0 @@ -# Generated by Django 2.2 on 2019-09-16 20:47 -from django.core.files import File -from django.db import migrations -import uuid -from urllib.request import urlretrieve -from urllib.error import HTTPError -import os -from django.contrib.auth import get_user_model - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0037_delete_profile'), - ] - - def move_data(apps, schema_editor): - User = apps.get_model('users', 'User') - for user in User.objects.all(): - if not user.profile_photo_custom.name: - if user.profile_photo_social is not None and user.profile_photo_social is not '': - try: - urlretrieve(user.profile_photo_social, filename=user.profile_photo_social.split('/')[-1]) - file = open(user.profile_photo_social.split('/')[-1], 'rb') - filename = "%s.%s" % (uuid.uuid4(), 'jpg') - user.profile_photo_custom.save(filename, File(file), save=True) - os.remove(user.profile_photo_social.split('/')[-1]) - except FileNotFoundError as err: - pass # something wrong with local path - except HTTPError as err: - pass # something wrong with url - - operations = [ - migrations.RunPython(move_data, reverse_code=migrations.RunPython.noop), - ] diff --git a/users/migrations/0039_auto_20190916_1408.py b/users/migrations/0039_auto_20190916_1408.py deleted file mode 100644 index 05bd23a..0000000 --- a/users/migrations/0039_auto_20190916_1408.py +++ /dev/null @@ -1,22 +0,0 @@ -# Generated by Django 2.2 on 2019-09-16 21:08 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0038_auto_20190916_1353'), - ] - - operations = [ - migrations.RenameField( - model_name='user', - old_name='profile_photo_custom', - new_name='profile_photo', - ), - migrations.RemoveField( - model_name='user', - name='profile_photo_social', - ), - ] diff --git a/users/migrations/0040_user_is_demo.py b/users/migrations/0040_user_is_demo.py deleted file mode 100644 index 3e28182..0000000 --- a/users/migrations/0040_user_is_demo.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2 on 2019-09-17 17:55 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0039_auto_20190916_1408'), - ] - - operations = [ - migrations.AddField( - model_name='user', - name='is_demo', - field=models.BooleanField(default=False), - ), - ] diff --git a/users/migrations/0041_feedback_from_demo_account.py b/users/migrations/0041_feedback_from_demo_account.py deleted file mode 100644 index dc0aeeb..0000000 --- a/users/migrations/0041_feedback_from_demo_account.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2 on 2019-09-28 19:37 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0040_user_is_demo'), - ] - - operations = [ - migrations.AddField( - model_name='feedback', - name='from_demo_account', - field=models.BooleanField(default=False), - ), - ] diff --git a/users/migrations/0042_user_is_email_public.py b/users/migrations/0042_user_is_email_public.py deleted file mode 100644 index 900fa12..0000000 --- a/users/migrations/0042_user_is_email_public.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2 on 2019-09-28 22:32 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0041_feedback_from_demo_account'), - ] - - operations = [ - migrations.AddField( - model_name='user', - name='is_email_public', - field=models.BooleanField(default=True), - ), - ] diff --git a/users/migrations/0044_remove_user_user_type.py b/users/migrations/0044_remove_user_user_type.py deleted file mode 100644 index 3f5e143..0000000 --- a/users/migrations/0044_remove_user_user_type.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 2.2 on 2019-09-28 23:57 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0043_usertype'), - ] - - operations = [ - migrations.RemoveField( - model_name='user', - name='user_type', - ), - ] diff --git a/users/migrations/0045_auto_20190928_1657.py b/users/migrations/0045_auto_20190928_1657.py deleted file mode 100644 index 84d881e..0000000 --- a/users/migrations/0045_auto_20190928_1657.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2 on 2019-09-28 23:57 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0044_remove_user_user_type'), - ] - - operations = [ - migrations.RenameField( - model_name='user', - old_name='type', - new_name='user_type', - ), - ] diff --git a/users/migrations/0046_auto_20190928_1725.py b/users/migrations/0046_auto_20190928_1725.py deleted file mode 100644 index edddd54..0000000 --- a/users/migrations/0046_auto_20190928_1725.py +++ /dev/null @@ -1,33 +0,0 @@ -# Generated by Django 2.2 on 2019-09-29 00:25 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0045_auto_20190928_1657'), - ] - - operations = [ - migrations.AddField( - model_name='usertype', - name='alumni_listing_enabled', - field=models.BooleanField(default=False), - ), - migrations.AddField( - model_name='usertype', - name='blog_creation_enabled', - field=models.BooleanField(default=False), - ), - migrations.AddField( - model_name='usertype', - name='college_specific_metrics_enabled', - field=models.BooleanField(default=False), - ), - migrations.AddField( - model_name='usertype', - name='event_creation_enabled', - field=models.BooleanField(default=False), - ), - ] diff --git a/users/migrations/0047_user_profile_update_completed.py b/users/migrations/0047_user_profile_update_completed.py deleted file mode 100644 index 74eaeed..0000000 --- a/users/migrations/0047_user_profile_update_completed.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2 on 2019-09-30 03:20 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0046_auto_20190928_1725'), - ] - - operations = [ - migrations.AddField( - model_name='user', - name='profile_update_completed', - field=models.BooleanField(default=False), - ), - ] diff --git a/users/migrations/0048_auto_20190929_2057.py b/users/migrations/0048_auto_20190929_2057.py deleted file mode 100644 index 6f1b05b..0000000 --- a/users/migrations/0048_auto_20190929_2057.py +++ /dev/null @@ -1,27 +0,0 @@ -# Generated by Django 2.2 on 2019-09-30 03:57 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0047_user_profile_update_completed'), - ] - - def update_profile_update_completed(apps, schema_editor): - User = apps.get_model('users', 'User') - users = User.objects.all() - for user in users: - if user.user_type is not None and user.user_type.name != 'Undefined': - user.signup_flow_completed = True - user.save() - - operations = [ - migrations.RenameField( - model_name='user', - old_name='profile_update_completed', - new_name='signup_flow_completed', - ), - migrations.RunPython(update_profile_update_completed, reverse_code=migrations.RunPython.noop) - ] diff --git a/users/urls.py b/users/urls.py index d7dbd62..f170452 100644 --- a/users/urls.py +++ b/users/urls.py @@ -11,7 +11,6 @@ path('linkSocialAccount/', views.link_social_account), path('logout/', views.logout), path('updateGmailToken/', views.update_gmail_token), - path('syncUserEmails/', views.sync_user_emails), path('activate/', views.activate_user), path('sendActivationCode/', views.send_activation_code), path('forgotPassword/', views.forgot_password), diff --git a/users/views.py b/users/views.py index b510600..a7a6f5e 100644 --- a/users/views.py +++ b/users/views.py @@ -16,8 +16,6 @@ from rest_framework.decorators import api_view from rest_framework.parsers import JSONParser from social_django.models import UserSocialAuth - -from blog.models import Blog from college.models import College from company.utils import get_or_create_company from major.utils import insert_or_update_major @@ -25,14 +23,9 @@ from utils import utils from utils.error_codes import ResponseCodes from utils.generic_json_creator import create_response -from utils.gmail_lookup import fetch_job_applications from utils.linkedin_utils import get_access_token_with_code from utils.logger import log from utils.models import Country, State -from jobapps.models import JobApplication, GoogleMail -from event.models import Event, EventAttendee -from poll.models import Vote -from review.models import Review from utils.utils import send_notification_email_to_admins, get_boolean_from_request from .models import EmploymentStatus, UserType from .models import Feedback @@ -64,10 +57,7 @@ def register(request): linkedin_auth_code = body['linkedin_auth_code'] if 'google_access_token' in body: google_access_token = body['google_access_token'] - if 'user_type' in body: - user_type = UserType.objects.get(pk=body['user_type']) - else: - user_type = UserType.objects.get(name__iexact='Undefined') + user_type, new = UserType.objects.get_or_create(name__iexact='Employer') username = body['username'] email = body['email'] password = body['password'] @@ -107,7 +97,7 @@ def register(request): 'grant_type': 'password', 'username': username, 'password': password} - response = requests.post('http://localhost:8000/auth/token', data=json.dumps( + response = requests.post('http://localhost:8001/auth/token', data=json.dumps( post_data), headers={'content-type': 'application/json'}) json_res = json.loads(response.text) if 'error' in json_res: @@ -128,7 +118,7 @@ def register(request): else: post_data['backend'] = 'google-oauth2' post_data['token'] = body['google_access_token'] - response = requests.post('http://localhost:8000/auth/convert-token', + response = requests.post('http://localhost:8001/auth/convert-token', data=json.dumps(post_data), headers={'content-type': 'application/json'}) jsonres = json.loads(response.text) log(jsonres, 'e') @@ -139,13 +129,6 @@ def register(request): social_user = UserSocialAuth.objects.get(extra_data__icontains=post_data['token']) if social_user.user.email != user.email: - JobApplication.objects.filter(user=social_user.user).update(user=user) - GoogleMail.objects.filter(user=social_user.user).update(user=user) - Event.objects.filter(host_user=social_user.user).update(host_user=user) - EventAttendee.objects.filter(user=social_user.user).update(user=user) - Vote.objects.filter(user=social_user.user).update(user=user) - Review.objects.filter(user=social_user.user).update(user=user) - Blog.objects.filter(user=social_user.user).update(user=user) social_user.user.delete() social_user.user = user @@ -298,7 +281,7 @@ def login(request): return JsonResponse(create_response(data=None, success=False, error_code=ResponseCodes.verify_recaptcha_failed), safe=False) - response = requests.post('http://localhost:8000/auth/token', data=json.dumps( + response = requests.post('http://localhost:8001/auth/token', data=json.dumps( post_data), headers={'content-type': 'application/json'}) json_res = json.loads(response.text) if 'error' in json_res: @@ -319,7 +302,7 @@ def logout(request): post_data = {'token': body['token'], 'client_id': body['client_id'], 'client_secret': body['client_secret']} headers = {'content-type': 'application/json'} - response = requests.post('http://localhost:8000/auth/revoke-token', + response = requests.post('http://localhost:8001/auth/revoke-token', data=json.dumps(post_data), headers=headers) if response.status_code is 204 or response.status_code is 200: success = True @@ -392,10 +375,8 @@ def update_profile(request): if EmploymentStatus.objects.filter(pk=body['emp_status_id']).count() > 0: user.emp_status = EmploymentStatus.objects.get( pk=body['emp_status_id']) - if 'user_type' in body: - user.user_type = UserType.objects.get(pk=body['user_type']) - elif user.user_type is None: - user.user_type = UserType.objects.get(name__iexact='Undefined') + user_type, new = UserType.objects.get_or_create(name__iexact='Employer') + if 'college_id' in body: if College.objects.filter(pk=body['college_id']).count() > 0: user.college = College.objects.get( @@ -449,7 +430,7 @@ def link_social_account(request): else: return JsonResponse( create_response(data=None, success=False, error_code=ResponseCodes.account_already_linked), safe=False) - response = requests.post('http://localhost:8000/auth/convert-token', + response = requests.post('http://localhost:8001/auth/convert-token', data=json.dumps(post_data), headers={'content-type': 'application/json'}) json_res = json.loads(response.text) log(json_res, 'e') @@ -460,13 +441,6 @@ def link_social_account(request): social_user = UserSocialAuth.objects.get(extra_data__icontains=post_data['token']) if social_user.user.email != request.user.email: - JobApplication.objects.filter(user=social_user.user).update(user=request.user) - GoogleMail.objects.filter(user=social_user.user).update(user=request.user) - Event.objects.filter(host_user=social_user.user).update(host_user=request.user) - EventAttendee.objects.filter(user=social_user.user).update(user=request.user) - Vote.objects.filter(user=social_user.user).update(user=request.user) - Review.objects.filter(user=social_user.user).update(user=request.user) - Blog.objects.filter(publisher_profile=social_user.user).update(publisher_profile=request.user) social_user.user.delete() social_user.user = request.user @@ -475,14 +449,13 @@ def link_social_account(request): post_data = {'token': json_res['access_token'], 'client_id': body['client_id'], 'client_secret': body['client_secret']} headers = {'content-type': 'application/json'} - response = requests.post('http://localhost:8000/auth/revoke-token', + response = requests.post('http://localhost:8001/auth/revoke-token', data=json.dumps(post_data), headers=headers) log(str(response), 'e') if provider == 'google-oauth2': request.user.is_gmail_read_ok = True request.user.save() - schedule_fetcher(request.user.id) return JsonResponse(create_response(data=ProfileSerializer(instance=request.user, many=False).data), safe=False) return JsonResponse(create_response(data=None, success=success, error_code=code), safe=False) @@ -503,7 +476,7 @@ def auth_social_user(request): post_data['token'] = get_access_token_with_code(body['token']) else: post_data['token'] = body['token'] - response = requests.post('http://localhost:8000/auth/convert-token', + response = requests.post('http://localhost:8001/auth/convert-token', data=json.dumps(post_data), headers={'content-type': 'application/json'}) json_res = json.loads(response.text) log(json_res, 'e') @@ -514,10 +487,8 @@ def auth_social_user(request): success = True code = ResponseCodes.success user = AccessToken.objects.get(token=json_res['access_token']).user - if 'user_type' in body: - user.user_type = UserType.objects.get(pk=body['user_type']) - elif user.user_type is None: - user.user_type = UserType.objects.get(name__iexact='Undefined') + if user.user_type is None: + user.user_type, new = UserType.objects.get_or_create(name__iexact='Employer') json_res['user_type'] = UserTypeSerializer(instance=user.user_type, many=False).data json_res['signup_flow_completed'] = user.signup_flow_completed user.approved = True @@ -525,41 +496,15 @@ def auth_social_user(request): if provider == 'google-oauth2': user.is_gmail_read_ok = True user.save() - schedule_fetcher(user.id) return JsonResponse(create_response(data=json_res, success=success, error_code=code), safe=False) - -@background(schedule=1) -def schedule_fetcher(user_id): - user = User.objects.get(pk=user_id) - if user.social_auth.filter(provider='google-oauth2'): - user.synching = True - user.save() - fetch_job_applications(user) - - -@csrf_exempt -@api_view(["GET"]) -def sync_user_emails(request): - if not request.user.is_gmail_read_ok: - return JsonResponse(create_response(data=None, success=False, error_code=ResponseCodes.google_token_expired), - safe=False) - # it'll be used for background tasking in production - # refs. https://medium.com/@robinttt333/running-background-tasks-in-django-f4c1d3f6f06e - # https://django-background-tasks.readthedocs.io/en/latest/ - # https://stackoverflow.com/questions/41205607/how-to-activate-the-process-queue-in-django-background-tasks - # schedule_fetcher.now(request.user.id) - schedule_fetcher(request.user.id) - return JsonResponse(create_response(data=None), safe=False) - - @require_POST @csrf_exempt def refresh_token(request): body = JSONParser().parse(request) post_data = {'client_id': body['client_id'], 'client_secret': body['client_secret'], 'grant_type': 'refresh_token', 'refresh_token': body['refresh_token']} - response = requests.post('http://localhost:8000/auth/token', data=json.dumps( + response = requests.post('http://localhost:8001/auth/token', data=json.dumps( post_data), headers={'content-type': 'application/json'}) json_res = json.loads(response.text) if 'error' in json_res: @@ -609,7 +554,6 @@ def update_gmail_token(request): request.user.is_gmail_read_ok = True request.user.save() code = ResponseCodes.success - schedule_fetcher(request.user.id) else: success = False code = ResponseCodes.user_profile_not_found diff --git a/utils/gmail_lookup.py b/utils/gmail_lookup.py deleted file mode 100644 index d197872..0000000 --- a/utils/gmail_lookup.py +++ /dev/null @@ -1,377 +0,0 @@ -from __future__ import print_function - -import base64 -import string -import traceback -from datetime import datetime - -import requests -from bs4 import BeautifulSoup as bs -from django.contrib.auth import get_user_model -from googleapiclient import errors -from googleapiclient.discovery import build - -from company.utils import get_or_create_company -from jobapps.models import ApplicationStatus -from jobapps.models import GoogleMail -from jobapps.models import JobApplication -from jobapps.models import Source -from jobapps.models import StatusHistory -from position.utils import get_or_insert_position -from utils.logger import log -from .gmail_utils import convert_time -from .gmail_utils import find_nth -from .gmail_utils import remove_html_tags -from .gmail_utils import unicode_to_ascii -from .social_auth_credentials import Credentials - -User = get_user_model() - - -def get_email_detail(service, user_id, msg_id, user, source): - """Get a Message with given ID. - Args: - service: Authorized Gmail API service instance. - user_id: User's email address. The special value "me" - can be used to indicate the authenticated user. - msg_id: The ID of the Message required. - Returns: - A Message. - """ - try: - if JobApplication.objects.all().filter(msg_id=msg_id).count() > 0: - log('this email parsed before', 'e') - return - message = service.users().messages().get( - userId=user_id, id=msg_id, format='full').execute() - mail_from = None - mail_subject = None - mail_body = None - original_date = None - for header in message['payload']['headers']: - if header['name'] == 'Subject': - mail_subject = str(header['value']) - if mail_from is not None and original_date is not None: - break - elif header['name'] == 'From': - mail_from = str(header['value']) - if mail_subject is not None and original_date is not None: - break - elif header['name'] == 'Date': - date = header['value'] - original_date = header['value'] - date = convert_time(str(date)) - if 'parts' not in message['payload']: - if message['payload']['mimeType'] == 'text/html' and int(message['payload']['body']['size']) > 0: - mail_body = str(base64.urlsafe_b64decode( - message['payload']['body']['data'].encode('ASCII'))) - else: - mail_body = None - else: - for part in message['payload']['parts']: - if (part['mimeType'] == 'text/html'): - # get mail's body as a string - mail_body = str(base64.urlsafe_b64decode( - part['body']['data'].encode('ASCII'))) - break - else: - mail_body = None - - if original_date is None: - log(mail_subject, 'e') - log(str(message['payload']['headers']), 'e') - - if mail_subject is not None and mail_body is not None and original_date is not None: - inserted_before = GoogleMail.objects.all().filter(msg_id=msg_id) - if inserted_before.count() == 0: - app_source = Source.objects.get(value__iexact=source) - mail = GoogleMail(user=user, subject=mail_subject, body=mail_body, date=date, msg_id=msg_id, - app_source=app_source) - mail.save() - else: - mail = inserted_before[0] - else: - mail = None - - job_title = '' - company = '' - image_url = '' - - if source == 'LinkedIn': - # job_title and company are in the subject in LinkedIn mails - # we should find them in the subject - if 'for ' in mail_subject and ' at ' in mail_subject: - job_title = mail_subject[mail_subject.index( - 'for ') + 4: mail_subject.index(' at ')] - if 'at ' in mail_subject: - company = mail_subject[mail_subject.index('at ') + 3:] - - if mail_body is not None: - # trying to find company logo in the body - s = find_nth(mail_body, 'https://media.licdn.com', 2) - if s != -1: - e = find_nth(mail_body, '" alt="' + company + '"', 1) - image_url = mail_body[s: e].replace('&', '&') - image_exists = requests.get(image_url) - if len(image_url) > 300: - image_url = None - if image_exists.status_code == 404: - image_url = None - else: - image_url = None - - elif source == 'Vettery': - # job_title and company are in the body in Vettery mails - if mail_body is not None: - if 'Role: ' in mail_body and 'Salary' in mail_body: - job_title = mail_body[mail_body.index( - 'Role: ') + 6: mail_body.index('Salary')] - job_title = remove_html_tags(job_title) - if 'interview with ' in mail_body and '. Interested?' in mail_body: - company = mail_body[mail_body.index( - 'interview with ') + 15: mail_body.index('. Interested?')] - elif 'Our take on ' in mail_body and ':' in mail_body: - company = mail_body[mail_body.index( - 'Our take on ') + 12: mail_body.index(':' in mail_body: - c_start_index = mail_body.index('updates from') + 16 - c_end_index = mail_body[c_start_index: ( - c_start_index + 100)].index('') - company = mail_body[c_start_index: c_start_index + c_end_index] - image_url = None - elif source == 'glassdoor': - # company is in the subject - if 'on to ' in mail_subject and ' completed.' in mail_subject: - company = mail_subject[mail_subject.index( - 'on to ') + 6: mail_subject.index(' completed.')] - - if mail_body is not None: - # job_title is in the body - soup = bs(mail_body, 'html.parser') - images = soup.findAll('img') - for image in images: - if image.has_attr('alt') and image['alt'] == company: - image_url = image['src'] - image_exists = requests.get(image_url) - if image_exists.status_code == 404: - image_url = None - break - job_title = soup.find( - 'a', attrs={'style': 'text-decoration: none; color:#0066cc'}).contents[0] - elif source == 'jobvite.com': - if 'Recruiting Team' in mail_from: - company = mail_from[:mail_from.find(' Recruiting Team')] - if ' for ' in mail_subject and ' at ' in mail_subject: - job_title = mail_subject[mail_subject.index( - ' for ') + 5: mail_subject.index(' at ')] - - if mail_body is not None: - # check the body for more accurate companmy name - if ' at ' in mail_body and '. We' in mail_body: - company = mail_body[mail_body.index( - ' at ') + 4:mail_body.index('. We')] - - # check the body for the job title - if ' the ' in mail_body and ' role at ' + company in mail_body: - job_title = mail_body[mail_body.index( - ' the ') + 5:mail_body.index(' role at ')] - elif ' the ' in mail_body and ' job at ' + company in mail_body: - job_title = mail_body[mail_body.index( - ' the ') + 5:mail_body.index(' job at ')] - else: - # jobinvite sends the approval email with this keyword - return - elif source == 'smartrecruiters.com': - company = mail_subject[mail_subject.rindex( - 'applying to ') + 12:].strip(string.punctuation) - soup = bs(mail_body, 'html.parser') - ps = soup.findAll('p') - first_parag = '' - if len(ps) == 0: - first_parag = soup.text - for p in ps: - if company in p.text: - first_parag = p.text - break - if first_parag != '': - # needs more data to determine the pattern - if ' position of ' in first_parag and '. We' in first_parag: - job_title = first_parag[first_parag.index( - ' position of ') + 13:first_parag.index('. We')] - elif 'application for the ' in first_parag and ', ' + company in first_parag: - job_title = first_parag[ - first_parag.index('application for the ') + 20:first_parag.index(', ' + company)] - elif source == 'greenhouse.io': - pass - elif source == 'lever.co': - company = mail_from[:mail_from.index(' ')] - company = company.replace('"', '') - if 'application for ' in mail_body and '.