diff --git a/python/apps/fixtures/vacancies.json b/python/apps/fixtures/vacancies.json index 4604e4adb..521916ef4 100644 --- a/python/apps/fixtures/vacancies.json +++ b/python/apps/fixtures/vacancies.json @@ -4,7 +4,7 @@ "pk": 1, "fields": { "uuid": "aada680d-c43b-413b-86db-b63da812832f", - "title": "Django Developer Needed", + "title": "Go Developer Needed", "request": 2, "created_by": 1, "city": "Bishkek", @@ -16,6 +16,9 @@ "image": "", "responsibilities": "qqweqweqweqweqweqweqwe", "comments": "Comment 1", + "diesel": false, + "jobkg":false, + "facebook":true, "created": "2018-07-09T08:05:58.278Z", "last_published": "2018-07-09T08:05:58.278Z" } @@ -30,12 +33,15 @@ "created_by": 1, "city": "Bishkek", "address": "Admin str. 123", - "work_conditions": "[\"Sjdfkgdfklgjkldfgjkl\"]", + "work_conditions": "[\"Mvahahahahahaha\", \"hELOO ASDFADSF\"]", "working_hours": "FULL_TIME", "salary_min": 200.0, "salary_max": 2020.0, "responsibilities": "ergklgjerklgjerklerjgklerjklerjlrgor", "comments": "Comment 2", + "diesel": true, + "jobkg":false, + "facebook":false, "created": "2018-07-09T08:08:01.196Z", "last_published": "2018-07-09T08:08:01.196Z" } @@ -47,12 +53,10 @@ "vacancy": 1, "created_by": 1, "created": "2018-07-09T08:08:01.196Z", - "facebook": false, - "facebook_url": "http://some_url", - "diesel_exist": false, - "diesel_url": "http://some_url", - "jobkg_exist": true, - "jobkg_url": "http://some_url" + "message":"Successfully published to facebook", + "url":"https://facebook.com/adsf", + "publisher_service":"FACEBOOK", + "status":"SUCCESS" } }, { @@ -60,14 +64,13 @@ "pk": 2, "fields": { "vacancy": 2, - "created_by": 2, + "created_by": 1, "created": "2018-07-09T08:08:01.196Z", - "facebook": true, - "facebook_url": "http://some_url", - "diesel_exist": true, - "diesel_url": "http://some_url", - "jobkg_exist": true, - "jobkg_url": "http://some_url" + "message":"Successfully published to diesel", + "url":"https://diesel.kg/adsf", + "publisher_service":"DIESEL", + "status":"SUCCESS" + } } ] diff --git a/python/apps/utils/rabbitmq.py b/python/apps/utils/rabbitmq.py index 530af580a..2cdc95da0 100644 --- a/python/apps/utils/rabbitmq.py +++ b/python/apps/utils/rabbitmq.py @@ -32,7 +32,7 @@ def __init__(self, host='localhost', user='', password=''): self.connection = pika.BlockingConnection(self.parameters) self.channel = self.connection.channel() self.queue = '' - self.response = None + self.uuid = None @staticmethod def message_to_server(query_set, serializer): @@ -42,6 +42,8 @@ def message_to_server(query_set, serializer): message = JSONRenderer().render(serializer.data) + print(message) + return message @staticmethod @@ -60,9 +62,6 @@ def call(self, queryset=None, serializer=None, exchange_name='', exchange_type=' message = self.message_to_server(queryset, serializer) cor_id = json.loads(message) uuid = cor_id['uuid'] - else: - message = message - uuid = '' self.channel.exchange_declare(exchange=exchange_name, exchange_type=exchange_type, durable=False) self.channel.queue_declare(queue=self.queue, durable=False) @@ -84,3 +83,72 @@ def call(self, queryset=None, serializer=None, exchange_name='', exchange_type=' print(" [.] Got %r" % self.response) return self.response + + def on_response(self, ch, method, props, body): + + self.response = body + + def call_java(self, queryset=None, serializer=None, exchange_name='', exchange_type='topic', q_receiving='', + q_sending='', message='', facebook=False): + self.response = None + self.q_sending = q_sending + self.q_receiving = q_receiving + + self.channel.queue_declare(queue=self.q_receiving, durable=True) + self.channel.exchange_declare(exchange=exchange_name, exchange_type=exchange_type, durable=True) + if queryset and serializer: + message = self.message_to_server(queryset, serializer) + if facebook: + message = message.decode('utf-8') + message = json.loads(message) + message['facebook_user_access_token'] = 'EAAVEWZBXPkcQBAOtPLDrQPgBykLVbYoHdmFhwZAjfNhRYK4U0Vus9A2uYSQn41x78ftbSZAvqxZAzTZBx5VVQr4xZBiMQlggHtM4yPa9kDcqC24Q4ZAk9fDD99ry24ncCLjG0Hd1ZB0U4RHyggyCdZC0SI7xrcSWMR5SYPZCKv2pgDke6RZAaA7McnhC7nnk6UZCkx4ZD' + message = json.dumps(message) + content = json.loads(message) + self.uuid = content['uuid'] + + self.channel.basic_consume(self.on_response, + no_ack=True, + queue=q_receiving) + + self.channel.basic_publish(exchange=exchange_name, + routing_key=self.q_sending, + properties=pika.BasicProperties( + delivery_mode=2, # make message persistent + content_type='json' + ), + body=message) + + print(self.response) + while self.response is None: + self.connection.process_data_events() + + print("Self Response:") + print(self.response) + self.connection.close() + return self.response + + def on_request(self, ch, method, properties, body): + print("Have message from the client") + response = body + + ch.basic_publish(exchange='', + routing_key=self.q_sending, + body=response) + + ch.basic_ack(delivery_tag=method.delivery_tag) + + def consume(self, exchange_name='', exchange_type='topic', q_receiving='', q_sending=''): + self.q_receiving = q_receiving + self.q_sending = q_sending + + self.channel.queue_declare(queue=self.q_receiving, durable=True) + self.channel.exchange_declare(exchange=exchange_name, exchange_type=exchange_type, durable=True) + self.channel.queue_bind(exchange=exchange_name, + queue=self.q_receiving, + routing_key=self.q_sending) + print(' [*] Waiting for Messages. To exit press CTRL+C') + + self.channel.basic_consume(self.on_request, + queue=self.q_receiving, + ) + self.channel.start_consuming() diff --git a/python/apps/vacancies/migrations/0022_auto_20180716_1335.py b/python/apps/vacancies/migrations/0022_auto_20180716_1335.py new file mode 100644 index 000000000..dac306a42 --- /dev/null +++ b/python/apps/vacancies/migrations/0022_auto_20180716_1335.py @@ -0,0 +1,56 @@ +# Generated by Django 2.0.6 on 2018-07-16 07:35 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('vacancies', '0021_merge_20180713_1628'), + ] + + operations = [ + migrations.RemoveField( + model_name='publication', + name='created', + ), + migrations.RemoveField( + model_name='publication', + name='diesel_exist', + ), + migrations.RemoveField( + model_name='publication', + name='diesel_url', + ), + migrations.RemoveField( + model_name='publication', + name='facebook', + ), + migrations.RemoveField( + model_name='publication', + name='facebook_url', + ), + migrations.RemoveField( + model_name='publication', + name='jobkg_exist', + ), + migrations.RemoveField( + model_name='publication', + name='jobkg_url', + ), + migrations.AddField( + model_name='vacancy', + name='diesel', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='vacancy', + name='facebook', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='vacancy', + name='jobkg', + field=models.BooleanField(default=False), + ), + ] diff --git a/python/apps/vacancies/migrations/0023_auto_20180716_1406.py b/python/apps/vacancies/migrations/0023_auto_20180716_1406.py new file mode 100644 index 000000000..b359dd2a4 --- /dev/null +++ b/python/apps/vacancies/migrations/0023_auto_20180716_1406.py @@ -0,0 +1,33 @@ +# Generated by Django 2.0.6 on 2018-07-16 08:06 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('vacancies', '0022_auto_20180716_1335'), + ] + + operations = [ + migrations.AddField( + model_name='publication', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AddField( + model_name='publication', + name='message', + field=models.CharField(default='', max_length=200), + ), + migrations.AddField( + model_name='publication', + name='publisher_service', + field=models.CharField(default='', max_length=50), + ), + migrations.AddField( + model_name='publication', + name='status', + field=models.CharField(default='', max_length=50), + ), + ] diff --git a/python/apps/vacancies/migrations/0024_publication_url.py b/python/apps/vacancies/migrations/0024_publication_url.py new file mode 100644 index 000000000..e57d78e8e --- /dev/null +++ b/python/apps/vacancies/migrations/0024_publication_url.py @@ -0,0 +1,18 @@ +# Generated by Django 2.0.6 on 2018-07-16 08:20 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('vacancies', '0023_auto_20180716_1406'), + ] + + operations = [ + migrations.AddField( + model_name='publication', + name='url', + field=models.URLField(null=True), + ), + ] diff --git a/python/apps/vacancies/migrations/0025_auto_20180717_1747.py b/python/apps/vacancies/migrations/0025_auto_20180717_1747.py new file mode 100644 index 000000000..dc73cea35 --- /dev/null +++ b/python/apps/vacancies/migrations/0025_auto_20180717_1747.py @@ -0,0 +1,18 @@ +# Generated by Django 2.0.6 on 2018-07-17 11:47 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('vacancies', '0024_publication_url'), + ] + + operations = [ + migrations.AlterField( + model_name='publication', + name='message', + field=models.CharField(max_length=200, null=True), + ), + ] diff --git a/python/apps/vacancies/models.py b/python/apps/vacancies/models.py index 5bf0c0ca5..96b077416 100644 --- a/python/apps/vacancies/models.py +++ b/python/apps/vacancies/models.py @@ -4,9 +4,7 @@ from django.contrib.postgres.fields import ArrayField from django.db import models from django.urls import reverse - from apps.requests.models import Request - User = get_user_model() WORKING_HOURS = (("FULL_TIME", 'Полный рабочий день'), @@ -24,12 +22,14 @@ class Vacancy(models.Model): address = models.CharField(max_length=50) work_conditions = ArrayField(base_field=models.CharField(max_length=200, blank=True)) working_hours = models.CharField(choices=WORKING_HOURS, max_length=10, default="FULL_TIME") - salary_min = models.FloatField() salary_max = models.FloatField() image = models.ImageField(upload_to='media', null=True) responsibilities = models.TextField(null=True) comments = models.TextField(null=True) + diesel = models.BooleanField(default=False) + jobkg = models.BooleanField(default=False) + facebook = models.BooleanField(default=False) created = models.DateTimeField(auto_now_add=True) last_published = models.DateTimeField(auto_now=True) @@ -44,13 +44,11 @@ def get_absolute_url(self): class Publication(models.Model): vacancy = models.ForeignKey(Vacancy, on_delete=models.PROTECT) created_by = models.ForeignKey(User, on_delete=models.PROTECT) - created = models.DateTimeField(auto_now_add=True) - facebook = models.BooleanField(default=False) - facebook_url = models.URLField(null=True) - diesel_exist = models.BooleanField(default=False) - diesel_url = models.URLField(null=True) - jobkg_exist = models.BooleanField(default=False) - jobkg_url = models.URLField(null=True) + message = models.CharField(max_length=200, null = True) + url = models.URLField(null=True) + publisher_service = models.CharField(max_length=50, default='') + status = models.CharField(max_length=50, default='') + created = models.DateTimeField(auto_now_add=True, null=True) class Meta: default_related_name = 'publications' diff --git a/python/apps/vacancies/serializers.py b/python/apps/vacancies/serializers.py index de6161375..f926effd6 100644 --- a/python/apps/vacancies/serializers.py +++ b/python/apps/vacancies/serializers.py @@ -1,18 +1,24 @@ from rest_framework import serializers -from apps.departments.serializers import RequirementSerializer, DepartmentSerializer +from apps.departments.models import Requirement, Department +from apps.departments.serializers import RequirementSerializer from apps.requests.models import Request from apps.users.serializers import AuxUserSerializer from .models import Vacancy, Publication -from apps.departments.models import Requirement + + +class VacancyDepartmentSerializer(serializers.ModelSerializer): + class Meta: + model = Department + exclude = ['id'] class VacancyRequirementSerializer(serializers.ModelSerializer): - department = DepartmentSerializer() + department = VacancyDepartmentSerializer() class Meta: model = Requirement - fields = ('id', 'department', 'name', 'type') + fields = ('department', 'name', 'type') class VacancyListSerializer(serializers.ModelSerializer): @@ -80,9 +86,3 @@ class Meta: 'salary_min', 'salary_max', 'image', 'responsibilities' ) - -class VacancyPartialUpdateSerializer(serializers.ModelSerializer): - - class Meta: - model = Vacancy - fields = ('working_hours') diff --git a/python/apps/vacancies/tasks.py b/python/apps/vacancies/tasks.py new file mode 100644 index 000000000..c769283f4 --- /dev/null +++ b/python/apps/vacancies/tasks.py @@ -0,0 +1,36 @@ +import json + +from django.conf import settings +from djcelery import celery + +from apps.users.models import User +from apps.utils.rabbitmq import RabbitMQ +from apps.vacancies.models import Vacancy, Publication + + +@celery.task +def send_message_to_java(queryset, serializer, service='', facebook=False): + + rabbit = RabbitMQ(host=settings.RABBITMQ_HOST, user=settings.RABBITMQ_USERNAME, password=settings.RABBITMQ_PASSWORD) + content = rabbit.call_java(queryset, serializer, + exchange_name='share', + q_receiving='shareResponse', + q_sending=service+'.publish', facebook=facebook) + + content = content.decode('utf-8') + + content = json.loads(content) + + vacancy = Vacancy.objects.get(uuid=content['uuid']) + user = User.objects.get(email=vacancy.created_by) + print(content) + data = {"vacancy": vacancy, + "created_by": user, + "message": content['message'], + "url": content['url'], + "status": content['status'], + "publisher_service": content['publisher_service_type'] + } + print(data) + + Publication.objects.create(**data) diff --git a/python/apps/vacancies/views.py b/python/apps/vacancies/views.py index 44b320eb2..f4517660c 100644 --- a/python/apps/vacancies/views.py +++ b/python/apps/vacancies/views.py @@ -1,12 +1,13 @@ +from django.contrib import messages from rest_framework import generics from rest_framework.response import Response -from rest_framework.status import HTTP_201_CREATED +from rest_framework.status import HTTP_201_CREATED, HTTP_200_OK from apps.utils.serializers import MethodSerializerView from .models import Vacancy, Publication -from apps.requests.models import Request from .serializers import VacancyListSerializer, VacancyCreateUpdateSerializer, VacancyDetailSerializer, \ - PublicationListSerializer, PublicationCreateSerializer + PublicationListSerializer, JavaVacancySerializer, PublicationCreateSerializer +from .tasks import send_message_to_java class VacancyListView(generics.ListCreateAPIView): @@ -34,9 +35,21 @@ class PublicationList(MethodSerializerView, generics.ListCreateAPIView): ('POST',): PublicationCreateSerializer } + def create(self, request, *args, **kwargs): + data = request.data + queryset = Vacancy.objects.get(pk=data['vacancy']) + if data['facebook']: + send_message_to_java.delay(queryset, JavaVacancySerializer, 'facebook', facebook=True) + if data['jobkg']: + send_message_to_java.delay(queryset, JavaVacancySerializer, 'jobKg') + if data['diesel']: + send_message_to_java.delay(queryset, JavaVacancySerializer, 'diesel') + + messages.success(self.request, "We are publicating. wait a moment and refresh") + print("Message from create method") + return Response(data, status=HTTP_200_OK) + class PublicationDetail(generics.RetrieveAPIView): queryset = Publication.objects.all() serializer_class = PublicationListSerializer - - diff --git a/python/config/base.py b/python/config/base.py index 508424f41..a64d7ca80 100644 --- a/python/config/base.py +++ b/python/config/base.py @@ -1,5 +1,6 @@ import os +import djcelery from configurations import Configuration, values BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) @@ -39,8 +40,11 @@ class Base(Configuration): 'apps.requests', 'apps.users', 'apps.vacancies', - 'apps.templates' + 'apps.templates', + + 'djcelery', ] + djcelery.setup_loader() SOCIAL_AUTH_RAISE_EXCEPTIONS = True SOCIAL_AUTH_URL_NAMESPACE = 'social' @@ -201,3 +205,14 @@ class Base(Configuration): RABBITMQ_PASSWORD = values.SecretValue() RABBITMQ_HOST = values.SecretValue() RABBITMQ_PORT = values.SecretValue() + + # BROKER_URL = "amqp://{username}:{password}@{host}:{port}//".format( + # + # username=RABBITMQ_USERNAME, + # password=RABBITMQ_PASSWORD, + # host=RABBITMQ_HOST, + # port=RABBITMQ_PORT + # ) + # + + BROKER_URL = "amqp://guest:guest@159.65.153.5:5672//" \ No newline at end of file