Fixed bugs on Submit presentation flow

* added tags per allowed track
* updated presentation progress
* added presentation progress on presentation serializer
* added new endpoint to mark presentation as completed
PUT /api/v1/summits/{id}/presentations/{presentation_id}/completed

Change-Id: I23ec05341f74498312f074236b691dd6473700b1
This commit is contained in:
Sebastian Marcet 2018-09-26 15:01:33 -03:00
parent 76b206edbe
commit aebbcd1bd4
10 changed files with 214 additions and 3 deletions

View File

@ -284,6 +284,7 @@ final class OAuth2PresentationApiController extends OAuth2ProtectedController
'attending_media' => 'required|boolean',
'links' => 'sometimes|url_array',
'extra_questions' => 'sometimes|entity_value_array',
'tags' => 'sometimes|string_array',
];
$data = $data->all();
@ -360,6 +361,7 @@ final class OAuth2PresentationApiController extends OAuth2ProtectedController
'attending_media' => 'sometimes|boolean',
'links' => 'sometimes|url_array',
'extra_questions' => 'sometimes|entity_value_array',
'tags' => 'sometimes|string_array',
];
$data = $data->all();
@ -405,6 +407,51 @@ final class OAuth2PresentationApiController extends OAuth2ProtectedController
}
}
/**
* @param $summit_id
* @param $presentation_id
* @return mixed
*/
public function completePresentationSubmission($summit_id, $presentation_id){
try {
$summit = SummitFinderStrategyFactory::build($this->summit_repository, $this->resource_server_context)->find($summit_id);
if (is_null($summit)) return $this->error404();
$member_id = $this->resource_server_context->getCurrentUserExternalId();
if(is_null($member_id))
return $this->error403();
$member = $this->member_repository->getById($member_id);
if(is_null($member))
return $this->error403();
$presentation = $this->presentation_service->completePresentationSubmission
(
$summit,
$presentation_id,
$member
);
return $this->updated(SerializerRegistry::getInstance()->getSerializer($presentation)->serialize());
}
catch (EntityNotFoundException $ex1)
{
Log::warning($ex1);
return $this->error404();
}
catch (ValidationException $ex2)
{
Log::warning($ex2);
return $this->error412($ex2->getMessages());
}
catch (Exception $ex)
{
Log::error($ex);
return $this->error500($ex);
}
}
/**
* @param $presentation_id
* @return mixed

View File

@ -288,6 +288,8 @@ Route::group([
// opened without role CFP - valid selection plan on CFP status
Route::put('', 'OAuth2PresentationApiController@updatePresentationSubmission');
Route::put('completed', 'OAuth2PresentationApiController@completePresentationSubmission');
Route::delete('', 'OAuth2PresentationApiController@deletePresentation');
Route::group(['prefix' => 'videos'], function () {

View File

@ -27,6 +27,7 @@ class PresentationSerializer extends SummitEventSerializer
'ToRecord' => 'to_record:json_boolean',
'AttendingMedia' => 'attending_media:json_boolean',
'StatusNice' => 'status:json_string',
'ProgressNice' => 'progress:json_string',
];
protected static $allowed_fields = [
@ -38,6 +39,7 @@ class PresentationSerializer extends SummitEventSerializer
'to_record',
'attending_media',
'status',
'progress',
];
protected static $allowed_relations = [

View File

@ -463,6 +463,32 @@ class Presentation extends SummitEvent
return $this->status;
}
/**
* @return string
*/
public function getProgressNice(){
switch($this->progress){
case self::PHASE_NEW:
return 'NEW';
break;
case self::PHASE_SUMMARY:
return 'SUMMARY';
break;
case self::PHASE_TAGS:
return 'TAGS';
break;
case self::PHASE_SPEAKERS:
return 'SPEAKERS';
break;
case self::PHASE_COMPLETE:
return 'COMPLETE';
break;
default:
return 'NEW';
break;
}
}
/**
* @return mixed
*/
@ -472,7 +498,7 @@ class Presentation extends SummitEvent
}
/**
* @param mixed $progress
* @param int $progress
*/
public function setProgress($progress)
{

View File

@ -285,6 +285,17 @@ class PresentationCategory extends SilverstripeBaseModel
$this->allowed_tags->clear();
}
/**
* @param string $tag_value
* @return Tag|null
*/
public function getAllowedTagByVal($tag_value){
$criteria = Criteria::create();
$criteria->where(Criteria::expr()->eq('tag', trim($tag_value)));
$res = $this->allowed_tags->matching($criteria)->first();
return $res === false ? null : $res;
}
/**
* @param Tag $tag
* @return $this

View File

@ -68,6 +68,17 @@ interface IPresentationService
*/
public function updatePresentationSubmission(Summit $summit, $presentation_id, Member $member, array $data);
/**
* @param Summit $summit
* @param int $presentation_id
* @param Member $member
* @return Presentation
* @throws ValidationException
* @throws EntityNotFoundException
*/
public function completePresentationSubmission(Summit $summit, $presentation_id, Member $member);
/**
* @param Member $member
* @param int $presentation_id

View File

@ -20,6 +20,7 @@ use App\Models\Foundation\Summit\Events\Presentations\TrackQuestions\TrackAnswer
use Illuminate\Support\Facades\Event;
use models\exceptions\EntityNotFoundException;
use models\exceptions\ValidationException;
use models\main\ITagRepository;
use models\main\Member;
use models\summit\factories\IPresentationVideoFactory;
use models\summit\ISpeakerRepository;
@ -49,23 +50,38 @@ final class PresentationService
*/
private $video_factory;
/**
* @var ISpeakerRepository
*/
private $speaker_repository;
/**
* @var ITagRepository
*/
private $tag_repository;
/**
* PresentationService constructor.
* @param IPresentationVideoFactory $video_factory
* @param ISummitEventRepository $presentation_repository
* @param ISpeakerRepository $speaker_repository
* @param ITagRepository $tag_repository
* @param ITransactionService $tx_service
*/
public function __construct
(
IPresentationVideoFactory $video_factory,
ISummitEventRepository $presentation_repository,
ISpeakerRepository $speaker_repository,
ITagRepository $tag_repository,
ITransactionService $tx_service
)
{
parent::__construct($tx_service);
$this->presentation_repository = $presentation_repository;
$this->speaker_repository = $speaker_repository;
$this->tag_repository = $tag_repository;
$this->video_factory = $video_factory;
}
@ -282,19 +298,25 @@ final class PresentationService
$presentation = $summit->getEvent($presentation_id);
if (is_null($presentation))
throw new EntityNotFoundException(trans(
'not_found_errors.PresentationService.updatePresentationSubmission.PresentationNotFound',
['presentation_id' => $presentation_id]
));
if (!$presentation instanceof Presentation)
throw new EntityNotFoundException(trans(
'not_found_errors.PresentationService.updatePresentationSubmission.PresentationNotFound',
['presentation_id' => $presentation_id]
));
if(!$presentation->canEdit($current_speaker))
throw new ValidationException(trans(
'validation_errors.PresentationService.updatePresentationSubmission.CurrentSpeakerCanNotEditPresentation',
['presentation_id' => $presentation_id]
));
return $this->saveOrUpdatePresentation
(
$summit,
@ -387,6 +409,31 @@ final class PresentationService
// add me as speaker
$presentation->addSpeaker($current_speaker);
if (isset($data['tags'])) {
$presentation->clearTags();
if(count($data['tags']) > 0){
if($presentation->getProgress() == Presentation::PHASE_SUMMARY)
$presentation->setProgress(Presentation::PHASE_TAGS);
}
foreach ($data['tags'] as $tag_value) {
$tag = $track->getAllowedTagByVal($tag_value);
if(is_null($tag)){
throw new ValidationException(
trans(
'validation_errors.PresentationService.saveOrUpdatePresentation.TagNotAllowed',
[
'tag' => $tag_value,
'track_id' => $track->getId()
]
)
);
}
$presentation->addTag($tag);
}
}
if (isset($data['links'])) {
$presentation->clearLinks();
@ -476,4 +523,46 @@ final class PresentationService
$this->event_repository->delete($presentation);
});
}
/**
* @param Summit $summit
* @param int $presentation_id
* @param Member $member
* @return Presentation
* @throws ValidationException
* @throws EntityNotFoundException
*/
public function completePresentationSubmission(Summit $summit, $presentation_id, Member $member)
{
return $this->tx_service->transaction(function () use ($summit, $member, $presentation_id) {
$current_speaker = $this->speaker_repository->getByMember($member);
if(is_null($current_speaker))
throw new EntityNotFoundException(sprintf("member %s does not has a speaker profile", $member->getId()));
$presentation = $summit->getEvent($presentation_id);
if(is_null($presentation))
throw new EntityNotFoundException(sprintf("presentation %s not found", $presentation_id));
if(!$presentation instanceof Presentation)
throw new EntityNotFoundException(sprintf("presentation %s not found", $presentation_id));
if(!$presentation->canEdit($current_speaker))
throw new ValidationException(sprintf("member %s can not edit presentation %s",
$member->getId(),
$presentation_id
));
if($presentation->getProgress() != Presentation::PHASE_SPEAKERS){
throw new ValidationException
(
sprintf("presentation %s is not allowed to mark as completed", $presentation_id)
);
}
$presentation->setProgress(Presentation::PHASE_COMPLETE);
return $presentation;
});
}
}

