diff --git a/app/Console/Commands/SummitListJsonGenerator.php b/app/Console/Commands/SummitListJsonGenerator.php index 05986b25..cd249ec2 100644 --- a/app/Console/Commands/SummitListJsonGenerator.php +++ b/app/Console/Commands/SummitListJsonGenerator.php @@ -13,9 +13,8 @@ **/ use Illuminate\Support\Facades\Log; use libs\utils\ICacheService; -use Mockery\Exception; +use Exception; use models\summit\ISummitRepository; -use ModelSerializers\SerializerRegistry; use services\model\ISummitService; use utils\PagingResponse; use Illuminate\Console\Command; diff --git a/app/Console/Commands/SummitRoomReservationRevocationCommand.php b/app/Console/Commands/SummitRoomReservationRevocationCommand.php new file mode 100644 index 00000000..87d73d87 --- /dev/null +++ b/app/Console/Commands/SummitRoomReservationRevocationCommand.php @@ -0,0 +1,113 @@ +reservations_repository = $reservations_repository; + $this->tx_service = $tx_service; + } + + /** + * Execute the console command. + * + * @return mixed + */ + public function handle() + { + + try { + + $this->info("processing summit room reservations"); + $start = time(); + + $this->tx_service->transaction(function(){ + $filter = new Filter(); + $filter->addFilterCondition(FilterElement::makeEqual('status', SummitRoomReservation::ReservedStatus)); + $eol = new \DateTime('now', new \DateTimeZone('UTC')); + $lifetime = intval(Config::get("bookable_rooms.reservation_lifetime", 5)); + $eol->sub(new \DateInterval('PT'.$lifetime.'M')); + $filter->addFilterCondition(FilterElement::makeLowerOrEqual('created', $eol->getTimestamp() )); + $page = $this->reservations_repository->getAllByPage(new PagingInfo(1, 100), $filter); + foreach($page->getItems() as $reservation){ + $reservation->cancel(); + } + }); + + $end = time(); + $delta = $end - $start; + $this->info(sprintf("execution call %s seconds", $delta)); + } + catch (Exception $ex) { + Log::error($ex); + } + } +} \ No newline at end of file diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 5b899d52..333ed36b 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -32,6 +32,7 @@ class Kernel extends ConsoleKernel \App\Console\Commands\ChatTeamMessagesSender::class, \App\Console\Commands\SummitListJsonGenerator::class, \App\Console\Commands\PromoCodesRedeemProcessor::class, + \App\Console\Commands\SummitRoomReservationRevocationCommand::class, ]; /** @@ -79,5 +80,8 @@ class Kernel extends ConsoleKernel $schedule->command('summit:promo-codes-redeem-processor', [end($summit_ids)])->daily()->withoutOverlapping(); + // bookable rooms + + $schedule->command('summit:room-reservation-revocation')->everyFiveMinutes()->withoutOverlapping(); } } diff --git a/app/Events/BookableRooms/BookableRoomReservationCanceled.php b/app/Events/BookableRooms/BookableRoomReservationCanceled.php new file mode 100644 index 00000000..ee1c9af5 --- /dev/null +++ b/app/Events/BookableRooms/BookableRoomReservationCanceled.php @@ -0,0 +1,22 @@ +summit_service->addBookableRoomAttribute($summit, $payload); - return $this->created(SerializerRegistry::getInstance()->getSerializer($attr)->serialize()); + return $this->created(SerializerRegistry::getInstance()->getSerializer($attr)->serialize(Request::input('expand', ''))); } catch (ValidationException $ex1) { Log::warning($ex1); @@ -235,7 +235,7 @@ final class OAuth2SummitBookableRoomsAttributeTypeApiController extends OAuth2Pr $attr = $summit->getBookableAttributeTypeById($type_id); if (is_null($attr)) return $this->error404(); - return $this->ok(SerializerRegistry::getInstance()->getSerializer($attr)->serialize()); + return $this->ok(SerializerRegistry::getInstance()->getSerializer($attr)->serialize(Request::input('expand', ''))); } catch (ValidationException $ex1) { Log::warning($ex1); diff --git a/app/Mail/AbstractBookableRoomReservationEmail.php b/app/Mail/AbstractBookableRoomReservationEmail.php new file mode 100644 index 00000000..2e2222db --- /dev/null +++ b/app/Mail/AbstractBookableRoomReservationEmail.php @@ -0,0 +1,42 @@ +reservation = $reservation; + } + + +} diff --git a/app/Mail/BookableRoomReservationCanceledEmail.php b/app/Mail/BookableRoomReservationCanceledEmail.php new file mode 100644 index 00000000..d4ce3e7e --- /dev/null +++ b/app/Mail/BookableRoomReservationCanceledEmail.php @@ -0,0 +1,37 @@ +from(Config::get("mail.from")) + ->to($this->reservation->getOwner()->getEmail()) + ->subject($subject) + ->view('emails.bookable_rooms.reservation_canceled'); + } +} diff --git a/app/Mail/BookableRoomReservationCreatedEmail.php b/app/Mail/BookableRoomReservationCreatedEmail.php new file mode 100644 index 00000000..57d2edf9 --- /dev/null +++ b/app/Mail/BookableRoomReservationCreatedEmail.php @@ -0,0 +1,37 @@ +from(Config::get("mail.from")) + ->to($this->reservation->getOwner()->getEmail()) + ->subject($subject) + ->view('emails.bookable_rooms.reservation_created'); + } +} diff --git a/app/Mail/BookableRoomReservationPaymentConfirmedEmail.php b/app/Mail/BookableRoomReservationPaymentConfirmedEmail.php new file mode 100644 index 00000000..b57a4997 --- /dev/null +++ b/app/Mail/BookableRoomReservationPaymentConfirmedEmail.php @@ -0,0 +1,38 @@ +from(Config::get("mail.from")) + ->to($this->reservation->getOwner()->getEmail()) + ->subject($subject) + ->view('emails.bookable_rooms.reservation_payment_confirmed'); + } +} diff --git a/app/Mail/BookableRoomReservationRefundAcceptedEmail.php b/app/Mail/BookableRoomReservationRefundAcceptedEmail.php new file mode 100644 index 00000000..81c02fe3 --- /dev/null +++ b/app/Mail/BookableRoomReservationRefundAcceptedEmail.php @@ -0,0 +1,38 @@ +from(Config::get("mail.from")) + ->to($this->reservation->getOwner()->getEmail()) + ->subject($subject) + ->view('emails.bookable_rooms.reservation_refund_accepted'); + } +} diff --git a/app/Mail/BookableRoomReservationRefundRequestedAdminEmail.php b/app/Mail/BookableRoomReservationRefundRequestedAdminEmail.php new file mode 100644 index 00000000..9cdc13ca --- /dev/null +++ b/app/Mail/BookableRoomReservationRefundRequestedAdminEmail.php @@ -0,0 +1,38 @@ +from(Config::get("mail.from")) + ->to(Config::get("bookable_rooms.admin_email")) + ->subject($subject) + ->view('emails.bookable_rooms.reservation_refund_requested_admin'); + } +} diff --git a/app/Mail/BookableRoomReservationRefundRequestedOwnerEmail.php b/app/Mail/BookableRoomReservationRefundRequestedOwnerEmail.php new file mode 100644 index 00000000..cb2d276d --- /dev/null +++ b/app/Mail/BookableRoomReservationRefundRequestedOwnerEmail.php @@ -0,0 +1,30 @@ +view('view.name'); + } +} diff --git a/app/Models/Foundation/Summit/Locations/SummitRoomReservation.php b/app/Models/Foundation/Summit/Locations/SummitRoomReservation.php index b4a77b07..f458b1ff 100644 --- a/app/Models/Foundation/Summit/Locations/SummitRoomReservation.php +++ b/app/Models/Foundation/Summit/Locations/SummitRoomReservation.php @@ -11,9 +11,14 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ -use Doctrine\ORM\Mapping AS ORM; +use App\Events\BookableRoomReservationCanceled; +use App\Events\BookableRoomReservationRefundAccepted; +use App\Events\PaymentBookableRoomReservationConfirmed; +use App\Events\RequestedBookableRoomReservationRefund; +use Illuminate\Support\Facades\Event; use models\main\Member; use models\utils\SilverstripeBaseModel; +use Doctrine\ORM\Mapping AS ORM; /** * @ORM\Entity(repositoryClass="App\Repositories\Summit\DoctrineSummitRoomReservationRepository") * @ORM\Table(name="SummitRoomReservation") @@ -60,6 +65,7 @@ class SummitRoomReservation extends SilverstripeBaseModel /** * @var string + * @ORM\Column(name="PaymentGatewayClientToken", type="string") */ private $payment_gateway_client_token; @@ -75,6 +81,12 @@ class SummitRoomReservation extends SilverstripeBaseModel */ private $amount; + /** + * @var float + * @ORM\Column(name="RefundedAmount", type="float") + */ + private $refunded_amount; + /** * @ORM\ManyToOne(targetEntity="models\main\Member", inversedBy="reservations") * @ORM\JoinColumn(name="OwnerID", referencedColumnName="ID") @@ -94,6 +106,7 @@ class SummitRoomReservation extends SilverstripeBaseModel const PayedStatus = "Payed"; const RequestedRefundStatus = "RequestedRefund"; const RefundedStatus = "Refunded"; + const Canceled = "Canceled"; public static $valid_status = [ self::ReservedStatus, @@ -101,6 +114,7 @@ class SummitRoomReservation extends SilverstripeBaseModel self::RequestedRefundStatus, self::RefundedStatus, self::ErrorStatus, + self::Canceled ]; /** @@ -111,6 +125,15 @@ class SummitRoomReservation extends SilverstripeBaseModel return $this->start_datetime; } + /** + * @param float $amount + */ + public function refund(float $amount){ + $this->status = self::RefundedStatus; + $this->refunded_amount = $amount; + Event::fire(new BookableRoomReservationRefundAccepted($this->getId())); + } + /** * @return \DateTime */ @@ -290,10 +313,17 @@ class SummitRoomReservation extends SilverstripeBaseModel $this->status = self::PayedStatus; $now = new \DateTime('now', new \DateTimeZone('UTC')); $this->approved_payment_date = $now; + Event::fire(new PaymentBookableRoomReservationConfirmed($this->getId())); + } + + public function cancel():void{ + $this->status = self::Canceled; + Event::fire(new BookableRoomReservationCanceled($this->id)); } public function requestRefund():void{ $this->status = self::RequestedRefundStatus; + Event::fire(new RequestedBookableRoomReservationRefund($this->getId())); } public function setPaymentError(string $error):void{ @@ -325,4 +355,20 @@ class SummitRoomReservation extends SilverstripeBaseModel } } + /** + * @return float + */ + public function getRefundedAmount(): float + { + return $this->refunded_amount; + } + + /** + * @param float $refunded_amount + */ + public function setRefundedAmount(float $refunded_amount): void + { + $this->refunded_amount = $refunded_amount; + } + } \ No newline at end of file diff --git a/app/Models/Foundation/Summit/Locations/SummitVenueRoom.php b/app/Models/Foundation/Summit/Locations/SummitVenueRoom.php index bb08805d..461fb79c 100644 --- a/app/Models/Foundation/Summit/Locations/SummitVenueRoom.php +++ b/app/Models/Foundation/Summit/Locations/SummitVenueRoom.php @@ -19,7 +19,7 @@ use Doctrine\ORM\Mapping AS ORM; /** * @ORM\Entity * @ORM\Table(name="SummitVenueRoom") - * Class SummitVenueRoom + * Class SummitVenueRoomgetLocalEndDatetime * @package models\summit */ class SummitVenueRoom extends SummitAbstractLocation implements IOrderable @@ -72,6 +72,16 @@ class SummitVenueRoom extends SummitAbstractLocation implements IOrderable return $this->venue; } + /** + * @return string + */ + public function getCompleteName():string{ + $name = $this->venue->getSummit()->getName(); + $name .= ' '.$this->venue->getName(); + $name .= ' '.$this->getName(); + return $name; + } + /** * @return int */ diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index e52683ad..1507cfc2 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -38,9 +38,16 @@ use App\Factories\EntityEvents\SummitEventUpdatedEntityEventFactory; use App\Factories\EntityEvents\SummitTicketTypeActionEntityEventFactory; use App\Factories\EntityEvents\TrackActionEntityEventFactory; use App\Factories\EntityEvents\TrackGroupActionActionEntityEventFactory; +use App\Mail\BookableRoomReservationCanceledEmail; +use App\Mail\BookableRoomReservationCreatedEmail; +use App\Mail\BookableRoomReservationPaymentConfirmedEmail; +use App\Mail\BookableRoomReservationRefundAcceptedEmail; +use App\Mail\BookableRoomReservationRefundRequestedAdminEmail; +use App\Mail\BookableRoomReservationRefundRequestedOwnerEmail; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\App; +use Illuminate\Support\Facades\Mail; use LaravelDoctrine\ORM\Facades\EntityManager; use models\summit\SummitRoomReservation; @@ -326,21 +333,48 @@ final class EventServiceProvider extends ServiceProvider Event::listen(\App\Events\BookableRoomReservationRefundAccepted::class, function($event) { $repository = EntityManager::getRepository(SummitRoomReservation::class); + $reservation = $repository->find($event->getReservationId()); + if(is_null($reservation) || ! $reservation instanceof SummitRoomReservation) return; + + Mail::send(new BookableRoomReservationRefundAcceptedEmail($reservation)); + }); Event::listen(\App\Events\CreatedBookableRoomReservation::class, function($event) { $repository = EntityManager::getRepository(SummitRoomReservation::class); + $reservation = $repository->find($event->getReservationId()); + if(is_null($reservation) || ! $reservation instanceof SummitRoomReservation) return; + + Mail::send(new BookableRoomReservationCreatedEmail($reservation)); + }); Event::listen(\App\Events\PaymentBookableRoomReservationConfirmed::class, function($event) { $repository = EntityManager::getRepository(SummitRoomReservation::class); + $reservation = $repository->find($event->getReservationId()); + if(is_null($reservation) || ! $reservation instanceof SummitRoomReservation) return; + + Mail::send(new BookableRoomReservationPaymentConfirmedEmail($reservation)); }); Event::listen(\App\Events\RequestedBookableRoomReservationRefund::class, function($event) { $repository = EntityManager::getRepository(SummitRoomReservation::class); + $reservation = $repository->find($event->getReservationId()); + if(is_null($reservation) || ! $reservation instanceof SummitRoomReservation) return; + + Mail::send(new BookableRoomReservationRefundRequestedAdminEmail($reservation)); + Mail::send(new BookableRoomReservationRefundRequestedOwnerEmail($reservation)); + }); + + Event::listen(\App\Events\BookableRoomReservationCanceled::class, function($event) + { + $repository = EntityManager::getRepository(SummitRoomReservation::class); + $reservation = $repository->find($event->getReservationId()); + if(is_null($reservation) || ! $reservation instanceof SummitRoomReservation) return; + Mail::send(new BookableRoomReservationCanceledEmail($reservation)); }); } } diff --git a/app/Repositories/Summit/DoctrineSummitRoomReservationRepository.php b/app/Repositories/Summit/DoctrineSummitRoomReservationRepository.php index 0049d238..5632b39a 100644 --- a/app/Repositories/Summit/DoctrineSummitRoomReservationRepository.php +++ b/app/Repositories/Summit/DoctrineSummitRoomReservationRepository.php @@ -49,6 +49,7 @@ class DoctrineSummitRoomReservationRepository 'status' => 'e.status:json_string', 'start_datetime' => 'e.start_datetime:datetime_epoch', 'end_datetime' => 'e.end_datetime:datetime_epoch', + 'created' => 'e.created:datetime_epoch', 'room_id' => new DoctrineJoinFilterMapping ( 'e.room', diff --git a/app/Services/Model/SummitLocationService.php b/app/Services/Model/SummitLocationService.php index 6f97465c..eea607dd 100644 --- a/app/Services/Model/SummitLocationService.php +++ b/app/Services/Model/SummitLocationService.php @@ -11,7 +11,6 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ - use App\Events\CreatedBookableRoomReservation; use App\Events\FloorDeleted; use App\Events\FloorInserted; @@ -22,8 +21,6 @@ use App\Events\LocationImageInserted; use App\Events\LocationImageUpdated; use App\Events\LocationInserted; use App\Events\LocationUpdated; -use App\Events\PaymentBookableRoomReservationConfirmed; -use App\Events\RequestedBookableRoomReservationRefund; use App\Events\SummitVenueRoomDeleted; use App\Events\SummitVenueRoomInserted; use App\Events\SummitVenueRoomUpdated; @@ -57,7 +54,6 @@ use models\summit\SummitRoomReservation; use models\summit\SummitVenue; use models\summit\SummitVenueFloor; use models\summit\SummitVenueRoom; - /** * Class SummitLocationService * @package App\Services\Model @@ -1755,7 +1751,6 @@ final class SummitLocationService if ($this->payment_gateway->isSuccessFullPayment($payload)) { $reservation->setPayed(); - Event::fire(new PaymentBookableRoomReservationConfirmed($reservation->getId())); return; } @@ -1795,8 +1790,6 @@ final class SummitLocationService $reservation->requestRefund(); - Event::fire(new RequestedBookableRoomReservationRefund($reservation->getId())); - return $reservation; }); } @@ -1828,9 +1821,7 @@ final class SummitLocationService $this->payment_gateway->refundPayment($reservation->getPaymentGatewayCartId(), $amount); - $reservation->setStatus(SummitRoomReservation::RefundedStatus); - - Event::fire(new CreatedBookableRoomReservation($reservation->getId())); + $reservation->refund($amount); return $reservation; }); diff --git a/config/app.php b/config/app.php index 9754b1ff..523e06c9 100644 --- a/config/app.php +++ b/config/app.php @@ -209,4 +209,7 @@ return [ 'Encryption' => services\utils\Facades\Encryption::class, ], + 'app_name' => env('APP_NAME', 'Open Infrastructure Summit'), + 'tenant_name' => env('TENANT_NAME', 'OpenStack'), + ]; diff --git a/config/bookable_rooms.php b/config/bookable_rooms.php new file mode 100644 index 00000000..8f0e9bb4 --- /dev/null +++ b/config/bookable_rooms.php @@ -0,0 +1,17 @@ + env('BOOKABLE_ROOMS_RESERVATION_LIFETIME', 5), + 'admin_email' => env('BOOKABLE_ROOMS_ADMIN_EMAIL'), +]; \ No newline at end of file diff --git a/config/mail.php b/config/mail.php index a0765885..e176c14c 100644 --- a/config/mail.php +++ b/config/mail.php @@ -55,7 +55,7 @@ return [ | */ - 'from' => ['address' => null, 'name' => null], + 'from' => ['address' => env('MAIL_FROM_EMAIL'), 'name' => env('MAIL_FROM_NAME')], /* |-------------------------------------------------------------------------- diff --git a/database/migrations/model/Version20190626125814.php b/database/migrations/model/Version20190626125814.php new file mode 100644 index 00000000..d51ecb3e --- /dev/null +++ b/database/migrations/model/Version20190626125814.php @@ -0,0 +1,46 @@ +hasTable("SummitRoomReservation")) { + $builder->table('SummitRoomReservation', function (Table $table) { + $table->text("PaymentGatewayClientToken"); + $table->decimal("RefundedAmount", 9, 2)->setDefault('0.00'); + }); + } + } + + /** + * @param Schema $schema + */ + public function down(Schema $schema) + { + + } +} diff --git a/resources/views/emails/bookable_rooms/reservation_canceled.blade.php b/resources/views/emails/bookable_rooms/reservation_canceled.blade.php new file mode 100644 index 00000000..77de8858 --- /dev/null +++ b/resources/views/emails/bookable_rooms/reservation_canceled.blade.php @@ -0,0 +1,25 @@ + + +
+ + + ++ Dear {!! $reservation->getOwner()->getFullName() !!}, +
++ Your Reservation for room {!! $reservation->getRoom()->getCompleteName() !!} got canceled because you did not take any action to pay it. +
++ Id {!! $reservation->getId()!!} + Owner {!! $reservation->getOwner()->getFullName()!!} + Email {!! $reservation->getOwner()->getEmail()!!} + From {!! $reservation->getLocalStartDatetime()->format("Y-m-d H:i:s") !!} + To {!! $reservation->getLocalEndDatetime()->format("Y-m-d H:i:s") !!} + Created {!! $reservation->getCreated()->format("Y-m-d H:i:s") !!} + Amount {!! $reservation->getAmount() !!} + Currency {!! $reservation->getCurrency() !!} +
+Cheers,
{!! Config::get('app.tenant_name') !!} Support Team
+ Dear {!! $reservation->getOwner()->getFullName() !!}, +
++ Your Reservation for room {!! $reservation->getRoom()->getCompleteName() !!} has been created successfully. +
+Cheers,
{!! Config::get('app.tenant_name') !!} Support Team
+ Dear {!! $reservation->getOwner()->getFullName() !!}, +
++ Your Reservation for room {!! $reservation->getRoom()->getCompleteName() !!} has been confirmed. +
++ Please take note of the reservation info bellow: +
++ From {!! $reservation->getLocalStartDatetime()->format("Y-m-d H:i:s") !!} + To {!! $reservation->getLocalEndDatetime()->format("Y-m-d H:i:s") !!} + Room Capacity {!! $reservation->getRoom()->getCapacity() !!} + Amount {!! $reservation->getAmount() !!} + Currency {!! $reservation->getCurrency() !!} +
+Cheers,
{!! Config::get('app.tenant_name') !!} Support Team
+ Dear {!! $reservation->getOwner()->getFullName() !!}, +
++ Your Refund Request Reservation for room {!! $reservation->getRoom()->getCompleteName() !!} has been confirmed. +
++ Please take note of the reservation info bellow: +
++ From {!! $reservation->getLocalStartDatetime()->format("Y-m-d H:i:s") !!} + To {!! $reservation->getLocalEndDatetime()->format("Y-m-d H:i:s") !!} + Room Capacity {!! $reservation->getRoom()->getCapacity() !!} + Amount {!! $reservation->getRefundedAmount() !!} + Currency {!! $reservation->getCurrency() !!} +
+Cheers,
{!! Config::get('app.tenant_name') !!} Support Team
+ There is a new reservation refund request available to process +
++ Please take note of the reservation info bellow: +
++ Id {!! $reservation->getId()!!} + Owner {!! $reservation->getOwner()->getFullName()!!} + Email {!! $reservation->getOwner()->getEmail()!!} + From {!! $reservation->getLocalStartDatetime()->format("Y-m-d H:i:s") !!} + To {!! $reservation->getLocalEndDatetime()->format("Y-m-d H:i:s") !!} + Created {!! $reservation->getCreated()->format("Y-m-d H:i:s") !!} + Amount {!! $reservation->getAmount() !!} + Currency {!! $reservation->getCurrency() !!} +
+Cheers,
{!! Config::get('app.tenant_name') !!} Support Team
+ Dear {!! $reservation->getOwner()->getFullName() !!}, +
++ You had requested a refund for your reservation. +
++ Please take note of the reservation info bellow: +
++ Id {!! $reservation->getId()!!} + Owner {!! $reservation->getOwner()->getFullName()!!} + Email {!! $reservation->getOwner()->getEmail()!!} + From {!! $reservation->getLocalStartDatetime()->format("Y-m-d H:i:s") !!} + To {!! $reservation->getLocalEndDatetime()->format("Y-m-d H:i:s") !!} + Created {!! $reservation->getCreated()->format("Y-m-d H:i:s") !!} + Amount {!! $reservation->getAmount() !!} + Currency {!! $reservation->getCurrency() !!} +
+Cheers,
{!! Config::get('app.tenant_name') !!} Support Team
Dear {{ $request->getRequestedBy()->getFullName() }}, - User {{ $request->getSpeaker()->getFullName() }} has approved your request to edit his/her Speaker Profile.
- The OpenStack Team. -
\ No newline at end of file + User {{ $request->getSpeaker()->getFullName() }} has approved your request to edit his/her Speaker Profile. + +Cheers,
{!! Config::get('app.tenant_name') !!} Support Team
Dear {{ $request->getRequestedBy()->getFullName() }}, - User {{ $request->getSpeaker()->getFullName() }} has rejected your request to edit his/her Speaker Profile.
- The OpenStack Team. -
\ No newline at end of file + User {{ $request->getSpeaker()->getFullName() }} has rejected your request to edit his/her Speaker Profile. + +Cheers,
{!! Config::get('app.tenant_name') !!} Support Team
Dear {{ $request->getSpeaker()->getFullName() }}, - User {{ $request->getRequestedBy()->getFullName() }} has requested to be able to edit your Speaker Profile. - To Allow that please click on the following link Allow.
- The OpenStack Team. -
\ No newline at end of file + User {{ $request->getRequestedBy()->getFullName() }} has requested to be able to edit your Speaker Profile. + ++ To Allow that please click on the following link Allow. +
+Cheers,
{!! Config::get('app.tenant_name') !!} Support Team