Skip to content

Commit

Permalink
VJB-46 Asynchronous actions on vacancies.
Browse files Browse the repository at this point in the history
Actions with vacancies moved to celery tasks.
  • Loading branch information
Klyaus authored and achievement008 committed Jul 2, 2018
1 parent e45bc09 commit a8dea6c
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 33 deletions.
11 changes: 10 additions & 1 deletion vacancy/admin.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from django.contrib import admin
from .models import Vacancy

from .models import Vacancy, CandidateOnVacancy


class AdminVacancy(admin.ModelAdmin):
Expand All @@ -10,4 +11,12 @@ class Meta:
model = Vacancy


class CandidateOnVacancyAdmin(admin.ModelAdmin):
list_display = [f.name for f in CandidateOnVacancy._meta.fields]

class Meta:
model = CandidateOnVacancy


admin.site.register(Vacancy, AdminVacancy)
admin.site.register(CandidateOnVacancy, CandidateOnVacancyAdmin)
9 changes: 6 additions & 3 deletions vacancy/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,16 @@ class Meta:
ordering = ('-updated_at',)


class ProfileOnVacancy(models.Model):
profile = models.ForeignKey('candidateprofile.CandidateProfile',
on_delete=models.CASCADE)
class CandidateOnVacancy(models.Model):
candidate = models.ForeignKey('jobboard.Candidate',
on_delete=models.CASCADE)
vacancy = models.ForeignKey(Vacancy,
on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)

class Meta:
unique_together = (('candidate', 'vacancy'), )


class VacancyOffer(models.Model):
vacancy = models.ForeignKey('vacancy.Vacancy',
Expand Down
30 changes: 20 additions & 10 deletions vacancy/signals/handlers.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
from django.conf import settings
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.conf import settings
from jobboard.handlers.new_candidate import CandidateHandler
from pipeline.models import Pipeline
from vacancy.models import Vacancy, ProfileOnVacancy

from jobboard.handlers.candidate import CandidateHandler
from jobboard.tasks import save_txn_to_history, save_txn
from vacancy.tasks import new_vacancy
from pipeline.models import Pipeline
from vacancy.models import Vacancy, CandidateOnVacancy
from vacancy.tasks import new_vacancy, change_status, change_vacancy_allowed_amount


@receiver(post_save, sender=Vacancy)
Expand All @@ -15,15 +16,24 @@ def handler_new_vacancy(sender, instance, created, **kwargs):
Pipeline.objects.create(vacancy=instance)


@receiver(post_save, sender=ProfileOnVacancy)
@receiver(post_save, sender=CandidateOnVacancy)
def new_subscribe(sender, instance, created, **kwargs):
#TODO change
if created:
candidate_h = CandidateHandler(settings.WEB_ETH_COINBASE, instance.cv.candidate.contract_address)
txn_hash = candidate_h.subscribe(instance.vacancy.uuid, instance.cv.uuid)
candidate_h = CandidateHandler(account=settings.WEB_ETH_COINBASE,
contract_address=instance.candidate.contract_address)
txn_hash = candidate_h.subscribe(instance.vacancy.uuid)
if txn_hash:
user_id = instance.cv.candidate.user.id
user_id = instance.candidate.user.id
save_txn.delay(txn_hash.hex(), 'Subscribe', user_id, instance.vacancy.id)
save_txn_to_history.delay(user_id, txn_hash.hex(), 'Subscribe to vacancy {}'.format(instance.vacancy.title))
else:
instance.delete()


@receiver(post_save, sender=Vacancy)
def change_vacancy_status(sender, instance, created, **kwargs):
if instance.published:
if hasattr(instance, 'change_status') and instance.change_status:
change_status.delay(instance.id)
elif hasattr(instance, 'allowed_changed') and instance.allowed_changed:
change_vacancy_allowed_amount.delay(instance.id)
52 changes: 49 additions & 3 deletions vacancy/tasks.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
from __future__ import absolute_import, unicode_literals

from celery import shared_task
from jobboard.tasks import save_txn, save_txn_to_history

from jobboard.handlers.employer import EmployerHandler
from jobboard.handlers.oracle import OracleHandler
from jobboard.tasks import save_txn, save_txn_to_history
from vacancy.models import Vacancy


Expand All @@ -18,5 +21,48 @@ def new_vacancy(vacancy_id):
int(vacancy.allowed_amount) * 10 ** 18)
if txn_hash:
save_txn_to_history.apply_async(args=(vacancy.employer.user.id, txn_hash.hex(),
'Creation of a new vacancy: {}'.format(vacancy.title)), countdown=2)
save_txn.apply_async(args=(txn_hash.hex(), 'NewVacancy', vacancy.employer.user.id, vacancy.id), countdown=2)
'Creation of a new vacancy: {}'.format(vacancy.title)), countdown=1)
save_txn.apply_async(args=(txn_hash.hex(), 'NewVacancy', vacancy.employer.user.id, vacancy.id), countdown=1)


@shared_task
def change_status(vacancy_id):
try:
vacancy = Vacancy.objects.get(pk=vacancy_id)
except Vacancy.DoesNotExist:
print('Vacancy {} does not exist'.format(vacancy_id))
else:
emp_h = EmployerHandler(vacancy.employer.contract_address)
oracle = OracleHandler()
bch_vacancy = oracle.vacancy(vacancy.uuid)
if bch_vacancy['enabled']:
txn_hash = emp_h.disable_vac(vacancy.uuid)
else:
txn_hash = emp_h.enable_vac(vacancy.uuid)
if txn_hash:
save_txn_to_history.apply_async(args=(vacancy.employer.user.id, txn_hash.hex(),
'Vacancy status changed: {}'.format(vacancy.title)), countdown=1)
save_txn.apply_async(args=(txn_hash.hex(), 'VacancyChange', vacancy.employer.user.id, vacancy.id),
countdown=1)
return True