View File

@ -1691,6 +1691,9 @@ final class SummitService extends AbstractService implements ISummitService
if (is_null($speaker))
throw new EntityNotFoundException(sprintf('speaker %s not found', $speaker_id));
if($presentation->getProgress() == Presentation::PHASE_TAGS)
$presentation->setProgress(Presentation::PHASE_SPEAKERS);
$presentation->addSpeaker($speaker);
});
}
@ -1732,6 +1735,9 @@ final class SummitService extends AbstractService implements ISummitService
if (is_null($speaker))
throw new EntityNotFoundException(sprintf('speaker %s not found', $speaker_id));
if($presentation->getProgress() == Presentation::PHASE_TAGS)
$presentation->setProgress(Presentation::PHASE_SPEAKERS);
$presentation->removeSpeaker($speaker);
});
}
@ -1772,6 +1778,9 @@ final class SummitService extends AbstractService implements ISummitService
if (is_null($speaker))
throw new EntityNotFoundException(sprintf('speaker %s not found', $speaker_id));
if($presentation->getProgress() == Presentation::PHASE_TAGS)
$presentation->setProgress(Presentation::PHASE_SPEAKERS);
$presentation->setModerator($speaker);
});
}
@ -1813,6 +1822,9 @@ final class SummitService extends AbstractService implements ISummitService
if (is_null($speaker))
throw new EntityNotFoundException(sprintf('speaker %s not found', $speaker_id));
if($presentation->getProgress() == Presentation::PHASE_TAGS)
$presentation->setProgress(Presentation::PHASE_SPEAKERS);
$presentation->unsetModerator();
});
}

