diff --git a/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitAttendeesApiController.php b/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitAttendeesApiController.php index 1e89695a..1d7c2896 100644 --- a/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitAttendeesApiController.php +++ b/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitAttendeesApiController.php @@ -11,6 +11,7 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ +use App\ModelSerializers\SerializerUtils; use App\Services\Model\IAttendeeService; use App\Services\Model\ISummitOrderService; use Exception; @@ -31,11 +32,10 @@ use ModelSerializers\SerializerRegistry; use services\model\ISummitService; use utils\Filter; use utils\FilterElement; -use utils\FilterParser; -use utils\OrderParser; use Illuminate\Support\Facades\Input; use Illuminate\Support\Facades\Validator; -use utils\PagingInfo; +use utils\FilterParser; + /** * Class OAuth2SummitAttendeesApiController * @package App\Http\Controllers @@ -134,8 +134,6 @@ final class OAuth2SummitAttendeesApiController extends OAuth2ProtectedController * @return mixed */ public function getOwnAttendee($summit_id){ - $expand = Request::input('expand', ''); - try { $summit = SummitFinderStrategyFactory::build($this->summit_repository, $this->resource_server_context)->find($summit_id); @@ -144,7 +142,11 @@ final class OAuth2SummitAttendeesApiController extends OAuth2ProtectedController $type = CheckAttendeeStrategyFactory::Me; $attendee = CheckAttendeeStrategyFactory::build($type, $this->resource_server_context)->check('me', $summit); if(is_null($attendee)) return $this->error404(); - return $this->ok(SerializerRegistry::getInstance()->getSerializer($attendee)->serialize($expand)); + return $this->ok(SerializerRegistry::getInstance()->getSerializer($attendee)->serialize( + SerializerUtils::getExpand(), + SerializerUtils::getFields(), + SerializerUtils::getRelations() + )); } catch (\HTTP401UnauthorizedException $ex1) { Log::warning($ex1); @@ -163,8 +165,6 @@ final class OAuth2SummitAttendeesApiController extends OAuth2ProtectedController */ public function getAttendee($summit_id, $attendee_id) { - $expand = Request::input('expand', ''); - try { $summit = SummitFinderStrategyFactory::build($this->summit_repository, $this->resource_server_context)->find($summit_id); @@ -181,9 +181,9 @@ final class OAuth2SummitAttendeesApiController extends OAuth2ProtectedController SerializerRegistry::SerializerType_Private )->serialize ( - $expand, - [], - [], + SerializerUtils::getExpand(), + SerializerUtils::getFields(), + SerializerUtils::getRelations(), [ 'serializer_type' => SerializerRegistry::SerializerType_Private ] )); } @@ -383,6 +383,10 @@ final class OAuth2SummitAttendeesApiController extends OAuth2ProtectedController 'email' => ['=@', '=='], 'external_order_id' => ['=@', '=='], 'external_attendee_id' => ['=@', '=='], + 'member_id' => ['==', '>'], + 'ticket_type' => ['=@', '=='], + 'badge_type' => ['=@', '=='], + 'status' => ['=@', '=='], ]; }, function(){ @@ -394,6 +398,10 @@ final class OAuth2SummitAttendeesApiController extends OAuth2ProtectedController 'email' => 'sometimes|string', 'external_order_id' => 'sometimes|string', 'external_attendee_id' => 'sometimes|string', + 'member_id' => 'sometimes|integer', + 'ticket_type' => 'sometimes|string', + 'badge_type' => 'sometimes|string', + 'status' => 'sometimes|string', ]; }, function() @@ -404,6 +412,9 @@ final class OAuth2SummitAttendeesApiController extends OAuth2ProtectedController 'company', 'id', 'external_order_id', + 'member_id', + 'status', + 'full_name', ]; }, function($filter) use($summit){ @@ -437,6 +448,10 @@ final class OAuth2SummitAttendeesApiController extends OAuth2ProtectedController 'external_order_id' => ['=@', '=='], 'company' => ['=@', '=='], 'external_attendee_id' => ['=@', '=='], + 'member_id' => ['==','<=','>='], + 'ticket_type' => ['=@', '=='], + 'badge_type' => ['=@', '=='], + 'status' => ['=@', '=='], ]; }, function(){ @@ -448,17 +463,23 @@ final class OAuth2SummitAttendeesApiController extends OAuth2ProtectedController 'external_order_id' => 'sometimes|string', 'external_attendee_id' => 'sometimes|string', 'company' => 'sometimes|string', + 'member_id' => 'sometimes|integer', + 'ticket_type' => 'sometimes|string', + 'badge_type' => 'sometimes|string', + 'status' => 'sometimes|string', ]; }, function() { return [ - 'first_name', 'last_name', 'id', 'external_order_id', 'company', + 'member_id', + 'status', + 'full_name', ]; }, function($filter) use($summit){ @@ -498,6 +519,7 @@ final class OAuth2SummitAttendeesApiController extends OAuth2ProtectedController 'summit_hall_checked_in_date' => 'sometimes|date_format:U', 'first_name' => 'required_without:member_id|string|max:255', 'surname' => 'required_without:member_id|string|max:255', + 'admin_notes' => 'sometimes|string|max:1024', 'company' => 'sometimes|string|max:255', 'email' => 'required_without:member_id|string|max:255|email', 'member_id' => 'required_without_all:email|integer', @@ -518,7 +540,11 @@ final class OAuth2SummitAttendeesApiController extends OAuth2ProtectedController $attendee = $this->attendee_service->addAttendee($summit, $data->all()); - return $this->created(SerializerRegistry::getInstance()->getSerializer($attendee)->serialize()); + return $this->created(SerializerRegistry::getInstance()->getSerializer($attendee)->serialize( + SerializerUtils::getExpand(), + SerializerUtils::getFields(), + SerializerUtils::getRelations() + )); } catch (ValidationException $ex1) { Log::warning($ex1); @@ -592,6 +618,7 @@ final class OAuth2SummitAttendeesApiController extends OAuth2ProtectedController 'email' => 'required_without:member_id|string|max:255|email', 'member_id' => 'required_without_all:first_name,surname,email|integer', 'extra_questions' => 'sometimes|order_extra_question_dto_array', + 'admin_notes' => 'sometimes|string|max:1024', ]; // Creates a Validator instance and validates the data. @@ -671,7 +698,12 @@ final class OAuth2SummitAttendeesApiController extends OAuth2ProtectedController $ticket = $this->summit_order_service->createOrderSingleTicket($summit, $payload); - return $this->created(SerializerRegistry::getInstance()->getSerializer($ticket)->serialize()); + return $this->created(SerializerRegistry::getInstance()->getSerializer($ticket)->serialize + ( + SerializerUtils::getExpand(), + SerializerUtils::getFields(), + SerializerUtils::getRelations() + )); } catch (ValidationException $ex1) { Log::warning($ex1); @@ -742,7 +774,11 @@ final class OAuth2SummitAttendeesApiController extends OAuth2ProtectedController $ticket = $this->attendee_service->reassignAttendeeTicketByMember($summit, $attendee, $other_member, intval($ticket_id)); - return $this->updated(SerializerRegistry::getInstance()->getSerializer($ticket)->serialize()); + return $this->updated(SerializerRegistry::getInstance()->getSerializer($ticket)->serialize( + SerializerUtils::getExpand(), + SerializerUtils::getFields(), + SerializerUtils::getRelations() + )); } catch (ValidationException $ex1) { Log::warning($ex1); @@ -784,7 +820,11 @@ final class OAuth2SummitAttendeesApiController extends OAuth2ProtectedController $ticket = $this->attendee_service->reassignAttendeeTicket($summit, $attendee, intval($ticket_id), $payload); - return $this->updated(SerializerRegistry::getInstance()->getSerializer($ticket)->serialize()); + return $this->updated(SerializerRegistry::getInstance()->getSerializer($ticket)->serialize( + SerializerUtils::getExpand(), + SerializerUtils::getFields(), + SerializerUtils::getRelations() + )); } catch (ValidationException $ex1) { Log::warning($ex1); @@ -807,4 +847,90 @@ final class OAuth2SummitAttendeesApiController extends OAuth2ProtectedController { return $this->summit_repository; } + + /** + * @param $summit_id + * @return \Illuminate\Http\JsonResponse|mixed + */ + public function send($summit_id){ + try { + + if(!Request::isJson()) return $this->error400(); + $data = Input::json(); + + $summit = SummitFinderStrategyFactory::build($this->getSummitRepository(), $this->getResourceServerContext())->find($summit_id); + if (is_null($summit)) return $this->error404(); + + $payload = $data->all(); + + // Creates a Validator instance and validates the data. + $validation = Validator::make($payload, [ + 'email_flow_event' => 'required|string|in:'.join(',', [ + 'ATTENDEE_INVITATION' + ]), + 'attendees_ids' => 'sometimes|int_array', + ]); + + if ($validation->fails()) { + $messages = $validation->messages()->toArray(); + + return $this->error412 + ( + $messages + ); + } + + $filter = null; + + if (Input::has('filter')) { + $filter = FilterParser::parse(Input::get('filter'), [ + 'first_name' => ['=@', '=='], + 'last_name' => ['=@', '=='], + 'full_name' => ['=@', '=='], + 'email' => ['=@', '=='], + 'external_order_id' => ['=@', '=='], + 'company' => ['=@', '=='], + 'external_attendee_id' => ['=@', '=='], + 'member_id' => ['==','<=','>='], + 'ticket_type' => ['=@', '=='], + 'badge_type' => ['=@', '=='], + 'status' => ['=@', '=='], + ]); + } + + if (is_null($filter)) + $filter = new Filter(); + + $filter->validate([ + 'first_name' => 'sometimes|string', + 'last_name' => 'sometimes|string', + 'full_name' => 'sometimes|string', + 'company' => 'sometimes|string', + 'email' => 'sometimes|string', + 'external_order_id' => 'sometimes|string', + 'external_attendee_id' => 'sometimes|string', + 'member_id' => 'sometimes|integer', + 'ticket_type' => 'sometimes|string', + 'badge_type' => 'sometimes|string', + 'status' => 'sometimes|string', + ]); + + $this->attendee_service->triggerSend($summit, $payload, Input::get('filter')); + + return $this->ok(); + + } catch (EntityNotFoundException $ex1) { + Log::warning($ex1); + return $this->error404(); + } catch (ValidationException $ex2) { + Log::warning($ex2); + return $this->error412(array($ex2->getMessage())); + } catch (\HTTP401UnauthorizedException $ex3) { + Log::warning($ex3); + return $this->error401(); + } catch (\Exception $ex) { + Log::error($ex); + return $this->error500($ex); + } + } } \ No newline at end of file diff --git a/app/Http/Controllers/ConfigurationsController.php b/app/Http/Controllers/ConfigurationsController.php index 8fda92de..30374158 100644 --- a/app/Http/Controllers/ConfigurationsController.php +++ b/app/Http/Controllers/ConfigurationsController.php @@ -14,6 +14,7 @@ use App\Models\ResourceServer\IApiRepository; use Illuminate\Support\Facades\Input; use Illuminate\Support\Facades\Log; +use Illuminate\Support\Facades\Request; use Illuminate\Support\Facades\Route; use models\utils\IEntity; use ModelSerializers\SerializerRegistry; @@ -47,7 +48,7 @@ final class ConfigurationsController extends JsonController $items = []; foreach ($this->repository->getAll() as $i) { if ($i instanceof IEntity) { - $i = SerializerRegistry::getInstance()->getSerializer($i, SerializerRegistry::SerializerType_Public)->serialize(Input::get('expand', '')); + $i = SerializerRegistry::getInstance()->getSerializer($i, SerializerRegistry::SerializerType_Public)->serialize(Request::input('expand', '')); } $items[] = $i; } diff --git a/app/Http/Middleware/OAuth2BearerAccessTokenRequestValidator.php b/app/Http/Middleware/OAuth2BearerAccessTokenRequestValidator.php index 432a5d04..5a4e6053 100644 --- a/app/Http/Middleware/OAuth2BearerAccessTokenRequestValidator.php +++ b/app/Http/Middleware/OAuth2BearerAccessTokenRequestValidator.php @@ -110,7 +110,7 @@ class OAuth2BearerAccessTokenRequestValidator } else { // http://tools.ietf.org/html/rfc6750#section-2- 2 // if access token is not on authorization header check on POST/GET params - $access_token_value = Input::get(OAuth2Protocol::OAuth2Protocol_AccessToken, ''); + $access_token_value = Request::input(OAuth2Protocol::OAuth2Protocol_AccessToken, ''); } if (is_null($access_token_value) || empty($access_token_value)) { diff --git a/app/Http/routes.php b/app/Http/routes.php index bd33fc3c..02292bcd 100644 --- a/app/Http/routes.php +++ b/app/Http/routes.php @@ -850,6 +850,10 @@ Route::group([ // attendees Route::group(array('prefix' => 'attendees'), function () { + Route::group(['prefix' => 'all'], function (){ + Route::post('send', [ 'middleware' => 'auth.user', 'uses' => 'OAuth2SummitAttendeesApiController@send']); + }); + Route::get('', [ 'middleware' => 'auth.user', 'uses' => 'OAuth2SummitAttendeesApiController@getAttendeesBySummit']); Route::get('csv', [ 'middleware' => 'auth.user', 'uses' => 'OAuth2SummitAttendeesApiController@getAttendeesBySummitCSV']); Route::get('me', 'OAuth2SummitAttendeesApiController@getOwnAttendee'); diff --git a/app/Jobs/Emails/Registration/AbstractSummitAttendeeTicketEmail.php b/app/Jobs/Emails/Registration/Attendees/AbstractSummitAttendeeTicketEmail.php similarity index 100% rename from app/Jobs/Emails/Registration/AbstractSummitAttendeeTicketEmail.php rename to app/Jobs/Emails/Registration/Attendees/AbstractSummitAttendeeTicketEmail.php diff --git a/app/Jobs/Emails/Registration/InviteAttendeeTicketEditionMail.php b/app/Jobs/Emails/Registration/Attendees/InviteAttendeeTicketEditionMail.php similarity index 98% rename from app/Jobs/Emails/Registration/InviteAttendeeTicketEditionMail.php rename to app/Jobs/Emails/Registration/Attendees/InviteAttendeeTicketEditionMail.php index faa6f482..3f2bdfc6 100644 --- a/app/Jobs/Emails/Registration/InviteAttendeeTicketEditionMail.php +++ b/app/Jobs/Emails/Registration/Attendees/InviteAttendeeTicketEditionMail.php @@ -41,7 +41,7 @@ class InviteAttendeeTicketEditionMail extends AbstractSummitAttendeeTicketEmail $payload['owner_email'] = $owner->getEmail(); $payload['owner_first_name'] = $owner->getFirstName(); $payload['owner_last_name'] = $owner->getSurname(); - + $payload['summit_reassign_ticket_till_date'] = ''; $summit_reassign_ticket_till_date = $summit->getReassignTicketTillDateLocal(); if(!is_null($summit_reassign_ticket_till_date)) { $payload['summit_reassign_ticket_till_date'] = $summit_reassign_ticket_till_date->format("l j F Y h:i A T"); diff --git a/app/Jobs/Emails/Registration/Attendees/ProcessAttendeesEmailRequestJob.php b/app/Jobs/Emails/Registration/Attendees/ProcessAttendeesEmailRequestJob.php new file mode 100644 index 00000000..3231c57d --- /dev/null +++ b/app/Jobs/Emails/Registration/Attendees/ProcessAttendeesEmailRequestJob.php @@ -0,0 +1,72 @@ +summit_id = $summit->getId(); + $this->payload = $payload; + $this->filter = $filter; + } + + public function handle(IAttendeeService $service){ + Log::debug(sprintf("ProcessAttendeesEmailRequestJob::handle summit id %s", $this->summit_id)); + + $filter = !is_null($this->filter) ? FilterParser::parse($this->filter, [ + 'first_name' => ['=@', '=='], + 'last_name' => ['=@', '=='], + 'full_name' => ['=@', '=='], + 'company' => ['=@', '=='], + 'email' => ['=@', '=='], + 'external_order_id' => ['=@', '=='], + 'external_attendee_id' => ['=@', '=='], + 'member_id' => ['==', '>'], + 'ticket_type' => ['=@', '=='], + 'badge_type' => ['=@', '=='], + 'status' => ['=@', '=='], + ]) : null; + + $service->send($this->summit_id, $this->payload, $filter); + } + +} \ No newline at end of file diff --git a/app/Jobs/Emails/Registration/RevocationTicketEmail.php b/app/Jobs/Emails/Registration/Attendees/RevocationTicketEmail.php similarity index 100% rename from app/Jobs/Emails/Registration/RevocationTicketEmail.php rename to app/Jobs/Emails/Registration/Attendees/RevocationTicketEmail.php diff --git a/app/Jobs/Emails/Registration/SummitAttendeeTicketEmail.php b/app/Jobs/Emails/Registration/Attendees/SummitAttendeeTicketEmail.php similarity index 100% rename from app/Jobs/Emails/Registration/SummitAttendeeTicketEmail.php rename to app/Jobs/Emails/Registration/Attendees/SummitAttendeeTicketEmail.php diff --git a/app/Jobs/Emails/Registration/SummitAttendeeTicketRegenerateHashEmail.php b/app/Jobs/Emails/Registration/Attendees/SummitAttendeeTicketRegenerateHashEmail.php similarity index 100% rename from app/Jobs/Emails/Registration/SummitAttendeeTicketRegenerateHashEmail.php rename to app/Jobs/Emails/Registration/Attendees/SummitAttendeeTicketRegenerateHashEmail.php diff --git a/app/ModelSerializers/SerializerRegistry.php b/app/ModelSerializers/SerializerRegistry.php index 2744a411..4c17f206 100644 --- a/app/ModelSerializers/SerializerRegistry.php +++ b/app/ModelSerializers/SerializerRegistry.php @@ -285,11 +285,13 @@ final class SerializerRegistry ]; $this->registry['SummitOrderExtraQuestionAnswer'] = SummitOrderExtraQuestionAnswerSerializer::class; + $this->registry['SummitAttendee'] = [ self::SerializerType_Public => SummitAttendeeSerializer::class, - self::SerializerType_Private => SummitAttendeeSerializer::class, + self::SerializerType_Private => SummitAttendeeAdminSerializer::class, self::SerializerType_CSV => SummitAttendeeCSVSerializer::class, ]; + $this->registry['SummitAttendeeTicket'] = [ self::SerializerType_Public => BaseSummitAttendeeTicketSerializer::class, ISummitAttendeeTicketSerializerTypes::AdminType => SummitAttendeeTicketSerializer::class, diff --git a/app/ModelSerializers/SerializerUtils.php b/app/ModelSerializers/SerializerUtils.php new file mode 100644 index 00000000..a1ffb532 --- /dev/null +++ b/app/ModelSerializers/SerializerUtils.php @@ -0,0 +1,38 @@ + 'admin_notes:json_string', + ]; +} \ No newline at end of file diff --git a/app/ModelSerializers/Summit/Registration/SummitAttendeeSerializer.php b/app/ModelSerializers/Summit/Registration/SummitAttendeeSerializer.php index 27c03c4b..406cfd51 100644 --- a/app/ModelSerializers/Summit/Registration/SummitAttendeeSerializer.php +++ b/app/ModelSerializers/Summit/Registration/SummitAttendeeSerializer.php @@ -17,7 +17,7 @@ use models\summit\SummitAttendee; * Class SummitAttendeeSerializer * @package ModelSerializers */ -final class SummitAttendeeSerializer extends SilverStripeSerializer +class SummitAttendeeSerializer extends SilverStripeSerializer { protected static $array_mappings = [ 'SummitHallCheckedIn' => 'summit_hall_checked_in:json_boolean', @@ -30,7 +30,7 @@ final class SummitAttendeeSerializer extends SilverStripeSerializer 'Email' => 'email:json_string', 'CompanyName' => 'company:json_string', 'DisclaimerAcceptedDate' => 'disclaimer_accepted_date:datetime_epoch', - 'Status' => 'status:json_string' + 'Status' => 'status:json_string', ]; protected static $allowed_relations = [ diff --git a/app/Models/Foundation/Summit/Factories/SummitAttendeeFactory.php b/app/Models/Foundation/Summit/Factories/SummitAttendeeFactory.php index 8de1facf..6af2e09b 100644 --- a/app/Models/Foundation/Summit/Factories/SummitAttendeeFactory.php +++ b/app/Models/Foundation/Summit/Factories/SummitAttendeeFactory.php @@ -74,6 +74,9 @@ final class SummitAttendeeFactory if (isset($payload['company']) && !empty($payload['company'])) $attendee->setCompanyName(trim($payload['company'])); + if (isset($payload['admin_notes']) && !empty($payload['admin_notes'])) + $attendee->setAdminNotes(trim($payload['admin_notes'])); + if (isset($payload['shared_contact_info'])) $attendee->setShareContactInfo(boolval($payload['shared_contact_info'])); diff --git a/app/Models/Foundation/Summit/Registration/Attendees/SummitAttendee.php b/app/Models/Foundation/Summit/Registration/Attendees/SummitAttendee.php index d73ed332..820c7ec6 100644 --- a/app/Models/Foundation/Summit/Registration/Attendees/SummitAttendee.php +++ b/app/Models/Foundation/Summit/Registration/Attendees/SummitAttendee.php @@ -127,6 +127,12 @@ class SummitAttendee extends SilverstripeBaseModel */ private $status; + /** + * @ORM\Column(name="AdminNotes", type="string") + * @var string + */ + private $admin_notes; + /** * @return \DateTime */ @@ -679,4 +685,20 @@ class SummitAttendee extends SilverstripeBaseModel $this->external_id = $external_id; } + /** + * @return string + */ + public function getAdminNotes(): ?string + { + return $this->admin_notes; + } + + /** + * @param string $admin_notes + */ + public function setAdminNotes(string $admin_notes): void + { + $this->admin_notes = $admin_notes; + } + } \ No newline at end of file diff --git a/app/Models/Foundation/Summit/Registration/Attendees/SummitAttendeeTicket.php b/app/Models/Foundation/Summit/Registration/Attendees/SummitAttendeeTicket.php index 007b8462..f9feb4a7 100644 --- a/app/Models/Foundation/Summit/Registration/Attendees/SummitAttendeeTicket.php +++ b/app/Models/Foundation/Summit/Registration/Attendees/SummitAttendeeTicket.php @@ -11,6 +11,8 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ + +use App\Jobs\Emails\SummitAttendeeTicketRegenerateHashEmail; use Illuminate\Support\Facades\Event; use App\Events\RequestedSummitAttendeeTicketRefund; use App\Events\SummitAttendeeTicketRefundAccepted; @@ -291,6 +293,22 @@ class SummitAttendeeTicket extends SilverstripeBaseModel $this->hash_creation_date = new \DateTime('now', new \DateTimeZone('UTC')); } + /** + * @throws ValidationException + */ + public function sendPublicEditEmail(){ + if (!$this->isPaid()) + throw new ValidationException("ticket is not paid"); + + if (!$this->hasOwner()) + throw new ValidationException("ticket must have an assigned owner"); + + $this->generateQRCode(); + $this->generateHash(); + + SummitAttendeeTicketRegenerateHashEmail::dispatch($this); + } + /** * @return bool */ diff --git a/app/Repositories/Summit/DoctrineSummitAttendeeRepository.php b/app/Repositories/Summit/DoctrineSummitAttendeeRepository.php index d1ad5484..9dcf66a0 100644 --- a/app/Repositories/Summit/DoctrineSummitAttendeeRepository.php +++ b/app/Repositories/Summit/DoctrineSummitAttendeeRepository.php @@ -37,7 +37,10 @@ final class DoctrineSummitAttendeeRepository protected function applyExtraJoins(QueryBuilder $query){ $query = $query->join('e.summit', 's') ->leftJoin('e.member', 'm') - ->leftJoin('e.tickets', 't'); + ->leftJoin('e.tickets', 't') + ->leftJoin('t.badge', 'b') + ->leftJoin('b.type', 'bt') + ->leftJoin('t.ticket_type', 'tt'); return $query; } @@ -48,10 +51,14 @@ final class DoctrineSummitAttendeeRepository { return [ 'summit_id' => new DoctrineFilterMapping("s.id :operator :value"), + 'member_id' => new DoctrineFilterMapping("m.id :operator :value"), 'first_name' => [ "m.first_name :operator :value", "e.first_name :operator :value" ], + 'ticket_type' => new DoctrineFilterMapping("tt.name :operator :value"), + 'badge_type' => new DoctrineFilterMapping("bt.name :operator :value"), + 'status' => new DoctrineFilterMapping("e.status :operator :value"), 'last_name' => [ "m.last_name :operator :value", "e.surname :operator :value" @@ -77,10 +84,14 @@ final class DoctrineSummitAttendeeRepository { return [ 'id' => 'e.id', - 'first_name' => 'm.first_name', - 'last_name' => 'm.last_name', + 'first_name' => 'e.first_name', + 'last_name' => 'e.surname', + "full_name" => "LOWER(CONCAT(e.first_name, ' ', e.surname))", 'external_order_id' => 't.external_order_id', - 'company' => 'e.company_name' + 'company' => 'e.company_name', + 'member_id' => 'm.id', + 'status' => 'e.status', + ]; } diff --git a/app/Services/Model/AttendeeService.php b/app/Services/Model/AttendeeService.php index 09ddc048..1bb37734 100644 --- a/app/Services/Model/AttendeeService.php +++ b/app/Services/Model/AttendeeService.php @@ -11,7 +11,10 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ -use GuzzleHttp\Exception\ClientException; + +use App\Jobs\Emails\InviteAttendeeTicketEditionMail; +use App\Jobs\Emails\ProcessAttendeesEmailRequestJob; +use App\Jobs\Emails\SummitAttendeeTicketRegenerateHashEmail; use Illuminate\Support\Facades\Log; use libs\utils\ITransactionService; use models\exceptions\EntityNotFoundException; @@ -19,17 +22,18 @@ use models\exceptions\ValidationException; use models\main\IMemberRepository; use models\main\Member; use models\summit\factories\SummitAttendeeFactory; -use models\summit\factories\SummitAttendeeTicketFactory; use models\summit\ISummitAttendeeRepository; use models\summit\ISummitAttendeeTicketRepository; use models\summit\ISummitRegistrationPromoCodeRepository; use models\summit\ISummitTicketTypeRepository; use models\summit\Summit; use models\summit\SummitAttendee; -use models\summit\SummitAttendeeBadge; use models\summit\SummitAttendeeTicket; -use models\summit\SummitTicketType; use services\apis\IEventbriteAPI; +use utils\Filter; +use utils\FilterElement; +use utils\PagingInfo; + /** * Class AttendeeService * @package App\Services\Model @@ -358,4 +362,64 @@ final class AttendeeService extends AbstractService implements IAttendeeService } + /** + * @inheritDoc + */ + public function triggerSend(Summit $summit, array $payload, $filter = null): void + { + ProcessAttendeesEmailRequestJob::dispatch($summit, $payload, $filter); + } + + /** + * @inheritDoc + */ + public function send(int $summit_id, array $payload, Filter $filter = null): void + { + $flow_event = trim($payload['email_flow_event']); + + Log::debug(sprintf("AttendeeService::send summit id %s flow_event %s", $summit_id, $flow_event)); + + $ids = $this->tx_service->transaction(function() use($summit_id, $payload, $filter){ + if(isset($payload['attendees_ids'])) { + Log::debug(sprintf("AttendeeService::send summit id %s attendees_ids %s", $summit_id, json_encode($payload['attendees_ids']))); + return $payload['attendees_ids']; + } + Log::debug(sprintf("AttendeeService::send summit id %s getting by filter", $summit_id)); + if(is_null($filter)){ + $filter = new Filter(); + } + $filter->addFilterCondition(FilterElement::makeEqual('summit_id', $summit_id)); + return $this->attendee_repository->getAllIdsByPage(new PagingInfo(1, PHP_INT_MAX), $filter); + }); + + foreach ($ids as $attendee_id) + try { + $this->tx_service->transaction(function () use ($flow_event, $attendee_id) { + + Log::debug(sprintf("AttendeeService::send processing attendee id %s", $attendee_id)); + + $attendee = $this->attendee_repository->getByIdExclusiveLock(intval($attendee_id)); + if (is_null($attendee) || !$attendee instanceof SummitAttendee) return; + + foreach ($attendee->getTickets() as $ticket) { + try { + Log::debug(sprintf("AttendeeService::send processing attendee %s - ticket %s", $attendee->getEmail(), $ticket->getId())); + // send email + if ($flow_event == SummitAttendeeTicketRegenerateHashEmail::EVENT_SLUG) { + $ticket->sendPublicEditEmail(); + } + + if ($flow_event == InviteAttendeeTicketEditionMail::EVENT_SLUG) { + $attendee->sendInvitationEmail($ticket); + } + } catch (\Exception $ex) { + Log::warning($ex); + } + } + }); + } + catch (\Exception $ex) { + Log::warning($ex); + } + } } \ No newline at end of file diff --git a/app/Services/Model/IAttendeeService.php b/app/Services/Model/IAttendeeService.php index c3900e55..e6822cdd 100644 --- a/app/Services/Model/IAttendeeService.php +++ b/app/Services/Model/IAttendeeService.php @@ -17,6 +17,8 @@ use models\main\Member; use models\summit\Summit; use models\summit\SummitAttendee; use models\summit\SummitAttendeeTicket; +use utils\Filter; + /** * Interface IAttendeeService * @package App\Services\Model @@ -86,4 +88,18 @@ interface IAttendeeService * @throws \Exception */ public function reassignAttendeeTicket(Summit $summit, SummitAttendee $attendee, int $ticket_id, array $payload):SummitAttendeeTicket; + + /** + * @param Summit $summit + * @param array $payload + * @param mixed $filter + */ + public function triggerSend(Summit $summit, array $payload, $filter = null):void; + + /** + * @param int $summit_id + * @param array $payload + * @param Filter|null $filter + */ + public function send(int $summit_id, array $payload, Filter $filter = null):void; } \ No newline at end of file diff --git a/app/Services/Model/Imp/SummitOrderService.php b/app/Services/Model/Imp/SummitOrderService.php index 982a0d5d..02d2bb2f 100644 --- a/app/Services/Model/Imp/SummitOrderService.php +++ b/app/Services/Model/Imp/SummitOrderService.php @@ -26,7 +26,6 @@ use App\Models\Foundation\Summit\Factories\SummitOrderFactory; use App\Models\Foundation\Summit\Registration\IBuildDefaultPaymentGatewayProfileStrategy; use App\Models\Foundation\Summit\Repositories\ISummitAttendeeBadgePrintRuleRepository; use App\Models\Foundation\Summit\Repositories\ISummitAttendeeBadgeRepository; -use App\Services\Apis\IExternalUserApi; use App\Services\Utils\CSVReader; use Illuminate\Http\UploadedFile; use Illuminate\Support\Facades\Event; @@ -1643,16 +1642,7 @@ final class SummitOrderService if (is_null($ticket)) throw new EntityNotFoundException("ticket not found"); - if (!$ticket->isPaid()) - throw new ValidationException("ticket is not paid"); - - if (!$ticket->hasOwner()) - throw new ValidationException("ticket must have an assigned owner"); - - $ticket->generateQRCode(); - $ticket->generateHash(); - - SummitAttendeeTicketRegenerateHashEmail::dispatch($ticket); + $ticket->sendPublicEditEmail(); }); } diff --git a/database/migrations/model/Version20201022181641.php b/database/migrations/model/Version20201022181641.php index 7a046e6f..c4ce478b 100644 --- a/database/migrations/model/Version20201022181641.php +++ b/database/migrations/model/Version20201022181641.php @@ -1,12 +1,24 @@ -hasTable("SummitAttendee") && !$builder->hasColumn("SummitAttendee", "AdminNotes")) { + $builder->table('SummitAttendee', function (Table $table) { + $table->string("AdminNotes", 1024)->setNotnull(false)->setDefault(null); + }); + } + } + + /** + * @param Schema $schema + */ + public function down(Schema $schema) + { + $builder = new Builder($schema); + + if($schema->hasTable("SummitAttendee") && $builder->hasColumn("SummitAttendee", "AdminNotes")) { + $builder->table('SummitAttendee', function (Table $table) { + $table->dropColumn("AdminNotes"); + }); + } + } +}