Fixes on member affiliation API

* added endpoint to add new affiliation
  /api/v1/members/{member_id}/affiliations
* fixed issues on delete affiliation
* fixed validation on update affiliation
* updated serializer on speaker to get all affiliations

Change-Id: I31426265ab9e57e67a6d1ae2a24b49287ab8d700
This commit is contained in:
Sebastian Marcet 2018-08-30 01:14:22 -03:00
parent 2414f6a3e9
commit 2535885128
9 changed files with 225 additions and 12 deletions

View File

@ -228,6 +228,53 @@ final class OAuth2MembersApiController extends OAuth2ProtectedController
} }
} }
public function addAffiliation($member_id){
try {
if(!Request::isJson()) return $this->error400();
$data = Input::json();
$member = $this->repository->getById($member_id);
if(is_null($member)) return $this->error404();
$rules = [
'is_current' => 'required|boolean',
'start_date' => 'required|date_format:U|valid_epoch',
'end_date' => 'sometimes|date_format:U|after_or_null_epoch:start_date',
'organization_id' => 'required|integer',
'job_title' => 'sometimes|string|max:255'
];
// Creates a Validator instance and validates the data.
$validation = Validator::make($data->all(), $rules);
if ($validation->fails()) {
$messages = $validation->messages()->toArray();
return $this->error412
(
$messages
);
}
$affiliation = $this->member_service->addAffiliation($member, $data->all());
return $this->created(SerializerRegistry::getInstance()->getSerializer($affiliation)->serialize());
}
catch (ValidationException $ex1) {
Log::warning($ex1);
return $this->error412(array($ex1->getMessage()));
}
catch(EntityNotFoundException $ex2)
{
Log::warning($ex2);
return $this->error404(array('message'=> $ex2->getMessage()));
}
catch (Exception $ex) {
Log::error($ex);
return $this->error500($ex);
}
}
/** /**
* @param int $member_id * @param int $member_id
* @param int $affiliation_id * @param int $affiliation_id
@ -263,7 +310,7 @@ final class OAuth2MembersApiController extends OAuth2ProtectedController
$affiliation = $this->member_service->updateAffiliation($member, $affiliation_id, $data->all()); $affiliation = $this->member_service->updateAffiliation($member, $affiliation_id, $data->all());
return $this->ok(SerializerRegistry::getInstance()->getSerializer($affiliation)->serialize()); return $this->updated(SerializerRegistry::getInstance()->getSerializer($affiliation)->serialize());
} }
catch (ValidationException $ex1) { catch (ValidationException $ex1) {
Log::warning($ex1); Log::warning($ex1);

View File

@ -46,6 +46,7 @@ Route::group([
Route::group(['prefix' => 'affiliations'], function(){ Route::group(['prefix' => 'affiliations'], function(){
Route::get('', [ 'middleware' => 'auth.user:administrators|summit-front-end-administrators', 'uses' => 'OAuth2MembersApiController@getMemberAffiliations']); Route::get('', [ 'middleware' => 'auth.user:administrators|summit-front-end-administrators', 'uses' => 'OAuth2MembersApiController@getMemberAffiliations']);
Route::post('', [ 'middleware' => 'auth.user:administrators|summit-front-end-administrators', 'uses' => 'OAuth2MembersApiController@addAffiliation']);
Route::group(['prefix' => '{affiliation_id}'], function(){ Route::group(['prefix' => '{affiliation_id}'], function(){
Route::put('', [ 'middleware' => 'auth.user:administrators|summit-front-end-administrators', 'uses' => 'OAuth2MembersApiController@updateAffiliation']); Route::put('', [ 'middleware' => 'auth.user:administrators|summit-front-end-administrators', 'uses' => 'OAuth2MembersApiController@updateAffiliation']);
Route::delete('', [ 'middleware' => 'auth.user:administrators|summit-front-end-administrators', 'uses' => 'OAuth2MembersApiController@deleteAffiliation']); Route::delete('', [ 'middleware' => 'auth.user:administrators|summit-front-end-administrators', 'uses' => 'OAuth2MembersApiController@deleteAffiliation']);

View File

@ -111,6 +111,15 @@ final class AdminPresentationSpeakerSerializer extends PresentationSpeakerSerial
} }
$values['organizational_roles'] = $organizational_roles; $values['organizational_roles'] = $organizational_roles;
$affiliations = [];
if($speaker->hasMember()) {
$member = $speaker->getMember();
foreach ($member->getAllAffiliations() as $affiliation) {
$affiliations[] = SerializerRegistry::getInstance()->getSerializer($affiliation)->serialize('organization');
}
}
$values['affiliations'] = $affiliations;
if (!empty($expand)) { if (!empty($expand)) {
foreach (explode(',', $expand) as $relation) { foreach (explode(',', $expand) as $relation) {
switch (trim($relation)) { switch (trim($relation)) {

View File

@ -135,6 +135,10 @@ class Affiliation extends SilverstripeBaseModel
return $this->owner; return $this->owner;
} }
public function clearOwner(){
$this->owner = null;
}
/** /**
* @param Member $owner * @param Member $owner
*/ */
@ -189,4 +193,14 @@ class Affiliation extends SilverstripeBaseModel
{ {
$this->job_title = $job_title; $this->job_title = $job_title;
} }
public function __construct()
{
parent::__construct();
$this->is_current = false;
$this->start_date = null;
$this->end_date = null;
$this->organization = null;
$this->owner = null;
}
} }

