Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ LOG_STACK=single
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug

DB_CONNECTION=sqlite
# DB_HOST=127.0.0.1
# DB_PORT=3306
# DB_DATABASE=laravel
# DB_USERNAME=root
# DB_PASSWORD=
DB_CONNECTION=pgsql
DB_HOST=db-email
DB_PORT=5432
DB_DATABASE=
DB_USERNAME=
DB_PASSWORD=

SESSION_DRIVER=database
SESSION_LIFETIME=120
Expand Down Expand Up @@ -87,6 +87,8 @@ RABBITMQ_DEFAULT_HOST=
RABBITMQ_DEFAULT_PORT=
RABBITMQ_DEFAULT_USER=
RABBITMQ_DEFAULT_PASS=
RABBITMQ_EXCHANGE_PLUGINS=
RABBITMQ_QUEUE_OPINIONS_PUBLISHED=
RABBITMQ_QUEUE_PC=
RABBITMQ_QUEUE_PC_ROUTE_KEY_PROP=
RABBITMQ_QUEUE_PC_ROUTE_KEY_ADM=
2 changes: 2 additions & 0 deletions .env.testing
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ RABBITMQ_DEFAULT_HOST=rabbitmq
RABBITMQ_DEFAULT_PORT=5672
RABBITMQ_DEFAULT_USER=mqadmin
RABBITMQ_DEFAULT_PASS=Admin123XX_
RABBITMQ_EXCHANGE_PLUGINS=pluginsTest
RABBITMQ_QUEUE_OPINIONS_PUBLISHED=opinionsPublishedTest
RABBITMQ_QUEUE_PC=msgs
RABBITMQ_QUEUE_PC_ROUTE_KEY_PROP=proponente
RABBITMQ_QUEUE_PC_ROUTE_KEY_ADM=resposta
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ RUN apk add --no-cache \
# Limpeza dos pacotes
&& docker-php-source delete

EXPOSE 9000
EXPOSE 9000
75 changes: 75 additions & 0 deletions app/Console/Commands/ConsumePublishedOpinions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<?php

declare(strict_types=1);

namespace App\Console\Commands;

use App\Mail\PublishedOpinions;
use App\Services\AmqpService;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Mail;
use PhpAmqpLib\Message\AMQPMessage;

class ConsumePublishedOpinions extends Command
{
protected $signature = 'rabbitmq:consume-published-opinions-emails';

protected $description = 'Consome fila com usuários que deverão ser notificados que os pareceres foram publicados';

public function __construct(
private readonly AmqpService $amqpService,
) {
parent::__construct();
}

/**
* @throws \Exception
*/
public function handle(): int
{
$queue = config('app.rabbitmq.queues.opinions_published');
$this->info('🎯 Aguardando e-mails para envio...');
$this->amqpService->consumeQueue($queue, $this->processMessage(...));

return Command::SUCCESS;
}

private function processMessage(AMQPMessage $message): void
{
$data = json_decode($message->getBody(), true);

foreach ($data['registrations'] as $item) {
$sent = $this->sendMail($item, $data['opportunity']);

if (! $sent) {
// @todo: Decidir o que fazer em caso de erro no envio.
}
}

$message->ack();
}

private function sendMail(array $registration, array $opportunity): bool
{
try {
$email = $registration['agent']['email'];
$name = $registration['agent']['name'];

$sent = Mail::to($email, $name)
->send(new PublishedOpinions([
'opportunity' => $opportunity,
'registration' => $registration,
]));

$this->info("📧 E-mail enviado para: {$name} <{$email}>");
} catch (\Exception $e) {
logger($e->getMessage());

$this->error("❌ Falha ao enviar e-mail para: {$name} <{$email}>");

return false;
}

return (bool) $sent;
}
}
38 changes: 38 additions & 0 deletions app/Mail/PublishedOpinions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

declare(strict_types=1);

namespace App\Mail;

use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;

class PublishedOpinions extends Mailable
{
use Queueable, SerializesModels;

public function __construct(
protected array $data,
) {}

public function envelope(): Envelope
{
return new Envelope(
subject: 'Pareceres da inscrição publicados',
);
}

public function content(): Content
{
return new Content(
view: 'emails.published-opinions',
with: [
'opportunity' => $this->data['opportunity'],
'registration' => $this->data['registration'],
],
);
}
}
47 changes: 47 additions & 0 deletions app/Services/AmqpService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