View File

@ -1471,6 +1471,16 @@ class ApiEndpointsSeeder extends Seeder
sprintf(SummitScopes::WritePresentationData, $current_realm)
],
],
[
'name' => 'complete-submit-presentation',
'route' => '/api/v1/summits/{id}/presentations/{presentation_id}/completed',
'http_method' => 'PUT',
'scopes' => [
sprintf(SummitScopes::WriteSummitData, $current_realm),
sprintf(SummitScopes::WriteEventData, $current_realm),
sprintf(SummitScopes::WritePresentationData, $current_realm)
],
],
[
'name' => 'delete-submit-presentation',
'route' => '/api/v1/summits/{id}/presentations/{presentation_id}',

View File

@ -89,6 +89,7 @@ return [
'PresentationService.updatePresentationSubmission.NotValidSpeaker' => 'Current Member not has a valid speaker profile',
'PresentationService.updatePresentationSubmission.NotValidSelectionPlan' => 'Current Summit not has a valid selection plan',
'PresentationService.updatePresentationSubmission.CurrentSpeakerCanNotEditPresentation' => 'Current Speaker can not edit :presentation_id presentation',
'PresentationService.saveOrUpdatePresentation.TagNotAllowed' => 'tag :tag is not allowed on track :track_id',
// organizations
'OrganizationService.addOrganization.alreadyExistName' => 'Organization name :name already exists!',
// track tag groups