@shared_task
def change_vacancy_allowed_amount(vacancy_id):
try:
vacancy = Vacancy.objects.get(pk=vacancy_id)
except Vacancy.DoesNotExist:
pass
else:
emp_h = EmployerHandler(vacancy.employer.contract_address)
oracle = OracleHandler()
old_vacancy = oracle.vacancy(vacancy.uuid)
if old_vacancy['allowed_amount'] != int(vacancy.allowed_amount) * 10 ** 18:
txn_hash = emp_h.change_vacancy_allowance_amount(vacancy.uuid, int(vacancy.allowed_amount) * 10 ** 18)
if txn_hash:
save_txn_to_history.apply_async(args=(vacancy.employer.user.id, txn_hash.hex(),
'Vacancy allowed amount changed: {}'.format(vacancy.title)),
countdown=1)
save_txn.apply_async(
args=(txn_hash.hex(), 'VacancyAllowedChanged', vacancy.employer.user.id, vacancy.id),
countdown=1)
33 changes: 17 additions & 16 deletions vacancy/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@
from jobboard.handlers.coin import CoinHandler
from jobboard.handlers.oracle import OracleHandler
from jobboard.mixins import OnlyEmployerMixin, OnlyCandidateMixin
from jobboard.models import Candidate
from statistic.decorators import statistical
from vacancy.forms import VacancyForm, EditVacancyForm
from vacancy.models import Vacancy, ProfileOnVacancy, VacancyOffer
from vacancy.models import Vacancy, CandidateOnVacancy, VacancyOffer

_EMPLOYER, _CANDIDATE = 'employer', 'candidate'

Expand Down Expand Up @@ -56,7 +57,7 @@ def form_valid(self, form):

def process_form_instance(self, form):
form.instance.allowed_amount = form.cleaned_data['allowed_amount']
form.instance.uuid = Web3.toHex(os.urandom(15))
form.instance.uuid = Web3.toHex(os.urandom(32))
return super().form_valid(form)


Expand Down Expand Up @@ -93,32 +94,28 @@ class SubscribeToVacancyView(OnlyCandidateMixin, RedirectView):

def __init__(self, **kwargs):
super().__init__(**kwargs)
self.candidate_profile = None
self.vacancy = None
self.request = None

def get_redirect_url(self, *args, **kwargs):
return reverse('vacancy', kwargs={'pk': kwargs.get('vacancy_id')})

def get(self, request, *args, **kwargs):
self.candidate_profile = get_object_or_404(CandidateProfile,
id=kwargs.get('profile_id'),
candidate=request.role_object)
self.vacancy = get_object_or_404(Vacancy, id=kwargs.get('vacancy_id'))
return self.check_vac_profile(*args, **kwargs)

def check_vac_profile(self, *args, **kwargs):
if not self.vacancy.enabled:
messages.error(self.request, MESSAGES['disabled_vacancy'].format(self.vacancy.title))
elif not self.candidate_profile.enabled:
messages.error(self.request, MESSAGES['disabled_profile'].format(self.candidate_profile.title))
if not self.vacancy.enabled or not self.candidate_profile.enabled:
elif not self.request.role_object.enabled:
messages.error(self.request, MESSAGES['disabled_profile'].format(self.request.role_object.profile.title))
if not self.vacancy.enabled or not self.request.role_object.enabled:
return HttpResponseRedirect(self.get_redirect_url(*args, **kwargs))
else:
return self.subscribe(*args, **kwargs)

def subscribe(self, *args, **kwargs):
ProfileOnVacancy.objects.create(profile=self.candidate_profile, vacancy=self.vacancy)
CandidateOnVacancy.objects.create(candidate=self.request.role_object, vacancy=self.vacancy)
return super().get(self.request, *args, **kwargs)


Expand All @@ -142,6 +139,7 @@ def get(self, request, *args, **kwargs):
if not self.errors:
if self.object.enabled is not None:
self.object.enabled = None
self.object.change_status = True
self.object.save()
else:
for error in set(self.errors):
Expand All @@ -161,16 +159,16 @@ def check_actions(self):
if not self.object.pipeline.actions.exists():
self.errors.append('need_more_actions')
for action in self.object.pipeline.actions.all():
if action.type.condition_of_passage:
method = getattr(self, 'check_' + action.type.condition_of_passage)
if action.action_type.condition_of_passage:
method = getattr(self, 'check_' + action.action_type.condition_of_passage)
method(action)

def check_quiz(self, action):
if not action.exam.exists():
def check_exam(self, action):
if not hasattr(action, 'exam'):
self.errors.append('empty_exam')

def check_interview(self, action):
if not action.interview.exists():
if not hasattr(action, 'interview'):
self.errors.append('empty_interview')


Expand Down Expand Up @@ -199,9 +197,12 @@ class UpdateAllowedView(OnlyEmployerMixin, UpdateView):
fields = ('allowed_amount',)

def post(self, request, *args, **kwargs):
get_object_or_404(Vacancy, pk=kwargs.get('pk'), employer=request.role_object)
vacancy = get_object_or_404(Vacancy, pk=kwargs.get('pk'))
if vacancy.owner != request.user:
return HttpResponse(status=403)
return super().post(request, *args, **kwargs)

def form_valid(self, form):
form.instance.allowed_changed = True
form.save()
return HttpResponse('ok', status=200)

0 comments on commit a8dea6c

Please sign in to comment.