declare(strict_types=1);

namespace App\Services;

use PhpAmqpLib\Channel\AMQPChannel;
use PhpAmqpLib\Connection\AMQPStreamConnection;

class AmqpService
{
private AMQPStreamConnection $connection;

private AMQPChannel $channel;

/**
* @throws \Exception
*/
public function __construct()
{
$this->connection = new AMQPStreamConnection(
config('app.rabbitmq.host'),
config('app.rabbitmq.port'),
config('app.rabbitmq.user'),
config('app.rabbitmq.pass'),
);

$this->channel = $this->connection->channel();
}

/**
* @throws \Exception
*/
public function consumeQueue(string $queue, callable $callback): void
{
$this->channel->queue_declare(queue: $queue, durable: true, auto_delete: false);

$this->channel->basic_consume(queue: $queue, callback: $callback);

while ($this->channel->is_consuming()) {
$this->channel->wait();
}

$this->channel->close();
$this->connection->close();
}
}
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
"license": "MIT",
"require": {
"php": "^8.4",
"ext-pdo": "*",
"guzzlehttp/guzzle": "^7.0",
"juniorshyko/phpextensive": "^1.0",
"laravel/framework": "^12.0",
"laravel/sanctum": "^4.0",
"laravel/tinker": "^2.9",
"php-amqplib/php-amqplib": "^3.2",
"tymon/jwt-auth": "^2.1",
"ext-pdo": "*"
"tymon/jwt-auth": "^2.1"
},
"require-dev": {
"brianium/paratest": "^7.8",
Expand Down
18 changes: 10 additions & 8 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions config/app.php
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,10 @@
'queues' => [
'accountability' => env('RABBITMQ_QUEUE_PC'),
'published_recourses' => env('RABBITMQ_QUEUE_PUBLISHED_RECOURSES'),
'opinions_published' => env('RABBITMQ_QUEUE_OPINIONS_PUBLISHED'),
],
'exchanges' => [
'plugins' => env('RABBITMQ_EXCHANGE_PLUGINS'),
],
'route_key_prop' => env('RABBITMQ_QUEUE_PC_ROUTE_KEY_PROP'),
'route_key_adm' => env('RABBITMQ_QUEUE_PC_ROUTE_KEY_ADM'),
Expand Down
2 changes: 1 addition & 1 deletion docker/php-fpm/99-xdebug.ini
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
zend_extension=xdebug.so
xdebug.mode=off
xdebug.mode=coverage
xdebug.start_with_request=trigger
xdebug.discover_client_host=1
xdebug.client_host=host.docker.internal
Expand Down
7 changes: 7 additions & 0 deletions docker/php-fpm/supervisord.conf
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@ autorestart=true
stderr_logfile=/dev/stderr
stdout_logfile=/dev/stdout

[program:published-opinions]
command=php artisan rabbitmq:consume-published-opinions-emails
autostart=true
autorestart=true
stderr_logfile=/dev/stderr
stdout_logfile=/dev/stdout

[program:accountability_queue]
process_name=%(program_name)s
command=php /var/www/html/artisan queue:work
Expand Down
40 changes: 40 additions & 0 deletions resources/views/emails/published-opinions.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
@include('emails/header')

<table role="presentation" class="main">
<tr>
<td>
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr>
<td>
<main class="wrapper">
<p><b>Prezado(a), espero que esteja bem.</b></p>
<p>
A plataforma {{ $appName ?? 'Mapa Cultural do Ceará' }} vem por meio deste informar que os pareceres referentes ao projeto inscrito na oportunidade
<strong>{{ $opportunity['name'] }}</strong>
com número de inscrição
<strong>{{ $registration['number'] }}</strong>
foram publicados.
<br>
Para visualizar, acesse o link a seguir da sua
<span class="apple-link">
<span>
<a href="{{ $registration['url'] }}"> página de inscrição</a>.
</span>
</span>
<code><pre>{{ $registration['url'] }}</pre></code>
</p>
<p>
Cordialmente,
</p>
<p>
{{ $opportunity['owner']['name'] ?? 'Secretaria da Cultura do Estado do Ceará' }}.
</p>
</main>
</td>
</tr>
</table>
</td>
</tr>
</table>

@include('emails/footer')
Loading