Skip to content

Commit a336b94

Browse files
authored
Merge pull request #22 from gabrnavarro/add_milestone_get
Added get_milestones() function, examples
2 parents f47e192 + 2689535 commit a336b94

7 files changed

Lines changed: 241 additions & 5 deletions

File tree

README.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ All the examples below recognizes two environment variables:
9898
request <examples/cancel_milestone_payment.py>`__
9999
- `Request a Milestone payment
100100
release <examples/request_release_milestone_payment.py>`__
101+
- `Retrieve project milestones <examples/get_milestones.py>`__
102+
- `Retrieve a milestone by ID <examples/get_specific_milestone.py>`__
101103

102104
**Messaging**
103105

examples/get_milestones.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
from freelancersdk.session import Session
2+
from freelancersdk.resources.projects.projects import get_milestones
3+
from freelancersdk.resources.projects.exceptions import \
4+
MilestonesNotFoundException
5+
from freelancersdk.resources.users.helpers import (
6+
create_get_users_details_object
7+
)
8+
import os
9+
10+
11+
def sample_get_milestones():
12+
url = os.environ.get('FLN_URL')
13+
oauth_token = os.environ.get('FLN_OAUTH_TOKEN')
14+
session = Session(oauth_token=oauth_token, url=url)
15+
16+
get_milestones_data = {
17+
'project_ids': [
18+
101,
19+
102,
20+
],
21+
'limit': 10,
22+
'offset': 0,
23+
'user_details': create_get_users_details_object(
24+
country=True,
25+
profile_description=True
26+
)
27+
}
28+
29+
try:
30+
milestones = get_milestones(session, **get_milestones_data)
31+
except MilestonesNotFoundException as e:
32+
print('Error message: {}'.format(e.message))
33+
print('Server response: {}'.format(e.error_code))
34+
return None
35+
else:
36+
return milestones
37+
38+
39+
result = sample_get_milestones()
40+
41+
if result:
42+
print('Found milestones: {}'.format(len(result['milestones'])))

examples/get_specific_milestone.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
from freelancersdk.session import Session
2+
from freelancersdk.resources.projects.projects import get_milestone_by_id
3+
from freelancersdk.resources.projects.exceptions import \
4+
MilestonesNotFoundException
5+
from freelancersdk.resources.users.helpers import (
6+
create_get_users_details_object
7+
)
8+
9+
import os
10+
11+
12+
def sample_get_specific_milestone(milestone_id):
13+
url = os.environ.get('FLN_URL')
14+
oauth_token = os.environ.get('FLN_OAUTH_TOKEN')
15+
session = Session(oauth_token=oauth_token, url=url)
16+
user_details = create_get_users_details_object(
17+
country=True,
18+
profile_description=True
19+
)
20+
try:
21+
milestone = get_milestone_by_id(session, milestone_id, user_details)
22+
except MilestonesNotFoundException as e:
23+
print('Error message: {}'.format(e.message))
24+
print('Server response: {}'.format(e.error_code))
25+
return None
26+
else:
27+
return milestone
28+
29+
30+
milestone_id = 15323050
31+
result = sample_get_specific_milestone(milestone_id)
32+
33+
if result:
34+
print('Found milestone: {}'.format(result['milestones'][str(milestone_id)]))

freelancersdk/resources/projects/exceptions.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,15 @@ def __init__(self, message, error_code):
7070
self.error_code = error_code
7171

7272

73+
class MilestonesNotFoundException(Exception):
74+
"""
75+
Milestone could not be found
76+
"""
77+
def __init__(self, message, error_code):
78+
super(MilestonesNotFoundException, self).__init__(message)
79+
self.error_code = error_code
80+
81+
7382
class MilestoneNotCreatedException(Exception):
7483
"""
7584
Milestone could not be created

freelancersdk/resources/projects/helpers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
# Make API calls
1212
# /api/projects/0.1/<specific_endpoint>
13-
def make_get_request(session, endpoint, params_data):
13+
def make_get_request(session, endpoint, params_data=None):
1414
url = urljoin(session.url, '{}/{}/'.format(projects_endpoint, endpoint))
1515
return session.session.get(url, params=params_data, verify=True)
1616

freelancersdk/resources/projects/projects.py

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,14 @@
1414
MilestoneNotRequestedReleaseException, MilestoneNotCancelledException,
1515
MilestoneRequestNotCreatedException, MilestoneRequestNotAcceptedException,
1616
MilestoneRequestNotRejectedException, MilestoneRequestNotDeletedException,
17+
MilestonesNotFoundException,
1718
ReviewNotPostedException,
1819
JobsNotFoundException
1920
)
21+
22+
from freelancersdk.resources.projects.helpers import (
23+
create_get_projects_user_details_object
24+
)
2025
from freelancersdk.resources.projects import (
2126
make_get_request, make_post_request, make_put_request,
2227
)
@@ -222,7 +227,53 @@ def get_bids(session, project_ids=[], bid_ids=[], limit=10, offset=0):
222227
return json_data['result']
223228
else:
224229
raise BidsNotFoundException(
225-
message=json_data['message'], error_code=json_data['error_code'])
230+
message=json_data['message'], error_code=json_data['error_code']
231+
)
232+
233+
234+
def get_milestones(session, project_ids=[], milestone_ids=[], user_details=None, limit=10, offset=0):
235+
"""
236+
Get the list of milestones
237+
"""
238+
get_milestones_data = {}
239+
if milestone_ids:
240+
get_milestones_data['milestones[]'] = milestone_ids
241+
if project_ids:
242+
get_milestones_data['projects[]'] = project_ids
243+
get_milestones_data['limit'] = limit
244+
get_milestones_data['offset'] = offset
245+
246+
# Add projections if they exist
247+
if user_details:
248+
get_milestones_data.update(user_details)
249+
250+
# GET /api/projects/0.1/milestones/
251+
252+
response = make_get_request(session, 'milestones', params_data=get_milestones_data)
253+
json_data = response.json()
254+
if response.status_code == 200:
255+
return json_data['result']
256+
else:
257+
raise MilestonesNotFoundException(
258+
message=json_data['message'], error_code=json_data['error_code']
259+
)
260+
261+
262+
def get_milestone_by_id(session, milestone_id, user_details=None):
263+
"""
264+
Get a specific milestone
265+
"""
266+
# GET /api/projects/0.1/milestones/{milestone_id}/
267+
endpoint = 'milestones/{}'.format(milestone_id)
268+
269+
response = make_get_request(session, endpoint, params_data=user_details)
270+
json_data = response.json()
271+
if response.status_code == 200:
272+
return json_data['result']
273+
else:
274+
raise MilestonesNotFoundException(
275+
message=json_data['message'], error_code=json_data['error_code']
276+
)
226277

227278

228279
def award_project_bid(session, bid_id):
@@ -244,8 +295,10 @@ def award_project_bid(session, bid_id):
244295
return json_data['status']
245296
else:
246297
json_data = response.json()
247-
raise BidNotAwardedException(message=json_data['message'],
248-
error_code=json_data['error_code'])
298+
raise BidNotAwardedException(
299+
message=json_data['message'],
300+
error_code=json_data['error_code']
301+
)
249302

250303

251304
def revoke_project_bid(session, bid_id):

tests/test_projects.py

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
request_release_milestone_payment, cancel_milestone_payment,
1010
create_milestone_request, accept_milestone_request,
1111
reject_milestone_request, delete_milestone_request,
12-
get_jobs
12+
get_jobs, get_milestones, get_milestone_by_id
1313
)
1414
from freelancersdk.resources.projects.helpers import (
1515
create_budget_object, create_currency_object, create_job_object,
@@ -145,6 +145,54 @@ def json(self):
145145
}
146146

147147

148+
class FakeGetMilestonesGetResponse:
149+
150+
status_code = 200
151+
152+
def json(self):
153+
return {
154+
'status': 'success',
155+
'result': {
156+
'milestones': {
157+
'101': {
158+
'status': 'cleared',
159+
'bidder_id': 100,
160+
'project_id': 102,
161+
'transaction_id': 101
162+
},
163+
'201': {
164+
'status': 'cleared',
165+
'bidder_id': 200,
166+
'project_id': 202,
167+
'transaction_id': 201
168+
}
169+
},
170+
'users': None,
171+
},
172+
}
173+
174+
175+
class FakeGetMilestoneByIDGetResponse:
176+
177+
status_code = 200
178+
179+
def json(self):
180+
return {
181+
'status': 'success',
182+
'result': {
183+
'milestones': {
184+
'101': {
185+
'status': 'cleared',
186+
'bidder_id': 100,
187+
'project_id': 102,
188+
'transaction_id': 101
189+
}
190+
},
191+
'users': None,
192+
},
193+
}
194+
195+
148196
class FakeGetBidsGetResponse:
149197

150198
status_code = 200
@@ -508,6 +556,54 @@ def test_get_bids(self):
508556
verify=True)
509557
self.assertEquals(len(j['bids']), 5)
510558

559+
def test_get_milestones(self):
560+
# Dictionary being passed to the python get_milestone function
561+
user_details = create_get_projects_user_details_object(
562+
country=True,
563+
profile_description=True
564+
)
565+
get_milestones_data = {
566+
'milestone_ids': [
567+
101,
568+
102,
569+
],
570+
'limit': 20,
571+
'offset': 10,
572+
'user_details': user_details
573+
}
574+
575+
self.session.session.get = Mock()
576+
self.session.session.get.return_value = FakeGetMilestonesGetResponse()
577+
response = get_milestones(self.session, **get_milestones_data)
578+
579+
# Transforms the dictionary into the actual request sent by the function
580+
get_milestones_data.update({'milestones[]': get_milestones_data['milestone_ids']})
581+
get_milestones_data.update(user_details)
582+
del(get_milestones_data['milestone_ids'])
583+
del(get_milestones_data['user_details'])
584+
585+
self.session.session.get.assert_called_once_with(
586+
'https://fake-fln.com/api/projects/0.1/milestones/',
587+
params=get_milestones_data,
588+
verify=True
589+
)
590+
self.assertEquals(len(response['milestones']), 2)
591+
592+
def test_get_milestone(self):
593+
milestone_id = 101
594+
user_details = create_get_projects_user_details_object(
595+
country=True,
596+
profile_description=True
597+
)
598+
self.session.session.get = Mock()
599+
self.session.session.get.return_value = FakeGetMilestoneByIDGetResponse()
600+
get_milestone_by_id(self.session, milestone_id, user_details)
601+
self.session.session.get.assert_called_once_with(
602+
'https://fake-fln.com/api/projects/0.1/milestones/{}/'.format(milestone_id),
603+
params=user_details,
604+
verify=True
605+
)
606+
511607
def test_award_project_bid(self):
512608
bid_data = {
513609
'bid_id': 1,

0 commit comments

Comments
 (0)