View File

@ -61,13 +61,13 @@ class Member extends SilverstripeBaseModel
private $github_user; private $github_user;
/** /**
* @ORM\OneToMany(targetEntity="models\summit\SummitEventFeedback", mappedBy="owner", cascade={"persist"}) * @ORM\OneToMany(targetEntity="models\summit\SummitEventFeedback", mappedBy="owner", cascade={"persist"}, orphanRemoval=true)
* @var SummitEventFeedback[] * @var SummitEventFeedback[]
*/ */
private $feedback; private $feedback;
/** /**
* @ORM\OneToMany(targetEntity="Affiliation", mappedBy="owner", cascade={"persist"}) * @ORM\OneToMany(targetEntity="Affiliation", mappedBy="owner", cascade={"persist"}, orphanRemoval=true)
* @var Affiliation[] * @var Affiliation[]
*/ */
private $affiliations; private $affiliations;
@ -1019,7 +1019,7 @@ SQL;
*/ */
public function getAffiliationById($affiliation_id){ public function getAffiliationById($affiliation_id){
$criteria = Criteria::create(); $criteria = Criteria::create();
$criteria->where(Criteria::expr()->eq('id', $affiliation_id)); $criteria->where(Criteria::expr()->eq('id', intval($affiliation_id)));
$affiliation = $this->affiliations->matching($criteria)->first(); $affiliation = $this->affiliations->matching($criteria)->first();
@ -1031,7 +1031,22 @@ SQL;
* @return $this * @return $this
*/ */
public function removeAffiliation(Affiliation $affiliation){ public function removeAffiliation(Affiliation $affiliation){
$this->affiliations->removeElement($affiliation); if($this->affiliations->contains($affiliation)) {
$this->affiliations->removeElement($affiliation);
$affiliation->clearOwner();
}
return $this;
}
/**
* @param Affiliation $affiliation
* @return $this
*/
public function addAffiliation(Affiliation $affiliation){
if(!$this->affiliations->contains($affiliation)) {
$this->affiliations->add($affiliation);
$affiliation->setOwner($this);
}
return $this; return $this;
} }

View File

@ -19,6 +19,14 @@ use models\main\Member;
*/ */
interface IMemberService interface IMemberService
{ {
/**
* @param Member $member
* @param array $data
* @return Affiliation
*/
public function addAffiliation(Member $member, array $data);
/** /**
* @param Member $member * @param Member $member
* @param int $affiliation_id * @param int $affiliation_id

View File

@ -63,7 +63,7 @@ final class MemberService
$affiliation->setIsCurrent(boolval($data['is_current'])); $affiliation->setIsCurrent(boolval($data['is_current']));
if(isset($data['start_date'])) { if(isset($data['start_date'])) {
$start_date = intval($data['start_date']); $start_date = intval($data['start_date']);
$affiliation->setEndDate(new DateTime("@$start_date")); $affiliation->setStartDate(new DateTime("@$start_date"));
} }
if(isset($data['end_date'])) { if(isset($data['end_date'])) {
$end_date = intval($data['end_date']); $end_date = intval($data['end_date']);
@ -125,4 +125,50 @@ final class MemberService
$member->removeRsvp($rsvp); $member->removeRsvp($rsvp);
}); });
} }
/**
* @param Member $member
* @param array $data
* @return Affiliation
*/
public function addAffiliation(Member $member, array $data)
{
return $this->tx_service->transaction(function() use($member, $data){
$affiliation = new Affiliation();
if(isset($data['is_current']))
$affiliation->setIsCurrent(boolval($data['is_current']));
if(isset($data['start_date'])) {
$start_date = intval($data['start_date']);
$affiliation->setStartDate(new DateTime("@$start_date"));
}
if(isset($data['end_date'])) {
$end_date = intval($data['end_date']);
$affiliation->setEndDate($end_date > 0 ? new DateTime("@$end_date") : null);
}
if(isset($data['organization_id'])) {
$org = $this->organization_repository->getById(intval($data['organization_id']));
if(is_null($org))
throw new EntityNotFoundException(sprintf("organization id %s not found", $data['organization_id']));
$affiliation->setOrganization($org);
}
if(isset($data['job_title'])) {
$affiliation->setJobTitle(trim($data['job_title']));
}
if($affiliation->isCurrent() && $affiliation->getEndDate() != null)
throw new ValidationException
(
sprintf
(
"in order to set affiliation as current end_date should be null"
)
);
$member->addAffiliation($affiliation);
return $affiliation;
});
}
} }

View File

@ -1781,6 +1781,14 @@ class ApiEndpointsSeeder extends Seeder
'http_method' => 'GET', 'http_method' => 'GET',
'scopes' => [sprintf('%s/members/read', $current_realm)], 'scopes' => [sprintf('%s/members/read', $current_realm)],
], ],
[
'name' => 'add-member-affiliation',
'route' => '/api/v1/members/{member_id}/affiliations',
'http_method' => 'POST',
'scopes' => [
sprintf(SummitScopes::WriteMemberData, $current_realm)
],
],
[ [
'name' => 'update-member-affiliation', 'name' => 'update-member-affiliation',
'route' => '/api/v1/members/{member_id}/affiliations/{affiliation_id}', 'route' => '/api/v1/members/{member_id}/affiliations/{affiliation_id}',

View File

@ -161,16 +161,54 @@ final class OAuth2MembersApiTest extends ProtectedApiTest
$this->assertResponseStatus(200); $this->assertResponseStatus(200);
} }
public function testUpdateMemberAffiliation(){ public function testAddMemberAffiliation($member_id = 11624){
$params = [ $params = [
'member_id' => 11624, 'member_id' => $member_id,
'affiliation_id' => 61749,
]; ];
$start_datetime = new DateTime( "2018-11-10 00:00:00");
$start_datetime_unix = $start_datetime->getTimestamp();
$data = [ $data = [
'is_current' => true, 'is_current' => true,
'end_date' => 0, 'start_date' => $start_datetime_unix,
'job_title' => 'test update' 'job_title' => 'test affiliation',
'organization_id' => 1
];
$headers = [
"HTTP_Authorization" => " Bearer " . $this->access_token,
"CONTENT_TYPE" => "application/json"
];
$response = $this->action(
"POST",
"OAuth2MembersApiController@addAffiliation",
$params,
[],
[],
[],
$headers,
json_encode($data)
);
$content = $response->getContent();
$this->assertResponseStatus(201);
$affiliation = json_decode($content);
$this->assertTrue(!is_null($affiliation));
return $affiliation;
}
public function testUpdateMemberAffiliation($member_id = 11624){
$new_affiliation = $this->testAddMemberAffiliation($member_id);
$params = [
'member_id' => $member_id,
'affiliation_id' => $new_affiliation->id,
];
$data = [
'job_title' => 'job title update'
]; ];
$headers = [ $headers = [
@ -190,12 +228,39 @@ final class OAuth2MembersApiTest extends ProtectedApiTest
); );
$content = $response->getContent(); $content = $response->getContent();
$this->assertResponseStatus(200); $this->assertResponseStatus(201);
$affiliation = json_decode($content); $affiliation = json_decode($content);
$this->assertTrue(!is_null($affiliation)); $this->assertTrue(!is_null($affiliation));
return $affiliation; return $affiliation;
} }
public function testDeleteMemberAffiliation($member_id = 11624){
$new_affiliation = $this->testAddMemberAffiliation($member_id);
$params = [
'member_id' => $member_id,
'affiliation_id' => $new_affiliation->id,
];
$headers = [
"HTTP_Authorization" => " Bearer " . $this->access_token,
"CONTENT_TYPE" => "application/json"
];
$response = $this->action(
"DELETE",
"OAuth2MembersApiController@deleteAffiliation",
$params,
[],
[],
[],
$headers
);
$content = $response->getContent();
$this->assertResponseStatus(204);
}
public function testGetMemberAffiliation($member_id = 11624) public function testGetMemberAffiliation($member_id = 11624)
{ {