Fakultas Ilmu Komputer UI
Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
PMPL
Class Project
Kape
Commits
39ff0f1e
Commit
39ff0f1e
authored
Oct 08, 2019
by
Ichlasul Affan
Browse files
Implement create new milestones
Also updates permission and serializer
parent
f88e9355
Changes
11
Expand all
Hide whitespace changes
Inline
Side-by-side
core/lib/permissions.py
View file @
39ff0f1e
...
...
@@ -6,6 +6,7 @@ from core.models import Student
from
core.models
import
Supervisor
from
core.models
import
Application
from
core.models
import
Vacancy
from
core.models
import
VacancyMilestone
def
is_admin_or_student
(
user
):
...
...
@@ -159,3 +160,22 @@ class VacancyApprovalPermission(permissions.BasePermission):
def
has_object_permission
(
self
,
request
,
view
,
obj
):
return
isinstance
(
obj
,
Vacancy
)
class
IsAdminOrVacancyOwnerOrAuthenticatedReadOnly
(
permissions
.
IsAuthenticated
):
def
has_permission
(
self
,
request
,
view
):
is_authenticated
=
super
(
IsAdminOrVacancyOwnerOrAuthenticatedReadOnly
,
self
).
has_permission
(
request
,
view
)
if
is_authenticated
and
request
.
method
in
permissions
.
SAFE_METHODS
:
return
True
return
is_admin_or_company
(
request
.
user
)
def
has_object_permission
(
self
,
request
,
view
,
obj
):
user
=
request
.
user
if
user
and
request
.
method
in
permissions
.
SAFE_METHODS
:
return
True
if
user
.
is_superuser
or
user
.
is_staff
:
return
True
if
isinstance
(
obj
,
VacancyMilestone
):
return
user
.
company
==
obj
.
vacancy
.
company
raise
PermissionDenied
(
"Checking owner permission on non-milestone object"
)
core/migrations/0014_vacancymilestone.py
0 → 100644
View file @
39ff0f1e
# -*- coding: utf-8 -*-
# Generated by Django 1.11.17 on 2019-10-06 03:23
from
__future__
import
unicode_literals
from
django.db
import
migrations
,
models
import
django.db.models.deletion
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'core'
,
'0013_auto_20170602_1130'
),
]
operations
=
[
migrations
.
CreateModel
(
name
=
'VacancyMilestone'
,
fields
=
[
(
'id'
,
models
.
AutoField
(
auto_created
=
True
,
primary_key
=
True
,
serialize
=
False
,
verbose_name
=
'ID'
)),
(
'name'
,
models
.
CharField
(
max_length
=
100
)),
(
'detail'
,
models
.
TextField
()),
(
'expected_start'
,
models
.
DateField
()),
(
'expected_finish'
,
models
.
DateField
()),
(
'vacancy'
,
models
.
ForeignKey
(
on_delete
=
django
.
db
.
models
.
deletion
.
CASCADE
,
related_name
=
'milestones'
,
to
=
'core.Vacancy'
)),
],
),
]
core/migrations/0020_merge_20191006_1513.py
0 → 100644
View file @
39ff0f1e
# -*- coding: utf-8 -*-
# Generated by Django 1.11.17 on 2019-10-06 08:13
from
__future__
import
unicode_literals
from
django.db
import
migrations
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'core'
,
'0014_vacancymilestone'
),
(
'core'
,
'0017_vacancy_amount'
),
(
'core'
,
'0019_merge_20191006_0852'
),
]
operations
=
[
]
core/migrations/0025_merge_20191008_0048.py
0 → 100644
View file @
39ff0f1e
# -*- coding: utf-8 -*-
# Generated by Django 1.11.17 on 2019-10-07 17:48
from
__future__
import
unicode_literals
from
django.db
import
migrations
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'core'
,
'0020_merge_20191006_1513'
),
(
'core'
,
'0024_auto_20191007_1533'
),
]
operations
=
[
]
core/models/__init__.py
View file @
39ff0f1e
...
...
@@ -4,7 +4,4 @@ from core.models.accounts import Student
from
core.models.accounts
import
Supervisor
from
core.models.vacancies
import
Vacancy
from
core.models.vacancies
import
Application
from
core.models.vacancies
import
VacancyMilestone
core/models/vacancies.py
View file @
39ff0f1e
from
django.db
import
models
from
django.core.exceptions
import
ValidationError
from
core.models.accounts
import
Company
,
Student
...
...
@@ -36,3 +36,15 @@ class Application(models.Model):
class
Meta
:
unique_together
=
((
"student"
,
"vacancy"
),)
class
VacancyMilestone
(
models
.
Model
):
vacancy
=
models
.
ForeignKey
(
Vacancy
,
on_delete
=
models
.
CASCADE
,
related_name
=
"milestones"
,
null
=
False
)
name
=
models
.
CharField
(
max_length
=
100
,
null
=
False
)
detail
=
models
.
TextField
()
expected_start
=
models
.
DateField
()
expected_finish
=
models
.
DateField
()
def
clean
(
self
):
super
(
VacancyMilestone
,
self
).
clean
()
if
self
.
expected_start
>=
self
.
expected_finish
:
raise
ValidationError
(
"Expected start must be earlier than expected finish."
)
core/serializers/vacancies.py
View file @
39ff0f1e
from
rest_framework
import
serializers
from
core.models
import
Company
from
core.models.vacancies
import
Vacancy
,
Application
from
core.models.vacancies
import
Vacancy
,
Application
,
VacancyMilestone
from
core.serializers.accounts
import
StudentSerializer
,
CompanySerializer
...
...
@@ -95,3 +95,14 @@ class VacancyVerifiedSerializer(serializers.ModelSerializer):
class
Meta
:
model
=
Vacancy
fields
=
[
'verified'
]
class
VacancyMilestoneSerializer
(
serializers
.
ModelSerializer
):
def
validate
(
self
,
data
):
if
data
[
'expected_start'
]
>
data
[
'expected_finish'
]:
raise
serializers
.
ValidationError
(
"Expected start must be earlier than expected finish."
)
return
data
class
Meta
:
model
=
VacancyMilestone
fields
=
[
'name'
,
'detail'
,
'expected_start'
,
'expected_finish'
]
core/tests/test_vacancies.py
View file @
39ff0f1e
...
...
@@ -2,15 +2,15 @@ from datetime import datetime, timedelta
from
django.utils
import
timezone
import
json
import
requests_mock
from
django.core.exceptions
import
ValidationError
from
django.contrib.auth.models
import
User
from
rest_framework
import
status
from
rest_framework.test
import
APITestCase
from
core.models.accounts
import
Company
,
Student
,
Supervisor
from
core.models.vacancies
import
Vacancy
,
Application
from
core.models.vacancies
import
Vacancy
,
Application
,
VacancyMilestone
from
core.serializers.vacancies
import
VacancySerializer
class
ApplicationTests
(
APITestCase
):
@
requests_mock
.
Mocker
()
def
test_application_list
(
self
,
m
):
...
...
@@ -209,11 +209,11 @@ class VacancyTest(APITestCase):
url
=
'/api/vacancies/?verified=false'
response
=
self
.
client
.
get
(
url
,
format
=
'json'
)
self
.
assertEqual
(
response
.
status_code
,
status
.
HTTP_200_OK
)
def
test_filter_vacancy_list_by_company_ids
(
self
):
superuser
=
User
.
objects
.
create_superuser
(
'dummy.company'
,
'dummy.company@company.com'
,
'lalala123'
)
self
.
client
.
force_authenticate
(
user
=
superuser
)
new_user
=
User
.
objects
.
create_user
(
'dummy.company3'
,
'dummy.company3@company.com'
,
'lalala123'
)
new_company
=
Company
.
objects
.
create
(
user
=
new_user
,
description
=
"lalala"
,
status
=
Company
.
VERIFIED
,
logo
=
None
,
address
=
None
)
...
...
@@ -224,9 +224,9 @@ class VacancyTest(APITestCase):
address
=
None
)
open_time
=
datetime
(
2019
,
10
,
20
)
close_time
=
datetime
(
2019
,
12
,
20
)
vacancy1
=
Vacancy
.
objects
.
create
(
company
=
new_company
,
verified
=
True
,
open_time
=
open_time
,
vacancy1
=
Vacancy
.
objects
.
create
(
company
=
new_company
,
verified
=
True
,
open_time
=
open_time
,
description
=
''
,
close_time
=
close_time
,
name
=
'vacancy1'
)
vacancy2
=
Vacancy
.
objects
.
create
(
company
=
new_company2
,
verified
=
True
,
open_time
=
open_time
,
vacancy2
=
Vacancy
.
objects
.
create
(
company
=
new_company2
,
verified
=
True
,
open_time
=
open_time
,
description
=
''
,
close_time
=
close_time
,
name
=
'vacancy2'
)
url
=
'/api/vacancies/?company={}&company={}'
.
format
(
new_company
.
id
,
new_company2
.
id
)
response
=
self
.
client
.
get
(
url
,
format
=
'json'
)
...
...
@@ -255,7 +255,7 @@ class VacancyTest(APITestCase):
url
=
'/api/vacancies/?opened_only=false'
response
=
self
.
client
.
get
(
url
,
format
=
'json'
)
self
.
assertEqual
(
response
.
status_code
,
status
.
HTTP_200_OK
)
@
requests_mock
.
Mocker
()
def
test_closed_vacancy_not_included
(
self
,
m
):
m
.
get
(
'https://akun.cs.ui.ac.id/oauth/token/verify/?client_id=X3zNkFmepkdA47ASNMDZRX3Z9gqSU1Lwywu5WepG'
,
json
=
{
"username"
:
'dummy.mahasiswa'
,
"role"
:
'mahasiswa'
,
"identity_number"
:
'1234567890'
},
status_code
=
200
)
...
...
@@ -494,7 +494,7 @@ class CompanyListsTests(APITestCase):
url
=
'/api/companies/'
+
str
(
new_company
.
pk
)
+
'/applications/'
+
str
(
new_vacancy
.
pk
)
+
'/by_vacancy/?status=5'
response
=
self
.
client
.
get
(
url
,
format
=
'json'
)
self
.
assertEqual
(
response
.
status_code
,
status
.
HTTP_400_BAD_REQUEST
)
def
test_company_application_list_with_major
(
self
):
new_user
=
User
.
objects
.
create_user
(
'dummy.company4'
,
'dummy.company4@company.com'
,
'lalala123'
)
new_company
=
Company
.
objects
.
create
(
user
=
new_user
,
description
=
"lalala"
,
status
=
Company
.
VERIFIED
,
logo
=
None
,
address
=
None
)
...
...
@@ -602,7 +602,7 @@ class ValidationPositionNameinCreateLowonganKP(APITestCase):
response_status_code
=
response
.
status_code
self
.
assertEqual
(
response_status_code
,
200
)
def
test_name_contains_alphabets_and_numerics
(
self
):
self
.
payload
[
"name"
]
=
"Software18 Engineer"
...
...
@@ -639,20 +639,177 @@ class ValidationPositionNameinCreateLowonganKP(APITestCase):
response_status_code
=
response
.
status_code
self
.
assertEqual
(
response_status_code
,
400
)
class
AcceptOneOfferTests
(
APITestCase
):
class
VacancyMilestoneTests
(
APITestCase
):
def
setUp
(
self
):
super
(
VacancyMilestoneTests
,
self
).
setUp
()
self
.
user
=
User
.
objects
.
create_user
(
'dummy.student'
,
'dummy.student@home.com'
,
'lalala123'
)
self
.
company_user
=
User
.
objects
.
create_user
(
'dummy.company2'
,
'dummy.compan2y@company.com'
,
'lalala123'
)
self
.
company
=
Company
.
objects
.
create
(
user
=
self
.
company_user
,
description
=
"lalala"
,
status
=
Company
.
VERIFIED
,
logo
=
None
,
address
=
None
)
self
.
vacancy
=
Vacancy
.
objects
.
create
(
company
=
self
.
company
,
verified
=
True
,
open_time
=
datetime
.
fromtimestamp
(
0
),
description
=
"lalala"
,
close_time
=
datetime
.
today
())
def
create_milestone_object
(
self
):
return
VacancyMilestone
.
objects
.
create
(
vacancy
=
self
.
vacancy
,
name
=
"initiate"
,
detail
=
"install things"
,
expected_start
=
datetime
.
fromtimestamp
(
0
),
expected_finish
=
datetime
.
fromtimestamp
(
86400
))
def
test_vacancy_milestone_model
(
self
):
milestone1
=
VacancyMilestone
(
vacancy
=
self
.
vacancy
,
name
=
"initiate"
,
detail
=
"install things"
,
expected_start
=
datetime
.
fromtimestamp
(
0
),
expected_finish
=
datetime
.
fromtimestamp
(
86400
))
milestone1
.
full_clean
()
milestone2
=
VacancyMilestone
(
vacancy
=
self
.
vacancy
,
name
=
"a"
*
101
,
detail
=
"install things"
,
expected_start
=
datetime
.
fromtimestamp
(
0
),
expected_finish
=
datetime
.
fromtimestamp
(
86400
))
with
self
.
assertRaises
(
ValidationError
,
msg
=
"Name with more than 100 character should raise ValidationError"
):
milestone2
.
full_clean
()
milestone3
=
VacancyMilestone
(
vacancy
=
self
.
vacancy
,
name
=
"initiate"
,
detail
=
"install things"
,
expected_start
=
datetime
.
fromtimestamp
(
86400
),
expected_finish
=
datetime
.
fromtimestamp
(
0
))
with
self
.
assertRaises
(
ValidationError
,
msg
=
"Expected finish earlier than tart should raise ValidationError"
):
milestone3
.
full_clean
()
def
test_vacancy_milestones_list
(
self
):
milestone1
=
self
.
create_milestone_object
()
self
.
client
.
force_authenticate
(
user
=
self
.
user
)
url
=
'/api/vacancies/'
+
str
(
self
.
vacancy
.
pk
)
+
'/milestones/'
response
=
self
.
client
.
get
(
url
,
format
=
'json'
)
self
.
assertEqual
(
response
.
status_code
,
status
.
HTTP_200_OK
)
self
.
assertEqual
(
len
(
response
.
data
[
"results"
]),
1
)
self
.
assertEqual
(
response
.
data
[
"results"
][
0
][
"name"
],
milestone1
.
name
)
self
.
assertEqual
(
response
.
data
[
"results"
][
0
][
"detail"
],
milestone1
.
detail
)
def
test_create_new_milestone_on_a_vacancy_success
(
self
):
self
.
client
.
force_authenticate
(
user
=
self
.
company_user
)
url
=
'/api/vacancies/'
+
str
(
self
.
vacancy
.
pk
)
+
'/milestones/'
data
=
{
"name"
:
"initiate"
,
"detail"
:
"install things"
,
"expected_start"
:
"2019-01-20"
,
"expected_finish"
:
"2019-01-21"
}
response
=
self
.
client
.
post
(
url
,
data
,
format
=
'json'
)
self
.
assertEqual
(
response
.
status_code
,
status
.
HTTP_200_OK
)
self
.
assertEqual
(
self
.
vacancy
.
milestones
.
count
(),
1
)
new_milestone
=
self
.
vacancy
.
milestones
.
first
()
self
.
assertEqual
(
new_milestone
.
name
,
data
[
"name"
])
self
.
assertEqual
(
new_milestone
.
detail
,
data
[
"detail"
])
def
test_create_new_milestone_on_a_vacancy_invalid_data
(
self
):
self
.
client
.
force_authenticate
(
user
=
self
.
company_user
)
url
=
'/api/vacancies/'
+
str
(
self
.
vacancy
.
pk
)
+
'/milestones/'
data
=
{
"name"
:
"initiate"
,
"detail"
:
"install things"
,
"expected_start"
:
"2019-01-20"
,
"expected_finish"
:
"2019-01-01"
}
response
=
self
.
client
.
post
(
url
,
data
,
format
=
'json'
)
self
.
assertEqual
(
response
.
status_code
,
status
.
HTTP_400_BAD_REQUEST
)
self
.
assertEqual
(
self
.
vacancy
.
milestones
.
count
(),
0
)
def
test_create_new_milestone_on_a_vacancy_unauthorized_user
(
self
):
self
.
client
.
force_authenticate
(
user
=
self
.
user
)
url
=
'/api/vacancies/'
+
str
(
self
.
vacancy
.
pk
)
+
'/milestones/'
data
=
{
"name"
:
"initiate"
,
"detail"
:
"install things"
,
"expected_start"
:
"2019-01-20"
,
"expected_finish"
:
"2019-01-21"
}
response
=
self
.
client
.
post
(
url
,
data
,
format
=
'json'
)
self
.
assertEqual
(
response
.
status_code
,
status
.
HTTP_403_FORBIDDEN
)
self
.
assertEqual
(
self
.
vacancy
.
milestones
.
count
(),
0
)
def
test_modify_milestone_on_a_vacancy_success
(
self
):
milestone
=
self
.
create_milestone_object
()
self
.
client
.
force_authenticate
(
user
=
self
.
company_user
)
url
=
'/api/vacancies/'
+
str
(
self
.
vacancy
.
pk
)
+
'/milestones/'
+
str
(
milestone
.
pk
)
+
'/'
data
=
{
"name"
:
"initiate env"
,
"detail"
:
"install all things"
,
"expected_start"
:
"2019-01-20"
,
"expected_finish"
:
"2019-01-21"
}
response
=
self
.
client
.
put
(
url
,
data
,
format
=
'json'
)
self
.
assertEqual
(
response
.
status_code
,
status
.
HTTP_200_OK
)
self
.
assertEqual
(
self
.
vacancy
.
milestones
.
count
(),
1
)
new_milestone
=
self
.
vacancy
.
milestones
.
first
()
self
.
assertEqual
(
new_milestone
.
name
,
data
[
"name"
])
self
.
assertEqual
(
new_milestone
.
detail
,
data
[
"detail"
])
def
test_modify_milestone_on_a_vacancy_not_found
(
self
):
milestone
=
self
.
create_milestone_object
()
self
.
client
.
force_authenticate
(
user
=
self
.
company_user
)
url
=
'/api/vacancies/1000/milestones/'
+
str
(
milestone
.
pk
)
+
'/'
data
=
{
"name"
:
"initiate env"
,
"detail"
:
"install all things"
,
"expected_start"
:
"2019-01-20"
,
"expected_finish"
:
"2019-01-21"
}
response
=
self
.
client
.
put
(
url
,
data
,
format
=
'json'
)
self
.
assertEqual
(
response
.
status_code
,
status
.
HTTP_404_NOT_FOUND
)
url2
=
'/api/vacancies/'
+
str
(
self
.
vacancy
.
pk
)
+
'/milestones/1000/'
response2
=
self
.
client
.
put
(
url2
,
data
,
format
=
'json'
)
self
.
assertEqual
(
response2
.
status_code
,
status
.
HTTP_404_NOT_FOUND
)
self
.
assertEqual
(
self
.
vacancy
.
milestones
.
count
(),
1
)
new_milestone
=
self
.
vacancy
.
milestones
.
first
()
self
.
assertEqual
(
new_milestone
.
name
,
milestone
.
name
)
self
.
assertEqual
(
new_milestone
.
detail
,
milestone
.
detail
)
def
test_modify_milestone_on_a_vacancy_invalid_data
(
self
):
milestone
=
self
.
create_milestone_object
()
self
.
client
.
force_authenticate
(
user
=
self
.
company_user
)
url
=
'/api/vacancies/'
+
str
(
self
.
vacancy
.
pk
)
+
'/milestones/'
+
str
(
milestone
.
pk
)
+
'/'
data
=
{
"name"
:
"a"
*
101
,
"detail"
:
"install all things"
,
"expected_start"
:
"2019-01-21"
,
"expected_finish"
:
"2019-01-19"
}
response
=
self
.
client
.
put
(
url
,
data
,
format
=
'json'
)
self
.
assertEqual
(
response
.
status_code
,
status
.
HTTP_400_BAD_REQUEST
)
self
.
assertEqual
(
self
.
vacancy
.
milestones
.
count
(),
1
)
new_milestone
=
self
.
vacancy
.
milestones
.
first
()
self
.
assertEqual
(
new_milestone
.
name
,
milestone
.
name
)
self
.
assertEqual
(
new_milestone
.
detail
,
milestone
.
detail
)
def
test_modify_milestone_on_a_vacancy_unauthorized_user
(
self
):
milestone
=
self
.
create_milestone_object
()
self
.
client
.
force_authenticate
(
user
=
self
.
user
)
url
=
'/api/vacancies/'
+
str
(
self
.
vacancy
.
pk
)
+
'/milestones/'
+
str
(
milestone
.
pk
)
+
'/'
data
=
{
"name"
:
"initiate env"
,
"detail"
:
"install all things"
,
"expected_start"
:
"2019-01-20"
,
"expected_finish"
:
"2019-01-21"
}
response
=
self
.
client
.
put
(
url
,
data
,
format
=
'json'
)
self
.
assertEqual
(
response
.
status_code
,
status
.
HTTP_403_FORBIDDEN
)
self
.
assertEqual
(
self
.
vacancy
.
milestones
.
count
(),
1
)
new_milestone
=
self
.
vacancy
.
milestones
.
first
()
self
.
assertEqual
(
new_milestone
.
name
,
milestone
.
name
)
self
.
assertEqual
(
new_milestone
.
detail
,
milestone
.
detail
)
def
test_delete_milestone_on_a_vacancy_success
(
self
):
milestone
=
self
.
create_milestone_object
()
self
.
client
.
force_authenticate
(
user
=
self
.
company_user
)
url
=
'/api/vacancies/'
+
str
(
self
.
vacancy
.
pk
)
+
'/milestones/'
+
str
(
milestone
.
pk
)
+
'/'
response
=
self
.
client
.
delete
(
url
,
format
=
'json'
)
self
.
assertEqual
(
response
.
status_code
,
status
.
HTTP_200_OK
)
self
.
assertEqual
(
self
.
vacancy
.
milestones
.
count
(),
0
)
def
test_delete_milestone_on_a_vacancy_not_found
(
self
):
milestone
=
self
.
create_milestone_object
()
self
.
client
.
force_authenticate
(
user
=
self
.
company_user
)
url
=
'/api/vacancies/1000/milestones/'
+
str
(
milestone
.
pk
)
+
'/'
response
=
self
.
client
.
delete
(
url
,
format
=
'json'
)
self
.
assertEqual
(
response
.
status_code
,
status
.
HTTP_404_NOT_FOUND
)
url2
=
'/api/vacancies/'
+
str
(
self
.
vacancy
.
pk
)
+
'/milestones/1000/'
response2
=
self
.
client
.
delete
(
url2
,
format
=
'json'
)
self
.
assertEqual
(
response2
.
status_code
,
status
.
HTTP_404_NOT_FOUND
)
self
.
assertEqual
(
self
.
vacancy
.
milestones
.
count
(),
1
)
def
test_delete_milestone_on_a_vacancy_unauthorized_user
(
self
):
milestone
=
self
.
create_milestone_object
()
self
.
client
.
force_authenticate
(
user
=
self
.
user
)
url
=
'/api/vacancies/'
+
str
(
self
.
vacancy
.
pk
)
+
'/milestones/'
+
str
(
milestone
.
pk
)
+
'/'
response
=
self
.
client
.
delete
(
url
,
format
=
'json'
)
self
.
assertEqual
(
response
.
status_code
,
status
.
HTTP_403_FORBIDDEN
)
self
.
assertEqual
(
self
.
vacancy
.
milestones
.
count
(),
1
)
class
AcceptOneOfferTests
(
APITestCase
):
def
generateObject
(
self
):
new_user
=
User
.
objects
.
create_user
(
'dummy.company'
,
'dummy.company@company.com'
,
'lalala123'
)
new_company
=
Company
.
objects
.
create
(
user
=
new_user
,
description
=
"lalala"
,
status
=
Company
.
VERIFIED
,
logo
=
None
,
address
=
None
)
new_user2
=
User
.
objects
.
create_user
(
'dummy.company2'
,
'dummy.company2@company.com'
,
'lalala123'
)
new_company2
=
Company
.
objects
.
create
(
user
=
new_user2
,
description
=
"lalala"
,
status
=
Company
.
VERIFIED
,
logo
=
None
,
address
=
None
)
new_vacancy
=
Vacancy
.
objects
.
create
(
company
=
new_company
,
verified
=
True
,
open_time
=
datetime
.
fromtimestamp
(
0
),
description
=
"lalala"
,
close_time
=
datetime
.
today
())
new_vacancy2
=
Vacancy
.
objects
.
create
(
company
=
new_company2
,
verified
=
True
,
open_time
=
datetime
.
fromtimestamp
(
0
),
description
=
"lalala"
,
close_time
=
datetime
.
today
())
...
...
@@ -662,9 +819,9 @@ class AcceptOneOfferTests(APITestCase):
return
new_user3
,
new_vacancy
,
new_vacancy2
,
new_student
def
test_number_of_content_response_object_given_id_auth
(
self
):
new_user3
,
new_vacancy
,
new_vacancy2
,
new_student
=
self
.
generateObject
()
self
.
client
.
force_authenticate
(
new_user3
)
Application
.
objects
.
create
(
student
=
new_student
,
vacancy
=
new_vacancy
,
cover_letter
=
"asdasdasd"
)
...
...
@@ -677,7 +834,7 @@ class AcceptOneOfferTests(APITestCase):
status_response
=
[]
for
app
in
body
:
status_response
.
append
(
app
[
'status'
])
status_response
.
append
(
app
[
'status'
])
self
.
assertEqual
(
response
.
status_code
,
status
.
HTTP_200_OK
)
self
.
assertTrue
(
len
(
body
)
>=
2
)
...
...
@@ -699,7 +856,7 @@ class AcceptOneOfferTests(APITestCase):
url
=
'/api/acceptoffer/'
+
str
(
new_student
.
pk
)
+
'/vacancy/'
+
str
(
new_vacancy
.
pk
)
+
'/'
response
=
self
.
client
.
patch
(
url
,
format
=
'json'
)
body
=
json
.
loads
(
response
.
content
)
body
=
json
.
loads
(
response
.
content
)
self
.
assertEqual
(
response
.
status_code
,
status
.
HTTP_200_OK
)
self
.
assertTrue
(
len
(
body
)
==
0
)
...
...
@@ -714,19 +871,19 @@ class AcceptOneOfferTests(APITestCase):
with
self
.
assertRaises
(
TypeError
):
url
=
'/api/acceptoffer/'
+
None
+
'/vacancy/'
+
str
(
new_vacancy
.
pk
)
+
'/'
with
self
.
assertRaises
(
TypeError
):
url
=
'/api/acceptoffer/'
+
str
(
new_student
.
pk
)
+
'/vacancy/'
+
None
+
'/'
def
test_if_requester_is_not_authenticated
(
self
):
new_user3
,
new_vacancy
,
new_vacancy2
,
new_student
=
self
.
generateObject
()
Application
.
objects
.
create
(
student
=
new_student
,
vacancy
=
new_vacancy
,
cover_letter
=
"asdasdasd"
)
Application
.
objects
.
create
(
student
=
new_student
,
vacancy
=
new_vacancy2
,
cover_letter
=
"asdasdasd"
)
url
=
'/api/acceptoffer/'
+
str
(
new_student
.
pk
)
+
'/vacancy/'
+
str
(
new_vacancy
.
pk
)
+
'/'
response
=
self
.
client
.
patch
(
url
,
format
=
'json'
)
body
=
json
.
loads
(
response
.
content
)
body
=
json
.
loads
(
response
.
content
)
self
.
assertEqual
(
response
.
status_code
,
status
.
HTTP_403_FORBIDDEN
)
core/views/vacancies.py
View file @
39ff0f1e
...
...
@@ -2,7 +2,7 @@ import requests
from
django.utils
import
timezone
from
django.conf
import
settings
from
rest_framework
import
viewsets
,
status
from
rest_framework.decorators
import
detail_route
from
rest_framework.decorators
import
detail_route
,
permission_classes
from
rest_framework.exceptions
import
ValidationError
from
rest_framework.generics
import
get_object_or_404
from
rest_framework.pagination
import
PageNumberPagination
...
...
@@ -11,11 +11,12 @@ from rest_framework.response import Response
from
core.lib.mixins
import
MultiSerializerViewSetMixin
from
core.lib.permissions
import
IsAdminOrStudent
,
IsAdminOrCompany
,
IsAdminOrVacancyOwner
,
AsAdminOrSupervisor
,
\
VacancyApprovalPermission
VacancyApprovalPermission
,
IsAdminOrVacancyOwnerOrAuthenticatedReadOnly
from
core.models
import
Student
,
Company
from
core.models.vacancies
import
Vacancy
,
Application
from
core.models.vacancies
import
Vacancy
,
Application
,
VacancyMilestone
from
core.serializers.vacancies
import
VacancySerializer
,
ApplicationSerializer
,
ApplicationStatusSerializer
,
\
PostVacancySerializer
,
VacancyVerifiedSerializer
,
SupervisorStudentApplicationSerializer
PostVacancySerializer
,
VacancyVerifiedSerializer
,
SupervisorStudentApplicationSerializer
,
\
VacancyMilestoneSerializer
from
core.views.accounts
import
StudentViewSet
from
datetime
import
datetime
,
timedelta
,
time
...
...
@@ -388,6 +389,77 @@ class BookmarkedVacancyByStudentViewSet(viewsets.GenericViewSet):
return
Response
(
self
.
serializer_class
(
student
.
bookmarked_vacancies
,
many
=
True
,
context
=
{
'request'
:
request
}).
data
)
class
VacancyMilestoneViewSet
(
viewsets
.
GenericViewSet
):
serializer_class
=
VacancyMilestoneSerializer
permission_classes
=
[
IsAdminOrVacancyOwnerOrAuthenticatedReadOnly
]
def
list
(
self
,
request
,
vacancy_id
):
"""
Get list of a vacancy {vacancy_id}'s milestone plans
---
"""
vacancy
=
get_object_or_404
(
Vacancy
.
objects
.
all
(),
pk
=
vacancy_id
)
milestones
=
vacancy
.
milestones
.
all
()
page
=
self
.
paginate_queryset
(
milestones
)
if
page
is
not
None
:
return
self
.
get_paginated_response
(
self
.
serializer_class
(
page
,
many
=
True
,
context
=
{
'request'
:
request
}).
data
)
return
Response
(
self
.
serializer_class
(
milestones
,
many
=
True
,
context
=
{
'request'
:
request
}).
data
)
def
create
(
self
,
request
,
vacancy_id
):
"""
Create a new milestone for vacancy {vacancy_id}
---
parameters:
- name: body
description: JSON object containing 'name' string, 'detail' string, 'expected_start' date string, and
'expected_finish' date string
required: true
type: string
paramType: body
"""
vacancy
=
get_object_or_404
(
Vacancy
.
objects
.
all
(),
pk
=
vacancy_id
)
milestone_serializer
=
self
.
serializer_class
(
data
=
request
.
data
)
if
milestone_serializer
.
is_valid
():
milestone
=
milestone_serializer
.
save
(
vacancy
=
vacancy
)
return
Response
(
self
.
serializer_class
(
milestone
,
context
=
{
'request'
:
request
}).
data
,
status
=
status
.
HTTP_200_OK
)
return
Response
(
milestone_serializer
.
errors
,
status
=
status
.
HTTP_400_BAD_REQUEST
)
def
update
(
self
,
request
,
vacancy_id
,
pk
):
"""
Create existing milestone {pk} for vacancy {vacancy_id}
---
parameters:
- name: body
description: JSON object containing 'name' string, 'detail' string, 'expected_start' date string, and
'expected_finish' date string
required: true
type: string
paramType: body
"""
vacancy
=
get_object_or_404
(
Vacancy
.
objects
.
all
(),
pk
=
vacancy_id
)
old_milestone
=
get_object_or_404
(
vacancy
.
milestones
.
all
(),
pk
=
pk
)
milestone_serializer
=
self
.
serializer_class
(
old_milestone
,
data
=
request
.
data
)
if
milestone_serializer
.
is_valid
():
milestone
=
milestone_serializer
.
save
(
vacancy
=
vacancy
)
return
Response
(
self
.
serializer_class
(
milestone
,
context
=
{
'request'
:
request
}).
data
,
status
=
status
.
HTTP_200_OK
)
return
Response
(
milestone_serializer
.
errors
,
status
=
status
.
HTTP_400_BAD_REQUEST
)
def
destroy
(
self
,
request
,
vacancy_id
,
pk
):
"""
Remove existing milestone {pk} from vacancy {vacancy_id}
---
"""
vacancy
=
get_object_or_404
(
Vacancy
.
objects
.
all
(),
pk
=
vacancy_id
)
milestone
=
get_object_or_404
(
vacancy
.
milestones
.
all
(),
pk
=
pk
)
milestone
.
delete
()
return
Response
(
self
.
serializer_class
(
vacancy
.
milestones
.
all
(),
many
=
True
,
context
=
{
'request'
:
request
}).
data
)
class
AcceptOfferByStudentViewSet
(
MultiSerializerViewSetMixin
,
viewsets
.
GenericViewSet
):
queryset
=
Application
.
objects
.
all
()
permission_classes
=
[
IsAdminOrStudent
]
...
...
@@ -399,11 +471,11 @@ class AcceptOfferByStudentViewSet(MultiSerializerViewSetMixin, viewsets.GenericV
"""
student
=
get_object_or_404
(
Student
.
objects
.
all
().
order_by
(
'-updated'
),
pk
=
student_id
)
apps
=
Application
.
objects
.
filter
(
student
=
student
)
for
a
in
apps
:
if
a
.
vacancy_id
!=
int
(
pk
):
serializer
=
ApplicationStatusSerializer
(
a
,
data
=
{
'status'
:
5
},
partial
=
True
)
if
serializer
.
is_valid
():
serializer
.
save
()
return
Response
(
SupervisorStudentApplicationSerializer
(
apps
,
many
=
True
,
context
=
{
'request'
:
request
}).
data
)
\ No newline at end of file
return
Response
(
SupervisorStudentApplicationSerializer
(
apps
,
many
=
True
,
context
=
{
'request'
:
request
}).
data
)
kape/urls.py
View file @
39ff0f1e
...
...
@@ -25,7 +25,8 @@ from core import apps
from
core.views.accounts
import
StudentViewSet
,
CompanyViewSet
,
SupervisorViewSet
,
UserViewSet
,
LoginViewSet
,
\
CompanyRegisterViewSet
from
core.views.vacancies
import
VacancyViewSet
,
BookmarkedVacancyByStudentViewSet
,
StudentApplicationViewSet
,
\
CompanyApplicationViewSet
,
CompanyVacanciesViewSet
,
ApplicationViewSet
,
AcceptOfferByStudentViewSet
CompanyApplicationViewSet
,
CompanyVacanciesViewSet
,
ApplicationViewSet
,
VacancyMilestoneViewSet
,
\
AcceptOfferByStudentViewSet
from
core.views.feedbacks
import
FeedbackViewSet
schema_view
=
get_swagger_view
()
...
...
@@ -40,6 +41,8 @@ router.register(r'vacancies', VacancyViewSet)
router
.
register
(
r
'applications'
,
ApplicationViewSet
)
router
.
register
(
r
'feedbacks'
,
FeedbackViewSet
)