From 30cba364f3eb0bf07d1ea9f408029366e5a02a7e Mon Sep 17 00:00:00 2001
From: Junior-Shyko
Date: Thu, 27 Mar 2025 14:57:48 -0300
Subject: [PATCH 01/11] =?UTF-8?q?=F0=9F=94=A8=20#13=20-=20add=20supervisor?=
=?UTF-8?q?=20para=20varios=20comandos=20artisan?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
docker-compose.yml | 19 +------------------
docker/php-fpm/Dockerfile | 4 +++-
docker/php-fpm/supervisord.conf | 31 +++++++++++++++++++++++++++++++
docker/supervisord.conf | 29 -----------------------------
4 files changed, 35 insertions(+), 48 deletions(-)
create mode 100644 docker/php-fpm/supervisord.conf
delete mode 100644 docker/supervisord.conf
diff --git a/docker-compose.yml b/docker-compose.yml
index a9db9fb..999dcbe 100755
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -49,6 +49,7 @@ services:
build:
context: "./docker/php-fpm"
container_name: php_api
+ command: ["supervisord", "-c", "/etc/supervisord.conf"]
volumes:
- ${APP_CODE_PATH_HOST}:${APP_CODE_PATH_CONTAINER}${APP_CODE_CONTAINER_FLAG}
networks:
@@ -71,22 +72,6 @@ services:
networks:
- sail
- lab
-# rabbitmq:
-# image: rabbitmq:3-management
-# container_name: rabbitmq
-# hostname: rabbitmq
-# ports:
-# - "5672:5672"
-# - "15672:15672"
-# networks:
-# - lab
-# volumes:
-# - $PWD/storage/rabbitmq1:/var/lib/rabbitmq
-# environment:
-# - RABBITMQ_ERLANG_COOKIE=This_is_my_secret_phrase
-# - RABBITMQ_DEFAULT_USER=mqadmin
-# - RABBITMQ_DEFAULT_PASS=Admin123XX_
-# - CLUSTERED=true
networks:
sail:
driver: bridge
@@ -97,5 +82,3 @@ volumes:
driver: local
sail-redis:
driver: local
- # sail-meilisearch:
- # driver: local
diff --git a/docker/php-fpm/Dockerfile b/docker/php-fpm/Dockerfile
index e5037d7..6e7d082 100644
--- a/docker/php-fpm/Dockerfile
+++ b/docker/php-fpm/Dockerfile
@@ -27,7 +27,8 @@ RUN apt-get update && \
libreadline-dev \
libgmp-dev \
mariadb-client \
- unzip
+ unzip \
+ supervisor
# Install soap extention
RUN docker-php-ext-install soap
@@ -155,6 +156,7 @@ RUN usermod -u 1000 www-data
WORKDIR /var/www/html
COPY ./docker-entrypoint.sh /usr/local/bin/
+COPY ./supervisord.conf /etc/supervisord.conf
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
RUN ln -s /usr/local/bin/docker-entrypoint.sh /
ENTRYPOINT ["docker-entrypoint.sh"]
diff --git a/docker/php-fpm/supervisord.conf b/docker/php-fpm/supervisord.conf
new file mode 100644
index 0000000..4c6b060
--- /dev/null
+++ b/docker/php-fpm/supervisord.conf
@@ -0,0 +1,31 @@
+[supervisord]
+nodaemon=true
+### RODAR OS WORKS
+[program:diligence_consumer]
+command=php artisan diligence:consumer
+autostart=true
+autorestart=true
+stderr_logfile=/dev/stderr
+stdout_logfile=/dev/stdout
+
+[program:rabbitmq_consumer]
+command=php artisan rabbitmq:consume-published-recourse-emails
+autostart=true
+autorestart=true
+stderr_logfile=/dev/stderr
+stdout_logfile=/dev/stdout
+
+[supervisord]
+nodaemon=true
+user=root
+logfile=/var/log/supervisor/supervisord.log
+pidfile=/var/run/supervisord.pid
+
+# [program:php]
+# command=%(ENV_SUPERVISOR_PHP_COMMAND)s
+#user=%(ENV_SUPERVISOR_PHP_USER)s
+# environment=LARAVEL_SAIL="1"
+# stdout_logfile=/dev/stdout
+# stdout_logfile_maxbytes=0
+# stderr_logfile=/dev/stderr
+# stderr_logfile_maxbytes=0
diff --git a/docker/supervisord.conf b/docker/supervisord.conf
deleted file mode 100644
index 65cac38..0000000
--- a/docker/supervisord.conf
+++ /dev/null
@@ -1,29 +0,0 @@
-#[supervisord]
-#nodaemon=true
-#user=root
-#logfile=/var/log/supervisor/supervisord.log
-#pidfile=/var/run/supervisord.pid
-
-#[program:php]
-# command=/usr/bin/php -d variables_order=EGPCS /var/www/html/artisan serve --host=0.0.0.0
-#command=%(ENV_SUPERVISOR_PHP_COMMAND)s
-#; user=sail
-#environment=LARAVEL_SAIL="1"
-#stdout_logfile=/dev/stdout
-#stdout_logfile_maxbytes=0
-#stderr_logfile=/dev/stderr
-#stderr_logfile_maxbytes=0
-[supervisord]
-nodaemon=true
-user=root
-logfile=/var/log/supervisor/supervisord.log
-pidfile=/var/run/supervisord.pid
-
-[program:php]
-command=%(ENV_SUPERVISOR_PHP_COMMAND)s
-#user=%(ENV_SUPERVISOR_PHP_USER)s
-environment=LARAVEL_SAIL="1"
-stdout_logfile=/dev/stdout
-stdout_logfile_maxbytes=0
-stderr_logfile=/dev/stderr
-stderr_logfile_maxbytes=0
From 08c82deb94b7cecba17634c0282b49873344e814 Mon Sep 17 00:00:00 2001
From: Junior-Shyko
Date: Mon, 31 Mar 2025 14:05:08 -0300
Subject: [PATCH 02/11] =?UTF-8?q?=F0=9F=93=9D=20Add=20info=20no=20readme?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.gitignore | 1 +
README.md | 11 +++++++++++
docker/logs/nginx/error.log | 2 ++
3 files changed, 14 insertions(+)
diff --git a/.gitignore b/.gitignore
index 622b65a..5fdd7b2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,3 +21,4 @@ docker-data
data
storage
/docker/logs/
+docker/logs/nginx/error.log
\ No newline at end of file
diff --git a/README.md b/README.md
index 1d88531..e8b5002 100644
--- a/README.md
+++ b/README.md
@@ -52,3 +52,14 @@ Instruções [aqui](https://github.com/secultce/api-email/blob/develop/docs/TASK
### JWT Auth
É usado o pacote jwt-auth (https://jwt-auth.readthedocs.io/en/develop/) para criar tokens de acesso que são enviados nas requisições, para garantir que pessoas não autorizadas acessem os dados retornados nos endpoints usados na api.
+
+### Workers
+
+Para cada novo componente que precise trabalhar com as tarefas de filas por exemplo, deve ser adicionar o comando no arquivo *supervisord.conf* , que se encontra no caminho ***docker/php-fpm/*** e escrever algo como:
+
+ [program:name_command]
+ command=php artisan command:command
+ autostart=true
+ autorestart=true
+ stderr_logfile=/dev/stderr
+ stdout_logfile=/dev/stdout
\ No newline at end of file
diff --git a/docker/logs/nginx/error.log b/docker/logs/nginx/error.log
index a99eb36..887ffa4 100644
--- a/docker/logs/nginx/error.log
+++ b/docker/logs/nginx/error.log
@@ -1,3 +1,5 @@
2024/03/20 00:52:56 [emerg] 12#12: host not found in upstream "php-fpm:9000" in /etc/nginx/conf.d/upstream.conf:1
2024/03/20 00:58:24 [emerg] 12#12: host not found in upstream "php-fpm:9000" in /etc/nginx/conf.d/upstream.conf:1
2024/03/20 01:00:32 [emerg] 12#12: host not found in upstream "php-fpm:9000" in /etc/nginx/conf.d/upstream.conf:1
+2025/03/28 00:00:00 [notice] 65#65: signal process started
+2025/03/28 00:00:00 [notice] 66#66: signal process started
From c4d56033dd70f397b122036bac152fa2d96540a4 Mon Sep 17 00:00:00 2001
From: Ronny John
Date: Mon, 31 Mar 2025 14:34:00 -0300
Subject: [PATCH 03/11] chore: Update PHP Version
---
.editorconfig | 3 -
.env.testing | 8 +-
.gitignore | 4 +-
composer.json | 8 +-
composer.lock | 219 ++++++++++++++++++++++++++++++++++-
docker-compose.yml | 33 +++---
docker/php-fpm/99-xdebug.ini | 9 ++
docker/php-fpm/Dockerfile | 4 +-
phpunit.xml | 1 -
9 files changed, 258 insertions(+), 31 deletions(-)
create mode 100644 docker/php-fpm/99-xdebug.ini
diff --git a/.editorconfig b/.editorconfig
index 8f0de65..dd9a2b5 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -13,6 +13,3 @@ trim_trailing_whitespace = false
[*.{yml,yaml}]
indent_size = 2
-
-[docker-compose.yml]
-indent_size = 4
diff --git a/.env.testing b/.env.testing
index faafb24..8601ad6 100644
--- a/.env.testing
+++ b/.env.testing
@@ -1,5 +1,5 @@
APP_NAME=Laravel
-APP_ENV=local
+APP_ENV=testing
APP_KEY=base64:Bq7kBLzjHsoonNahT0xa08HqG4jQD62dw1LRXMCNdCE=
APP_DEBUG=true
APP_TIMEZONE=UTC
@@ -20,9 +20,9 @@ LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug
DB_CONNECTION=pgsql
-DB_HOST=172.19.18.161
+DB_HOST=172.19.18.213
DB_PORT=5433
-DB_DATABASE=api_email
+DB_DATABASE=api_email_test
DB_USERNAME=postgres
DB_PASSWORD=12345678
@@ -83,7 +83,7 @@ NGINX_PHP_UPSTREAM_CONTAINER=php-fpm
NGINX_PHP_UPSTREAM_PORT=9000
NGINX_SSL_PATH=./docker/nginx/ssl/
### PARA AS FILAS
-MAPA_URL=http://localhost:8088/
+MAPA_URL=http://172.19.18.213:8088/
#### RABBITMW ####
RABBITMQ_DEFAULT_HOST=rabbitmq
diff --git a/.gitignore b/.gitignore
index 5fdd7b2..2cac750 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,4 +21,6 @@ docker-data
data
storage
/docker/logs/
-docker/logs/nginx/error.log
\ No newline at end of file
+docker/logs/nginx/error.log
+
+xdebug.log
diff --git a/composer.json b/composer.json
index 5b730fb..edf587f 100644
--- a/composer.json
+++ b/composer.json
@@ -5,19 +5,21 @@
"keywords": ["laravel", "framework"],
"license": "MIT",
"require": {
- "php": "^8.2",
+ "php": "^8.4",
"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"
+ "tymon/jwt-auth": "^2.1",
+ "ext-pdo": "*"
},
"require-dev": {
+ "brianium/paratest": "^7.8",
"fakerphp/faker": "^1.23",
"laravel/breeze": "^2.0",
- "laravel/pint": "^1.13",
+ "laravel/pint": "^1.21",
"laravel/sail": "^1.26",
"lucascudo/laravel-pt-br-localization": "^3.0",
"mockery/mockery": "^1.6",
diff --git a/composer.lock b/composer.lock
index 4a2a16f..e7eacb8 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "cdabfb1ddb3c492f8353a47e1b654f65",
+ "content-hash": "c517e5610ee4326849a3e0b32f2eadbe",
"packages": [
{
"name": "brick/math",
@@ -6421,6 +6421,99 @@
}
],
"packages-dev": [
+ {
+ "name": "brianium/paratest",
+ "version": "v7.8.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/paratestphp/paratest.git",
+ "reference": "a585c346ddf1bec22e51e20b5387607905604a71"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/paratestphp/paratest/zipball/a585c346ddf1bec22e51e20b5387607905604a71",
+ "reference": "a585c346ddf1bec22e51e20b5387607905604a71",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-pcre": "*",
+ "ext-reflection": "*",
+ "ext-simplexml": "*",
+ "fidry/cpu-core-counter": "^1.2.0",
+ "jean85/pretty-package-versions": "^2.1.0",
+ "php": "~8.2.0 || ~8.3.0 || ~8.4.0",
+ "phpunit/php-code-coverage": "^11.0.9 || ^12.0.4",
+ "phpunit/php-file-iterator": "^5.1.0 || ^6",
+ "phpunit/php-timer": "^7.0.1 || ^8",
+ "phpunit/phpunit": "^11.5.11 || ^12.0.6",
+ "sebastian/environment": "^7.2.0 || ^8",
+ "symfony/console": "^6.4.17 || ^7.2.1",
+ "symfony/process": "^6.4.19 || ^7.2.4"
+ },
+ "require-dev": {
+ "doctrine/coding-standard": "^12.0.0",
+ "ext-pcov": "*",
+ "ext-posix": "*",
+ "phpstan/phpstan": "^2.1.6",
+ "phpstan/phpstan-deprecation-rules": "^2.0.1",
+ "phpstan/phpstan-phpunit": "^2.0.4",
+ "phpstan/phpstan-strict-rules": "^2.0.3",
+ "squizlabs/php_codesniffer": "^3.11.3",
+ "symfony/filesystem": "^6.4.13 || ^7.2.0"
+ },
+ "bin": [
+ "bin/paratest",
+ "bin/paratest_for_phpstorm"
+ ],
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "ParaTest\\": [
+ "src/"
+ ]
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Brian Scaturro",
+ "email": "scaturrob@gmail.com",
+ "role": "Developer"
+ },
+ {
+ "name": "Filippo Tessarotto",
+ "email": "zoeslam@gmail.com",
+ "role": "Developer"
+ }
+ ],
+ "description": "Parallel testing for PHP",
+ "homepage": "https://github.com/paratestphp/paratest",
+ "keywords": [
+ "concurrent",
+ "parallel",
+ "phpunit",
+ "testing"
+ ],
+ "support": {
+ "issues": "https://github.com/paratestphp/paratest/issues",
+ "source": "https://github.com/paratestphp/paratest/tree/v7.8.3"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sponsors/Slamdunk",
+ "type": "github"
+ },
+ {
+ "url": "https://paypal.me/filippotessarotto",
+ "type": "paypal"
+ }
+ ],
+ "time": "2025-03-05T08:29:11+00:00"
+ },
{
"name": "fakerphp/faker",
"version": "v1.24.1",
@@ -6484,6 +6577,67 @@
},
"time": "2024-11-21T13:46:39+00:00"
},
+ {
+ "name": "fidry/cpu-core-counter",
+ "version": "1.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/theofidry/cpu-core-counter.git",
+ "reference": "8520451a140d3f46ac33042715115e290cf5785f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/8520451a140d3f46ac33042715115e290cf5785f",
+ "reference": "8520451a140d3f46ac33042715115e290cf5785f",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2 || ^8.0"
+ },
+ "require-dev": {
+ "fidry/makefile": "^0.2.0",
+ "fidry/php-cs-fixer-config": "^1.1.2",
+ "phpstan/extension-installer": "^1.2.0",
+ "phpstan/phpstan": "^1.9.2",
+ "phpstan/phpstan-deprecation-rules": "^1.0.0",
+ "phpstan/phpstan-phpunit": "^1.2.2",
+ "phpstan/phpstan-strict-rules": "^1.4.4",
+ "phpunit/phpunit": "^8.5.31 || ^9.5.26",
+ "webmozarts/strict-phpunit": "^7.5"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Fidry\\CpuCoreCounter\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Théo FIDRY",
+ "email": "theo.fidry@gmail.com"
+ }
+ ],
+ "description": "Tiny utility to get the number of CPU cores.",
+ "keywords": [
+ "CPU",
+ "core"
+ ],
+ "support": {
+ "issues": "https://github.com/theofidry/cpu-core-counter/issues",
+ "source": "https://github.com/theofidry/cpu-core-counter/tree/1.2.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/theofidry",
+ "type": "github"
+ }
+ ],
+ "time": "2024-08-06T10:04:20+00:00"
+ },
{
"name": "filp/whoops",
"version": "2.18.0",
@@ -6606,6 +6760,66 @@
},
"time": "2020-07-09T08:09:16+00:00"
},
+ {
+ "name": "jean85/pretty-package-versions",
+ "version": "2.1.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Jean85/pretty-package-versions.git",
+ "reference": "4d7aa5dab42e2a76d99559706022885de0e18e1a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/4d7aa5dab42e2a76d99559706022885de0e18e1a",
+ "reference": "4d7aa5dab42e2a76d99559706022885de0e18e1a",
+ "shasum": ""
+ },
+ "require": {
+ "composer-runtime-api": "^2.1.0",
+ "php": "^7.4|^8.0"
+ },
+ "require-dev": {
+ "friendsofphp/php-cs-fixer": "^3.2",
+ "jean85/composer-provided-replaced-stub-package": "^1.0",
+ "phpstan/phpstan": "^2.0",
+ "phpunit/phpunit": "^7.5|^8.5|^9.6",
+ "rector/rector": "^2.0",
+ "vimeo/psalm": "^4.3 || ^5.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Jean85\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Alessandro Lai",
+ "email": "alessandro.lai85@gmail.com"
+ }
+ ],
+ "description": "A library to get pretty versions strings of installed dependencies",
+ "keywords": [
+ "composer",
+ "package",
+ "release",
+ "versions"
+ ],
+ "support": {
+ "issues": "https://github.com/Jean85/pretty-package-versions/issues",
+ "source": "https://github.com/Jean85/pretty-package-versions/tree/2.1.1"
+ },
+ "time": "2025-03-19T14:43:43+00:00"
+ },
{
"name": "laravel/breeze",
"version": "v2.3.6",
@@ -9125,7 +9339,8 @@
"prefer-stable": true,
"prefer-lowest": false,
"platform": {
- "php": "^8.2"
+ "php": "^8.4",
+ "ext-pdo": "*"
},
"platform-dev": {},
"plugin-api-version": "2.6.0"
diff --git a/docker-compose.yml b/docker-compose.yml
index 999dcbe..13a87bc 100755
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,16 +1,19 @@
-version: '3'
services:
- db:
- image: postgres:15
+ db-email:
+ image: postgres:16
+ restart: always
ports:
- "5433:5432"
environment:
- - DEBUG=true
- - POSTGRES_DB=api_email
- - POSTGRES_USER=postgres
- - POSTGRES_PASSWORD=12345678
+ - POSTGRES_DB=${DB_DATABASE}
+ - POSTGRES_USER=${DB_USERNAME}
+ - POSTGRES_PASSWORD=${DB_PASSWORD}
+ - POSTGRES_HOST_AUTH_METHOD=trust
volumes:
- - ./data:/var/lib/postgresql
+ - sail-db:/var/lib/postgresql/data
+ networks:
+ - sail
+
redis:
image: 'redis:alpine'
ports:
@@ -21,10 +24,7 @@ services:
- sail
- lab
healthcheck:
- test:
- - CMD
- - redis-cli
- - ping
+ test: [ "CMD", "redis-cli", "ping" ]
retries: 3
timeout: 5s
@@ -39,12 +39,12 @@ services:
- ${NGINX_HOST_LOG_PATH}:/var/log/nginx
- ${NGINX_SITES_PATH}:/etc/nginx/sites-available
ports:
- # port mappings, host to docker
- "${NGINX_HOST_HTTPS_PORT}:443"
- "${NGINX_HOST_HTTP_PORT}:80"
networks:
- sail
- lab
+
fpm-email:
build:
context: "./docker/php-fpm"
@@ -52,11 +52,13 @@ services:
command: ["supervisord", "-c", "/etc/supervisord.conf"]
volumes:
- ${APP_CODE_PATH_HOST}:${APP_CODE_PATH_CONTAINER}${APP_CODE_CONTAINER_FLAG}
+ - ./docker/php-fpm/99-xdebug.ini:/usr/local/etc/php/conf.d/99-xdebug.ini
networks:
- sail
- lab
expose:
- "9000"
+
mailpit:
image: 'axllent/mailpit:latest'
ports:
@@ -65,6 +67,7 @@ services:
networks:
- sail
- lab
+
memcached:
image: 'memcached:alpine'
ports:
@@ -72,13 +75,15 @@ services:
networks:
- sail
- lab
+
networks:
sail:
driver: bridge
lab:
external: true
+
volumes:
- sail-mysql:
+ sail-db:
driver: local
sail-redis:
driver: local
diff --git a/docker/php-fpm/99-xdebug.ini b/docker/php-fpm/99-xdebug.ini
new file mode 100644
index 0000000..c07042c
--- /dev/null
+++ b/docker/php-fpm/99-xdebug.ini
@@ -0,0 +1,9 @@
+zend_extension=xdebug.so
+xdebug.mode=off
+xdebug.start_with_request=trigger
+xdebug.discover_client_host=1
+xdebug.client_host=host.docker.internal
+xdebug.output_dir=/var/www/html
+xdebug.log=/var/www/html/xdebug.log
+xdebug.log_level=10
+xdebug.show_local_vars=1
diff --git a/docker/php-fpm/Dockerfile b/docker/php-fpm/Dockerfile
index 6e7d082..bae1e4e 100644
--- a/docker/php-fpm/Dockerfile
+++ b/docker/php-fpm/Dockerfile
@@ -1,8 +1,6 @@
# Copied from cyberduck/php-fpm-laravel
#https://github.com/Cyber-Duck/php-fpm-laravel/blob/8.1/Dockerfile
-FROM php:8.3-fpm
-
-MAINTAINER support@cyber-duck.co.uk
+FROM php:8.4-fpm
ENV COMPOSER_MEMORY_LIMIT='-1'
ARG NODE_VERSION=18
diff --git a/phpunit.xml b/phpunit.xml
index 06c7ff8..5c3671d 100644
--- a/phpunit.xml
+++ b/phpunit.xml
@@ -22,7 +22,6 @@
-
From 4f26ccc7bc5037cfe4dbc8c1d9c136e33db89d6d Mon Sep 17 00:00:00 2001
From: Junior-Shyko
Date: Wed, 9 Apr 2025 13:46:55 -0300
Subject: [PATCH 04/11] =?UTF-8?q?=F0=9F=9A=80=20#13=20-=20Adicionado=20wor?=
=?UTF-8?q?kers=20no=20supervisord?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
docker/prod/nginx/.gitignore | 4 ++
docker/prod/nginx/Dockerfile | 34 ++++++++++++++
docker/prod/nginx/conf.d/app.conf | 17 +++++++
docker/prod/nginx/logrotate/nginx | 14 ++++++
docker/prod/nginx/nginx.conf | 34 ++++++++++++++
docker/prod/nginx/sites/laravel.conf | 57 ++++++++++++++++++++++++
docker/prod/nginx/ssl/generate-keys.sh | 4 ++
docker/prod/nginx/startup.sh | 23 ++++++++++
docker/prod/php-fpm/Dockerfile | 46 +++++++++++++++++++
docker/prod/php-fpm/docker-entrypoint.sh | 43 ++++++++++++++++++
docker/prod/php-fpm/laravel.ini | 13 ++++++
docker/prod/php-fpm/published.sh | 7 +++
docker/prod/php-fpm/supervisord.conf | 39 ++++++++++++++++
docker/prod/php-fpm/works.sh | 7 +++
14 files changed, 342 insertions(+)
create mode 100644 docker/prod/nginx/.gitignore
create mode 100644 docker/prod/nginx/Dockerfile
create mode 100644 docker/prod/nginx/conf.d/app.conf
create mode 100644 docker/prod/nginx/logrotate/nginx
create mode 100644 docker/prod/nginx/nginx.conf
create mode 100644 docker/prod/nginx/sites/laravel.conf
create mode 100644 docker/prod/nginx/ssl/generate-keys.sh
create mode 100644 docker/prod/nginx/startup.sh
create mode 100644 docker/prod/php-fpm/Dockerfile
create mode 100644 docker/prod/php-fpm/docker-entrypoint.sh
create mode 100644 docker/prod/php-fpm/laravel.ini
create mode 100755 docker/prod/php-fpm/published.sh
create mode 100644 docker/prod/php-fpm/supervisord.conf
create mode 100755 docker/prod/php-fpm/works.sh
diff --git a/docker/prod/nginx/.gitignore b/docker/prod/nginx/.gitignore
new file mode 100644
index 0000000..003cd8e
--- /dev/null
+++ b/docker/prod/nginx/.gitignore
@@ -0,0 +1,4 @@
+*.crt
+*.csr
+*.key
+*.pem
\ No newline at end of file
diff --git a/docker/prod/nginx/Dockerfile b/docker/prod/nginx/Dockerfile
new file mode 100644
index 0000000..b6e1a60
--- /dev/null
+++ b/docker/prod/nginx/Dockerfile
@@ -0,0 +1,34 @@
+FROM nginx:alpine
+
+COPY nginx.conf /etc/nginx/
+
+RUN apk update \
+ && apk upgrade \
+ && apk --update add logrotate \
+ && apk add --no-cache openssl \
+ && apk add --no-cache bash
+
+RUN apk add --no-cache curl
+
+RUN set -x ; \
+ addgroup -g 82 -S www-data ; \
+ adduser -u 82 -D -S -G www-data www-data && exit 0 ; exit 1
+
+ARG PHP_UPSTREAM_CONTAINER=fpm-email
+ARG PHP_UPSTREAM_PORT=9000
+
+# Create 'messages' file used from 'logrotate'
+RUN touch /var/log/messages
+
+# Copy 'logrotate' config file
+COPY logrotate/nginx /etc/logrotate.d/
+
+# Set upstream conf and remove the default conf
+RUN echo "upstream php-upstream { server ${PHP_UPSTREAM_CONTAINER}:${PHP_UPSTREAM_PORT}; }" > /etc/nginx/conf.d/upstream.conf \
+ && rm /etc/nginx/conf.d/default.conf
+
+ADD ./startup.sh /opt/startup.sh
+RUN sed -i 's/\r//g' /opt/startup.sh
+CMD ["/bin/bash", "/opt/startup.sh"]
+
+EXPOSE 80 81 443
diff --git a/docker/prod/nginx/conf.d/app.conf b/docker/prod/nginx/conf.d/app.conf
new file mode 100644
index 0000000..cdaf0ad
--- /dev/null
+++ b/docker/prod/nginx/conf.d/app.conf
@@ -0,0 +1,17 @@
+server {
+ listen 80;
+ index index.php;
+ server_name localhost;
+ root /var/www/public;
+ location / {
+ try_files $uri $uri/ /index.php?$query_string;
+ }
+ location ~ \.php$ {
+ fastcgi_split_path_info ^(.+\.php)(/.+)$;
+ fastcgi_pass app:9000; # Aponta para o serviço `app` no docker-compose
+ fastcgi_index index.php;
+ include fastcgi_params;
+ fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
+ fastcgi_param PATH_INFO $fastcgi_path_info;
+ }
+}
\ No newline at end of file
diff --git a/docker/prod/nginx/logrotate/nginx b/docker/prod/nginx/logrotate/nginx
new file mode 100644
index 0000000..8c89a83
--- /dev/null
+++ b/docker/prod/nginx/logrotate/nginx
@@ -0,0 +1,14 @@
+/var/log/nginx/*.log {
+ daily
+ missingok
+ rotate 32
+ compress
+ delaycompress
+ nodateext
+ notifempty
+ create 644 www-data root
+ sharedscripts
+ postrotate
+ [ -f /var/run/nginx.pid ] && kill -USR1 `cat /var/run/nginx.pid`
+ endscript
+}
diff --git a/docker/prod/nginx/nginx.conf b/docker/prod/nginx/nginx.conf
new file mode 100644
index 0000000..56ededb
--- /dev/null
+++ b/docker/prod/nginx/nginx.conf
@@ -0,0 +1,34 @@
+user www-data;
+worker_processes 4;
+pid /run/nginx.pid;
+daemon off;
+
+events {
+ worker_connections 2048;
+ multi_accept on;
+ use epoll;
+}
+
+http {
+ server_tokens off;
+ sendfile on;
+ tcp_nopush on;
+ tcp_nodelay on;
+ keepalive_timeout 15;
+ types_hash_max_size 2048;
+ client_max_body_size 20M;
+ include /etc/nginx/mime.types;
+ default_type application/octet-stream;
+ access_log /dev/stdout;
+ error_log /dev/stderr;
+ gzip on;
+ gzip_disable "msie6";
+
+ ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
+ ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
+
+ include /etc/nginx/conf.d/*.conf;
+ include /etc/nginx/sites-available/*.conf;
+ open_file_cache off; # Disabled for issue 619
+ charset UTF-8;
+}
diff --git a/docker/prod/nginx/sites/laravel.conf b/docker/prod/nginx/sites/laravel.conf
new file mode 100644
index 0000000..5e7b01c
--- /dev/null
+++ b/docker/prod/nginx/sites/laravel.conf
@@ -0,0 +1,57 @@
+
+server {
+
+ listen 80;
+ listen [::]:80;
+
+ add_header X-Frame-Options "SAMEORIGIN";
+ add_header X-Content-Type-Options "nosniff";
+ charset utf-8;
+
+ # For https
+ listen 443 ssl;
+ listen [::]:443 ssl ipv6only=on;
+ ssl_certificate /etc/nginx/ssl/default.crt;
+ ssl_certificate_key /etc/nginx/ssl/default.key;
+
+ server_name laravel.dev.local;
+ root /var/www/html/public;
+ index index.php index.html index.htm;
+
+ location / {
+ try_files $uri $uri/ /index.php$is_args$args;
+ }
+
+ location ~ \.php$ {
+ try_files $uri /index.php =404;
+ fastcgi_pass php-upstream;
+ fastcgi_index index.php;
+ fastcgi_buffers 16 16k;
+ fastcgi_buffer_size 32k;
+ fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
+ #fixes timeouts
+ fastcgi_read_timeout 600;
+ include fastcgi_params;
+ }
+
+ location ~ /\.ht {
+ deny all;
+ }
+
+ location /.well-known/acme-challenge/ {
+ root /var/www/letsencrypt/;
+ log_not_found off;
+ }
+ location = /favicon.ico {
+ access_log off;
+ log_not_found off;
+ }
+ location = /robots.txt {
+ access_log off;
+ log_not_found off;
+ }
+
+
+ error_log /var/log/nginx/laravel_error.log;
+ access_log /var/log/nginx/laravel_access.log;
+}
diff --git a/docker/prod/nginx/ssl/generate-keys.sh b/docker/prod/nginx/ssl/generate-keys.sh
new file mode 100644
index 0000000..8f315d5
--- /dev/null
+++ b/docker/prod/nginx/ssl/generate-keys.sh
@@ -0,0 +1,4 @@
+openssl genrsa -out "./default.key" 2048
+chmod 644 ./default.key
+openssl req -new -key "./default.key" -out "./default.csr" -subj "/CN=default/O=default/C=UK"
+openssl x509 -req -days 365 -in "./default.csr" -signkey "./default.key" -out "./default.crt"
diff --git a/docker/prod/nginx/startup.sh b/docker/prod/nginx/startup.sh
new file mode 100644
index 0000000..b5bbe4f
--- /dev/null
+++ b/docker/prod/nginx/startup.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+
+if [ ! -f /etc/nginx/ssl/default.crt ]; then
+ openssl genrsa -out "/etc/nginx/ssl/default.key" 2048
+ openssl req -new -key "/etc/nginx/ssl/default.key" -out "/etc/nginx/ssl/default.csr" -subj "/CN=default/O=default/C=UK"
+ openssl x509 -req -days 365 -in "/etc/nginx/ssl/default.csr" -signkey "/etc/nginx/ssl/default.key" -out "/etc/nginx/ssl/default.crt"
+ chmod 644 /etc/nginx/ssl/default.key
+fi
+
+
+# cron job to restart nginx every 6 hour
+(crontab -l ; echo "0 0 */4 * * nginx -s reload") | crontab -
+
+# Start crond in background
+crond -l 2 -b
+
+
+#* * * * * root nginx -s reload >> /var/log/cron.log
+
+# Start nginx in foreground
+echo "NGINX started, daemon will restart every 6 hours now.";
+nginx
+
diff --git a/docker/prod/php-fpm/Dockerfile b/docker/prod/php-fpm/Dockerfile
new file mode 100644
index 0000000..1ea2231
--- /dev/null
+++ b/docker/prod/php-fpm/Dockerfile
@@ -0,0 +1,46 @@
+FROM php:8.4-fpm
+RUN apt-get update && \
+ apt-get install -y --force-yes --no-install-recommends \
+ libmemcached-dev \
+ libzip-dev \
+ libz-dev \
+ libpq-dev \
+ libjpeg-dev \
+ libpng-dev \
+ libfreetype6-dev \
+ libssl-dev \
+ openssh-server \
+ libmagickwand-dev \
+ git \
+ cron \
+ nano \
+ libxml2-dev \
+ libreadline-dev \
+ libgmp-dev \
+ mariadb-client \
+ unzip \
+ supervisor
+
+RUN docker-php-ext-install soap exif pcntl zip pdo_mysql pdo_pgsql bcmath intl gmp sockets
+
+RUN pecl install redis && docker-php-ext-enable redis
+RUN pecl install memcached && docker-php-ext-enable memcached
+
+RUN docker-php-ext-install gd && \
+ docker-php-ext-configure gd --with-freetype --with-jpeg && \
+ docker-php-ext-install gd
+
+COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
+WORKDIR /var/www
+COPY . /var/www
+COPY ./docker/prod/php-fpm/supervisord.conf /etc/supervisord.conf
+COPY ./docker/prod/php-fpm/published.sh /etc/published.sh
+COPY ./docker/prod/php-fpm/works.sh /etc/works.sh
+COPY ./docker/prod/php-fpm/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
+
+RUN composer install --no-dev --optimize-autoloader
+RUN chown -R www-data:www-data /var/www && chmod -R 755 /var/www/storage
+RUN chmod +x /usr/local/bin/docker-entrypoint.sh
+
+EXPOSE 9000
+ENTRYPOINT ["docker-entrypoint.sh"]
\ No newline at end of file
diff --git a/docker/prod/php-fpm/docker-entrypoint.sh b/docker/prod/php-fpm/docker-entrypoint.sh
new file mode 100644
index 0000000..97da946
--- /dev/null
+++ b/docker/prod/php-fpm/docker-entrypoint.sh
@@ -0,0 +1,43 @@
+#!/bin/bash
+
+# Destination of env file inside container
+ENV_FILE="/var/www/.env"
+
+for VAR in XDEBUG PHP_IDE_CONFIG REMOTE_HOST
+do
+ if [ -z "${!VAR}" ] && [ -f "${ENV_FILE}" ]; then
+ VALUE=$(grep $VAR $ENV_FILE | cut -d '=' -f 2-)
+ if [ ! -z "${VALUE}" ]; then
+ sed -i "/$VAR/d" ~/.bashrc
+ echo "export $VAR=$VALUE" >> ~/.bashrc;
+ fi
+ fi
+done
+
+if [ -z "${REMOTE_HOST}" ]; then
+ REMOTE_HOST="host.docker.internal"
+ sed -i "/REMOTE_HOST/d" ~/.bashrc
+ echo "export REMOTE_HOST=\"$REMOTE_HOST\"" >> ~/.bashrc;
+fi
+
+. ~/.bashrc
+
+service cron start
+
+if [ "true" == "$XDEBUG" ] && [ ! -f /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini ]; then
+ sed -i '/PHP_IDE_CONFIG/d' /etc/cron.d/laravel-scheduler
+ if [ ! -z "${PHP_IDE_CONFIG}" ]; then
+ echo -e "PHP_IDE_CONFIG=\"$PHP_IDE_CONFIG\"\n$(cat /etc/cron.d/laravel-scheduler)" > /etc/cron.d/laravel-scheduler
+ fi
+ docker-php-ext-enable xdebug && \
+ echo "xdebug.remote_enable=1" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini; \
+ echo "xdebug.remote_autostart=1" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini; \
+ echo "xdebug.remote_connect_back=0" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini; \
+ echo "xdebug.remote_host=$REMOTE_HOST" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini;
+elif [ -f /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini ]; then
+ sed -i '/PHP_IDE_CONFIG/d' /etc/cron.d/laravel-scheduler
+ rm -rf /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
+fi
+
+echo "Starting supervisord with command: $@"
+exec "$@"
\ No newline at end of file
diff --git a/docker/prod/php-fpm/laravel.ini b/docker/prod/php-fpm/laravel.ini
new file mode 100644
index 0000000..486a2ca
--- /dev/null
+++ b/docker/prod/php-fpm/laravel.ini
@@ -0,0 +1,13 @@
+date.timezone=UTC
+display_errors=Off
+log_errors=On
+
+; Maximum amount of memory a script may consume (128MB)
+; http://php.net/memory-limit
+memory_limit = 128M
+; Maximum allowed size for uploaded files.
+; http://php.net/upload-max-filesize
+upload_max_filesize = 20M
+; Sets max size of post data allowed.
+; http://php.net/post-max-size
+post_max_size = 20M
diff --git a/docker/prod/php-fpm/published.sh b/docker/prod/php-fpm/published.sh
new file mode 100755
index 0000000..f14c4df
--- /dev/null
+++ b/docker/prod/php-fpm/published.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+while true
+do
+ php artisan rabbitmq:consume-published-recourse-emails
+ echo "Worker da publicação caiu. Reiniciando em 60s..."
+ sleep 60
+done
diff --git a/docker/prod/php-fpm/supervisord.conf b/docker/prod/php-fpm/supervisord.conf
new file mode 100644
index 0000000..aedcdce
--- /dev/null
+++ b/docker/prod/php-fpm/supervisord.conf
@@ -0,0 +1,39 @@
+[supervisord]
+nodaemon=true
+user=root
+logfile=/var/log/supervisor/supervisord.log
+pidfile=/var/run/supervisord.pid
+logfile_maxbytes=0 #
+
+[program:php-fpm]
+command=/usr/local/sbin/php-fpm --nodaemonize
+autostart=true
+autorestart=true
+stderr_logfile=/var/log/php-fpm.err.log
+stdout_logfile=/var/log/php-fpm.out.log
+priority=100
+
+### RODAR OS WORKS
+[program:rabbitmq_published]
+command=/bin/bash /etc/published.sh
+autostart=true
+autorestart=true
+stderr_logfile=/var/log/rabbitmq_published.err.log
+stdout_logfile=/var/log/rabbitmq_published.out.log
+user=www-data
+numprocs=1
+priority=200
+logfile_maxbytes=50MB ; Tamanho máximo do log antes de rotacionar (opcional)
+logfile_backups=5
+
+[program:rabbitmq_pc]
+command=/bin/bash /etc/works.sh
+autostart=true
+autorestart=true
+stderr_logfile=/var/log/rabbitmq_consumer.err.log
+stdout_logfile=/var/log/rabbitmq_consumer.out.log
+user=www-data
+numprocs=1
+priority=200
+logfile_maxbytes=50MB ; Tamanho máximo do log antes de rotacionar (opcional)
+logfile_backups=5
\ No newline at end of file
diff --git a/docker/prod/php-fpm/works.sh b/docker/prod/php-fpm/works.sh
new file mode 100755
index 0000000..1455b26
--- /dev/null
+++ b/docker/prod/php-fpm/works.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+while true
+do
+ php artisan diligence:consumer
+ echo "Worker da PC caiu. Reiniciando em 60s..."
+ sleep 60
+done
From 7b254b16963f6d896d4660affc1c6bcd8e8e1a68 Mon Sep 17 00:00:00 2001
From: Junior-Shyko
Date: Wed, 9 Apr 2025 14:34:00 -0300
Subject: [PATCH 05/11] =?UTF-8?q?=F0=9F=93=9D=20#13=20-=20Add=20doc=20de?=
=?UTF-8?q?=20como=20buildar=20a=20imagem=20manualmente?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
docker/prod/docs/README.MD | 12 ++++++++++++
1 file changed, 12 insertions(+)
create mode 100644 docker/prod/docs/README.MD
diff --git a/docker/prod/docs/README.MD b/docker/prod/docs/README.MD
new file mode 100644
index 0000000..2740b50
--- /dev/null
+++ b/docker/prod/docs/README.MD
@@ -0,0 +1,12 @@
+
+### ✨ CRIAR IMAGEM MANUALMENTE
+
+✏️ Deve está na raiz do projeto e rodar o seguinte comando:
+
+ - `docker build --no-cache -t secultceara/api-email:latest -f docker/prod/php-fpm/Dockerfile .`
+
+✏️ Para enviar a imagem criada manualemente para o Docker Hub deve realizar os passos:
+
+ 1. Criar login da conta da secultceara com: `docker login -u {username}`
+ 2. Depois digitar a senha e após realizar o login com sucesso;
+ 3. Rodar o comando: `docker push docker.io/secultceara/api-email:latest`
\ No newline at end of file
From 4948633748d4d4bbc7b68ef8bf11ddb2d00f6a29 Mon Sep 17 00:00:00 2001
From: Ronny John
Date: Fri, 11 Apr 2025 11:51:05 -0300
Subject: [PATCH 06/11] chore: Add tests and code style checks
---
.env.testing | 11 +-
.gitignore | 1 +
.../ConsumePublishedRecourseEmails.php | 48 ++-
app/Console/Commands/ConsumerCommand.php | 63 ++--
app/Http/Controllers/UserController.php | 58 +---
app/Jobs/NotificationAccountability.php | 12 +-
app/Mail/AnswerNotification.php | 4 +-
app/Mail/DeadlineForAccountability.php | 20 +-
app/Mail/EmailRegistrationOpp.php | 4 +-
app/Mail/PublishedRecourse.php | 1 -
app/Mail/SendRegistration.php | 1 -
app/Models/User.php | 1 +
bootstrap/app.php | 17 +-
composer.json | 3 +-
composer.lock | 179 +++++------
config/app.php | 12 +
database/seeders/DatabaseSeeder.php | 2 -
lang/pt_BR/validation.php | 300 +++++++++---------
phpunit.xml | 5 +
pint.json | 3 +
.../deadline-for-accountability.blade.php | 2 +-
routes/api.php | 7 +-
routes/auth.php | 28 +-
routes/console.php | 6 +-
routes/web.php | 13 +-
tests/Feature/PC/EmailTest.php | 20 +-
tests/TestCase.php | 5 +-
.../ConsumePublishedRecourseEmailsTest.php | 128 ++++++++
.../Console/Commands/ConsumerCommandTest.php | 111 +++++++
tests/Unit/ExampleTest.php | 16 -
tests/Unit/Mail/AnswerNotificationTest.php | 52 +++
.../Mail/DeadlineForAccountabilityTest.php | 173 ++++++++++
tests/Unit/Mail/EmailRegistrationOppTest.php | 90 ++++++
tests/Unit/Mail/PublishedRecourseTest.php | 82 +++++
34 files changed, 1040 insertions(+), 438 deletions(-)
delete mode 100644 app/Mail/SendRegistration.php
create mode 100644 tests/Unit/Console/Commands/ConsumePublishedRecourseEmailsTest.php
create mode 100644 tests/Unit/Console/Commands/ConsumerCommandTest.php
delete mode 100644 tests/Unit/ExampleTest.php
create mode 100644 tests/Unit/Mail/AnswerNotificationTest.php
create mode 100644 tests/Unit/Mail/DeadlineForAccountabilityTest.php
create mode 100644 tests/Unit/Mail/EmailRegistrationOppTest.php
create mode 100644 tests/Unit/Mail/PublishedRecourseTest.php
diff --git a/.env.testing b/.env.testing
index 8601ad6..6306635 100644
--- a/.env.testing
+++ b/.env.testing
@@ -1,7 +1,7 @@
APP_NAME=Laravel
APP_ENV=testing
APP_KEY=base64:Bq7kBLzjHsoonNahT0xa08HqG4jQD62dw1LRXMCNdCE=
-APP_DEBUG=true
+APP_DEBUG=false
APP_TIMEZONE=UTC
APP_URL=http://localhost
@@ -20,11 +20,11 @@ LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug
DB_CONNECTION=pgsql
-DB_HOST=172.19.18.213
-DB_PORT=5433
+DB_HOST=db-email
+DB_PORT=5432
DB_DATABASE=api_email_test
-DB_USERNAME=postgres
-DB_PASSWORD=12345678
+DB_USERNAME=api_email
+DB_PASSWORD=pass
SESSION_DRIVER=database
SESSION_LIFETIME=120
@@ -55,7 +55,6 @@ MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS="hello@example.com"
MAIL_FROM_NAME="${APP_NAME}"
-
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
diff --git a/.gitignore b/.gitignore
index 2cac750..40d2b49 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,3 +24,4 @@ storage
docker/logs/nginx/error.log
xdebug.log
+tests/coverage-html
diff --git a/app/Console/Commands/ConsumePublishedRecourseEmails.php b/app/Console/Commands/ConsumePublishedRecourseEmails.php
index 9b3e356..b05da36 100644
--- a/app/Console/Commands/ConsumePublishedRecourseEmails.php
+++ b/app/Console/Commands/ConsumePublishedRecourseEmails.php
@@ -3,9 +3,11 @@
namespace App\Console\Commands;
use App\Mail\PublishedRecourse;
+use Exception;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Mail;
use PhpAmqpLib\Connection\AMQPStreamConnection;
+use PhpAmqpLib\Message\AMQPMessage;
class ConsumePublishedRecourseEmails extends Command
{
@@ -25,28 +27,24 @@ class ConsumePublishedRecourseEmails extends Command
/**
* Execute the console command.
+ *
+ * @throws Exception
*/
- public function handle()
+ public function handle(): void
{
- // Conectar ao RabbitMQ
- $connection = new AMQPStreamConnection(env('RABBITMQ_DEFAULT_HOST'), env('RABBITMQ_DEFAULT_PORT'), env('RABBITMQ_DEFAULT_USER'), env('RABBITMQ_DEFAULT_PASS'));
+ $queue = config('app.rabbitmq.queues.published_recourses_queue');
+ $connection = new AMQPStreamConnection(
+ config('app.rabbitmq.host'),
+ config('app.rabbitmq.port'),
+ config('app.rabbitmq.user'),
+ config('app.rabbitmq.pass'),
+ );
$channel = $connection->channel();
+ $channel->queue_declare($queue, false, true, false, false);
- $channel->queue_declare('published_recourses_queue', false, true, false, false);
$this->info('🎯 Aguardando e-mails para envio...');
- $callback = function ($msg) {
- $data = json_decode($msg->body, true);
-
- if ($this->sendEmail($data)) {
- $msg->ack(); // Confirma o processamento
- $this->info("📧 E-mail enviado para: {$data['email']}");
- } else {
- $this->error("❌ Falha ao enviar e-mail para: {$data['email']}");
- }
- };
-
- $channel->basic_consume('published_recourses_queue', '', false, false, false, false, $callback);
+ $channel->basic_consume(queue: $queue, callback: $this->processMessage(...));
while ($channel->is_consuming()) {
$channel->wait();
@@ -62,8 +60,24 @@ private function sendEmail($data): bool
Mail::to($data['email'])->send(new PublishedRecourse($data));
return true;
- } catch (\Exception $e) {
+ } catch (Exception $e) {
+ logger($e->getMessage());
+
return false;
}
}
+
+ protected function processMessage(AMQPMessage $msg): void
+ {
+ $data = json_decode($msg->body, true);
+
+ if ($this->sendEmail($data)) {
+ $msg->ack(); // Confirma o processamento
+ $this->info("📧 E-mail enviado para: {$data['email']}");
+
+ return;
+ }
+
+ $this->error("❌ Falha ao enviar e-mail para: {$data['email']}");
+ }
}
diff --git a/app/Console/Commands/ConsumerCommand.php b/app/Console/Commands/ConsumerCommand.php
index 7d103e5..c51fa36 100644
--- a/app/Console/Commands/ConsumerCommand.php
+++ b/app/Console/Commands/ConsumerCommand.php
@@ -3,10 +3,11 @@
namespace App\Console\Commands;
use App\Mail\AnswerNotification;
-use Illuminate\Support\Facades\Mail;
use App\Mail\EmailRegistrationOpp;
use Illuminate\Console\Command;
+use Illuminate\Support\Facades\Mail;
use PhpAmqpLib\Connection\AMQPStreamConnection;
+use PhpAmqpLib\Message\AMQPMessage;
class ConsumerCommand extends Command
{
@@ -22,51 +23,57 @@ class ConsumerCommand extends Command
*
* @var string
*/
- protected $description = 'Cosumidor das filas do Rabbitmq para as diligências';
+ protected $description = 'Consumidor das filas do Rabbitmq para as diligências';
/**
* Execute the console command.
+ *
+ * @throws \Exception
*/
- public function handle()
+ public function handle(): int
{
- $queue = env('RABBITMQ_QUEUE_PC');
+ $queue = config('app.rabbitmq.queues.accountability');
$connection = new AMQPStreamConnection(
- env('RABBITMQ_DEFAULT_HOST'),
- env('RABBITMQ_DEFAULT_PORT'),
- env('RABBITMQ_DEFAULT_USER'),
- env('RABBITMQ_DEFAULT_PASS'),
- '/'
+ config('app.rabbitmq.host'),
+ config('app.rabbitmq.port'),
+ config('app.rabbitmq.user'),
+ config('app.rabbitmq.pass'),
+ '/',
);
$channel = $connection->channel();
$channel->queue_declare($queue, false, true, false, false);
- $callback = function ($msg) {
- $data = json_decode($msg->body);
- if( $msg->getRoutingKey() == env('RABBITMQ_QUEUE_PC_ROUTE_KEY_PROP') )
- {
- Mail::to($data->email)->send(new EmailRegistrationOpp(
- $data->name,
- $data->number,
- $data->days
- ));
- }
- if($msg->getRoutingKey() == env('RABBITMQ_QUEUE_PC_ROUTE_KEY_ADM'))
- {
- Mail::to($data->comission)->cc($data->owner)->send(new AnswerNotification(
- $data->registration,
- ));
- };
- $msg->delivery_info['channel']->basic_ack($msg->delivery_info['delivery_tag']);
- };
$channel->basic_qos(null, 1, null);
- $channel->basic_consume($queue, '', false, false, false, false, $callback);
+ $channel->basic_consume(queue: $queue, callback: $this->processMessage(...));
+
while ($channel->is_consuming()) {
+ $this->info('🎯 Aguardando e-mails para envio...');
$channel->wait();
}
$channel->close();
return Command::SUCCESS;
+ }
+
+ protected function processMessage(AMQPMessage $msg): void
+ {
+ $data = json_decode($msg->body);
+
+ if ($msg->getRoutingKey() == config('app.rabbitmq.route_key_prop')) {
+ Mail::to($data->email)->send(new EmailRegistrationOpp(
+ $data->name,
+ $data->number,
+ $data->days
+ ));
+ }
+
+ if ($msg->getRoutingKey() == config('app.rabbitmq.route_key_adm')) {
+ Mail::to($data->comission)->cc($data->owner)->send(new AnswerNotification(
+ $data->registration
+ ));
+ }
+ $msg->delivery_info['channel']->basic_ack($msg->delivery_info['delivery_tag']);
}
}
diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php
index 9e3c5a2..dac8294 100644
--- a/app/Http/Controllers/UserController.php
+++ b/app/Http/Controllers/UserController.php
@@ -9,22 +9,6 @@
class UserController extends Controller
{
- /**
- * Display a listing of the resource.
- */
- public function index()
- {
- //
- }
-
- /**
- * Show the form for creating a new resource.
- */
- public function create()
- {
- //
- }
-
/**
* Handle an incoming registration request.
*
@@ -32,55 +16,15 @@ public function create()
*/
public function store(Request $request): JsonResponse
{
-
- // $request->validate([
- // 'name' => ['required', 'string', 'max:255'],
- // 'email' => ['required', 'string', 'lowercase', 'email', 'max:255', 'unique:'.User::class],
- // 'password' => ['required', 'confirmed', Rules\Password::defaults()],
- // ]);
-
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password),
]);
-// event(new Registered($user));
$token = $user->createToken('here-token-name');
- return response()->json( ['token' => $token->plainTextToken]);
- }
-
- /**
- * Display the specified resource.
- */
- public function show(string $id)
- {
- //
- }
-
- /**
- * Show the form for editing the specified resource.
- */
- public function edit(string $id)
- {
- //
- }
-
- /**
- * Update the specified resource in storage.
- */
- public function update(Request $request, string $id)
- {
- //
- }
-
- /**
- * Remove the specified resource from storage.
- */
- public function destroy(string $id)
- {
- //
+ return response()->json(['token' => $token->plainTextToken]);
}
public function draft(Request $request)
diff --git a/app/Jobs/NotificationAccountability.php b/app/Jobs/NotificationAccountability.php
index 3fe2a04..67ec48b 100644
--- a/app/Jobs/NotificationAccountability.php
+++ b/app/Jobs/NotificationAccountability.php
@@ -16,15 +16,13 @@ class NotificationAccountability implements ShouldQueue
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public $tries = 3;
+
public $backoff = 60;
/**
* Create a new job instance.
*/
- public function __construct(protected $infos)
- {
-
- }
+ public function __construct(protected $infos) {}
/**
* Execute the job.
@@ -32,13 +30,13 @@ public function __construct(protected $infos)
public function handle(): void
{
foreach ($this->infos as $info) {
- $info = (object)$info;
+ $info = (object) $info;
$emailSent = Mail::to($info->user_email)->send(new DeadlineForAccountability($info));
// $info->is_last_notification, último dia para enviar a notificação
if ($emailSent instanceof \Illuminate\Mail\SentMessage && $info->is_last_notification) {
- Http::post(config('app.mapa_url') . 'bigsheet/updateNotificationStatus', [
+ Http::post(config('app.mapa_url').'/bigsheet/updateNotificationStatus', [
'registration_number' => $info->registration_number,
- 'access_token' => config('jwt.secret')
+ 'access_token' => config('jwt.secret'),
]);
}
}
diff --git a/app/Mail/AnswerNotification.php b/app/Mail/AnswerNotification.php
index db08d72..ecdf52c 100644
--- a/app/Mail/AnswerNotification.php
+++ b/app/Mail/AnswerNotification.php
@@ -3,7 +3,6 @@
namespace App\Mail;
use Illuminate\Bus\Queueable;
-use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
@@ -18,8 +17,7 @@ class AnswerNotification extends Mailable
*/
public function __construct(
public string $number,
- )
- { }
+ ) {}
/**
* Get the message envelope.
diff --git a/app/Mail/DeadlineForAccountability.php b/app/Mail/DeadlineForAccountability.php
index 2543c4a..6a516eb 100644
--- a/app/Mail/DeadlineForAccountability.php
+++ b/app/Mail/DeadlineForAccountability.php
@@ -3,7 +3,6 @@
namespace App\Mail;
use Illuminate\Bus\Queueable;
-use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
@@ -13,8 +12,11 @@
class DeadlineForAccountability extends Mailable
{
use Queueable, SerializesModels;
+
public string $complementText = 'está na hora de preencher e enviar';
+
public string $titleReport = '';
+
/**
* Create a new message instance.
*/
@@ -38,18 +40,22 @@ public function envelope(): Envelope
*/
public function content(): Content
{
- $e = new Extensive();
- if($this->info->days_current === 85 || $this->info->days_current === 55){
+ $e = new Extensive;
+ if ($this->info->days_current === 85 || $this->info->days_current === 55) {
$this->complementText = 'faltam 05 (cinco) dias para o envio';
}
- // Mudando o titulo do relatorio
- $this->info->notification_type === "REFO" ? $this->titleReport = 'Relatório de Execução Final do Objeto - REFO' : $this->titleReport = 'Relatório de Avaliação Intermediária do Objeto - RAIO';
+
+ // Mudando o titulo do relatório
+ $this->titleReport = $this->info->notification_type === 'REFO'
+ ? 'Relatório de Execução Final do Objeto - REFO'
+ : 'Relatório de Avaliação Intermediária do Objeto - RAIO';
+
return new Content(
view: 'emails.deadline-for-accountability',
with: [
'info' => $this->info,
- 'days_current' => $e->extensive( $this->info->days_current, Extensive::MALE_NUMBER ),
- 'complment_text' => $this->complementText,
+ 'days_current' => $e->extensive($this->info->days_current, Extensive::MALE_NUMBER),
+ 'complement_text' => $this->complementText,
'title_report' => $this->titleReport,
]
);
diff --git a/app/Mail/EmailRegistrationOpp.php b/app/Mail/EmailRegistrationOpp.php
index 9ed395d..17f354a 100644
--- a/app/Mail/EmailRegistrationOpp.php
+++ b/app/Mail/EmailRegistrationOpp.php
@@ -3,7 +3,6 @@
namespace App\Mail;
use Illuminate\Bus\Queueable;
-use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
@@ -20,8 +19,7 @@ public function __construct(
public string $nameUser,
public string $number,
public string $days
- )
- { }
+ ) {}
/**
* Get the message envelope.
diff --git a/app/Mail/PublishedRecourse.php b/app/Mail/PublishedRecourse.php
index e71a8c7..619b620 100644
--- a/app/Mail/PublishedRecourse.php
+++ b/app/Mail/PublishedRecourse.php
@@ -3,7 +3,6 @@
namespace App\Mail;
use Illuminate\Bus\Queueable;
-use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
diff --git a/app/Mail/SendRegistration.php b/app/Mail/SendRegistration.php
deleted file mode 100644
index b3d9bbc..0000000
--- a/app/Mail/SendRegistration.php
+++ /dev/null
@@ -1 +0,0 @@
-withRouting(
@@ -13,15 +15,18 @@
)
->withMiddleware(function (Middleware $middleware) {
$middleware->api(prepend: [
- \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
+ EnsureFrontendRequestsAreStateful::class,
]);
$middleware->alias([
- 'verified' => \App\Http\Middleware\EnsureEmailIsVerified::class,
+ 'verified' => EnsureEmailIsVerified::class,
]);
-
- //
})
->withExceptions(function (Exceptions $exceptions) {
- //
- })->create();
+ // $exceptions->alias([
+ // 'auth' => \App\Exceptions\AuthenticationException::class,
+ // 'http' => \App\Exceptions\HttpException::class,
+ // 'validation' => \App\Exceptions\ValidationException::class,
+ // ]);
+ })
+ ->create();
diff --git a/composer.json b/composer.json
index edf587f..e3fd1bb 100644
--- a/composer.json
+++ b/composer.json
@@ -25,7 +25,8 @@
"mockery/mockery": "^1.6",
"nunomaduro/collision": "^8.0",
"phpunit/phpunit": "^11.0",
- "spatie/laravel-ignition": "^2.4"
+ "spatie/laravel-ignition": "^2.4",
+ "ext-pcntl": "*"
},
"autoload": {
"psr-4": {
diff --git a/composer.lock b/composer.lock
index e7eacb8..3a0a2c7 100644
--- a/composer.lock
+++ b/composer.lock
@@ -645,16 +645,16 @@
},
{
"name": "guzzlehttp/guzzle",
- "version": "7.9.2",
+ "version": "7.9.3",
"source": {
"type": "git",
"url": "https://github.com/guzzle/guzzle.git",
- "reference": "d281ed313b989f213357e3be1a179f02196ac99b"
+ "reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/guzzle/guzzle/zipball/d281ed313b989f213357e3be1a179f02196ac99b",
- "reference": "d281ed313b989f213357e3be1a179f02196ac99b",
+ "url": "https://api.github.com/repos/guzzle/guzzle/zipball/7b2f29fe81dc4da0ca0ea7d42107a0845946ea77",
+ "reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77",
"shasum": ""
},
"require": {
@@ -751,7 +751,7 @@
],
"support": {
"issues": "https://github.com/guzzle/guzzle/issues",
- "source": "https://github.com/guzzle/guzzle/tree/7.9.2"
+ "source": "https://github.com/guzzle/guzzle/tree/7.9.3"
},
"funding": [
{
@@ -767,20 +767,20 @@
"type": "tidelift"
}
],
- "time": "2024-07-24T11:22:20+00:00"
+ "time": "2025-03-27T13:37:11+00:00"
},
{
"name": "guzzlehttp/promises",
- "version": "2.0.4",
+ "version": "2.2.0",
"source": {
"type": "git",
"url": "https://github.com/guzzle/promises.git",
- "reference": "f9c436286ab2892c7db7be8c8da4ef61ccf7b455"
+ "reference": "7c69f28996b0a6920945dd20b3857e499d9ca96c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/guzzle/promises/zipball/f9c436286ab2892c7db7be8c8da4ef61ccf7b455",
- "reference": "f9c436286ab2892c7db7be8c8da4ef61ccf7b455",
+ "url": "https://api.github.com/repos/guzzle/promises/zipball/7c69f28996b0a6920945dd20b3857e499d9ca96c",
+ "reference": "7c69f28996b0a6920945dd20b3857e499d9ca96c",
"shasum": ""
},
"require": {
@@ -834,7 +834,7 @@
],
"support": {
"issues": "https://github.com/guzzle/promises/issues",
- "source": "https://github.com/guzzle/promises/tree/2.0.4"
+ "source": "https://github.com/guzzle/promises/tree/2.2.0"
},
"funding": [
{
@@ -850,20 +850,20 @@
"type": "tidelift"
}
],
- "time": "2024-10-17T10:06:22+00:00"
+ "time": "2025-03-27T13:27:01+00:00"
},
{
"name": "guzzlehttp/psr7",
- "version": "2.7.0",
+ "version": "2.7.1",
"source": {
"type": "git",
"url": "https://github.com/guzzle/psr7.git",
- "reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201"
+ "reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/guzzle/psr7/zipball/a70f5c95fb43bc83f07c9c948baa0dc1829bf201",
- "reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201",
+ "url": "https://api.github.com/repos/guzzle/psr7/zipball/c2270caaabe631b3b44c85f99e5a04bbb8060d16",
+ "reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16",
"shasum": ""
},
"require": {
@@ -950,7 +950,7 @@
],
"support": {
"issues": "https://github.com/guzzle/psr7/issues",
- "source": "https://github.com/guzzle/psr7/tree/2.7.0"
+ "source": "https://github.com/guzzle/psr7/tree/2.7.1"
},
"funding": [
{
@@ -966,7 +966,7 @@
"type": "tidelift"
}
],
- "time": "2024-07-18T11:15:46+00:00"
+ "time": "2025-03-27T12:30:47+00:00"
},
{
"name": "guzzlehttp/uri-template",
@@ -1096,16 +1096,16 @@
},
{
"name": "laravel/framework",
- "version": "v12.3.0",
+ "version": "v12.7.2",
"source": {
"type": "git",
"url": "https://github.com/laravel/framework.git",
- "reference": "ca0412e978f78ecea0cafbe34dd8b18010064f73"
+ "reference": "a4ba76e06fe6dd02312359f8184ab259900a7780"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/framework/zipball/ca0412e978f78ecea0cafbe34dd8b18010064f73",
- "reference": "ca0412e978f78ecea0cafbe34dd8b18010064f73",
+ "url": "https://api.github.com/repos/laravel/framework/zipball/a4ba76e06fe6dd02312359f8184ab259900a7780",
+ "reference": "a4ba76e06fe6dd02312359f8184ab259900a7780",
"shasum": ""
},
"require": {
@@ -1307,7 +1307,7 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
- "time": "2025-03-18T13:49:19+00:00"
+ "time": "2025-04-03T18:00:49+00:00"
},
{
"name": "laravel/prompts",
@@ -1434,16 +1434,16 @@
},
{
"name": "laravel/serializable-closure",
- "version": "v2.0.3",
+ "version": "v2.0.4",
"source": {
"type": "git",
"url": "https://github.com/laravel/serializable-closure.git",
- "reference": "f379c13663245f7aa4512a7869f62eb14095f23f"
+ "reference": "b352cf0534aa1ae6b4d825d1e762e35d43f8a841"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/f379c13663245f7aa4512a7869f62eb14095f23f",
- "reference": "f379c13663245f7aa4512a7869f62eb14095f23f",
+ "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/b352cf0534aa1ae6b4d825d1e762e35d43f8a841",
+ "reference": "b352cf0534aa1ae6b4d825d1e762e35d43f8a841",
"shasum": ""
},
"require": {
@@ -1491,7 +1491,7 @@
"issues": "https://github.com/laravel/serializable-closure/issues",
"source": "https://github.com/laravel/serializable-closure"
},
- "time": "2025-02-11T15:03:05+00:00"
+ "time": "2025-03-19T13:51:03+00:00"
},
{
"name": "laravel/tinker",
@@ -2353,16 +2353,16 @@
},
{
"name": "nesbot/carbon",
- "version": "3.8.6",
+ "version": "3.9.0",
"source": {
"type": "git",
"url": "https://github.com/CarbonPHP/carbon.git",
- "reference": "ff2f20cf83bd4d503720632ce8a426dc747bf7fd"
+ "reference": "6d16a8a015166fe54e22c042e0805c5363aef50d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/ff2f20cf83bd4d503720632ce8a426dc747bf7fd",
- "reference": "ff2f20cf83bd4d503720632ce8a426dc747bf7fd",
+ "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/6d16a8a015166fe54e22c042e0805c5363aef50d",
+ "reference": "6d16a8a015166fe54e22c042e0805c5363aef50d",
"shasum": ""
},
"require": {
@@ -2455,7 +2455,7 @@
"type": "tidelift"
}
],
- "time": "2025-02-20T17:33:38+00:00"
+ "time": "2025-03-27T12:57:33+00:00"
},
{
"name": "nette/schema",
@@ -2521,16 +2521,16 @@
},
{
"name": "nette/utils",
- "version": "v4.0.5",
+ "version": "v4.0.6",
"source": {
"type": "git",
"url": "https://github.com/nette/utils.git",
- "reference": "736c567e257dbe0fcf6ce81b4d6dbe05c6899f96"
+ "reference": "ce708655043c7050eb050df361c5e313cf708309"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nette/utils/zipball/736c567e257dbe0fcf6ce81b4d6dbe05c6899f96",
- "reference": "736c567e257dbe0fcf6ce81b4d6dbe05c6899f96",
+ "url": "https://api.github.com/repos/nette/utils/zipball/ce708655043c7050eb050df361c5e313cf708309",
+ "reference": "ce708655043c7050eb050df361c5e313cf708309",
"shasum": ""
},
"require": {
@@ -2601,9 +2601,9 @@
],
"support": {
"issues": "https://github.com/nette/utils/issues",
- "source": "https://github.com/nette/utils/tree/v4.0.5"
+ "source": "https://github.com/nette/utils/tree/v4.0.6"
},
- "time": "2024-08-07T15:39:19+00:00"
+ "time": "2025-03-30T21:06:30+00:00"
},
{
"name": "nikic/php-parser",
@@ -3912,16 +3912,16 @@
},
{
"name": "symfony/console",
- "version": "v7.2.1",
+ "version": "v7.2.5",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
- "reference": "fefcc18c0f5d0efe3ab3152f15857298868dc2c3"
+ "reference": "e51498ea18570c062e7df29d05a7003585b19b88"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/console/zipball/fefcc18c0f5d0efe3ab3152f15857298868dc2c3",
- "reference": "fefcc18c0f5d0efe3ab3152f15857298868dc2c3",
+ "url": "https://api.github.com/repos/symfony/console/zipball/e51498ea18570c062e7df29d05a7003585b19b88",
+ "reference": "e51498ea18570c062e7df29d05a7003585b19b88",
"shasum": ""
},
"require": {
@@ -3985,7 +3985,7 @@
"terminal"
],
"support": {
- "source": "https://github.com/symfony/console/tree/v7.2.1"
+ "source": "https://github.com/symfony/console/tree/v7.2.5"
},
"funding": [
{
@@ -4001,7 +4001,7 @@
"type": "tidelift"
}
],
- "time": "2024-12-11T03:49:26+00:00"
+ "time": "2025-03-12T08:11:12+00:00"
},
{
"name": "symfony/css-selector",
@@ -4137,16 +4137,16 @@
},
{
"name": "symfony/error-handler",
- "version": "v7.2.4",
+ "version": "v7.2.5",
"source": {
"type": "git",
"url": "https://github.com/symfony/error-handler.git",
- "reference": "aabf79938aa795350c07ce6464dd1985607d95d5"
+ "reference": "102be5e6a8e4f4f3eb3149bcbfa33a80d1ee374b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/error-handler/zipball/aabf79938aa795350c07ce6464dd1985607d95d5",
- "reference": "aabf79938aa795350c07ce6464dd1985607d95d5",
+ "url": "https://api.github.com/repos/symfony/error-handler/zipball/102be5e6a8e4f4f3eb3149bcbfa33a80d1ee374b",
+ "reference": "102be5e6a8e4f4f3eb3149bcbfa33a80d1ee374b",
"shasum": ""
},
"require": {
@@ -4192,7 +4192,7 @@
"description": "Provides tools to manage errors and ease debugging PHP code",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/error-handler/tree/v7.2.4"
+ "source": "https://github.com/symfony/error-handler/tree/v7.2.5"
},
"funding": [
{
@@ -4208,7 +4208,7 @@
"type": "tidelift"
}
],
- "time": "2025-02-02T20:27:07+00:00"
+ "time": "2025-03-03T07:12:39+00:00"
},
{
"name": "symfony/event-dispatcher",
@@ -4432,16 +4432,16 @@
},
{
"name": "symfony/http-foundation",
- "version": "v7.2.3",
+ "version": "v7.2.5",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-foundation.git",
- "reference": "ee1b504b8926198be89d05e5b6fc4c3810c090f0"
+ "reference": "371272aeb6286f8135e028ca535f8e4d6f114126"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/http-foundation/zipball/ee1b504b8926198be89d05e5b6fc4c3810c090f0",
- "reference": "ee1b504b8926198be89d05e5b6fc4c3810c090f0",
+ "url": "https://api.github.com/repos/symfony/http-foundation/zipball/371272aeb6286f8135e028ca535f8e4d6f114126",
+ "reference": "371272aeb6286f8135e028ca535f8e4d6f114126",
"shasum": ""
},
"require": {
@@ -4490,7 +4490,7 @@
"description": "Defines an object-oriented layer for the HTTP specification",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/http-foundation/tree/v7.2.3"
+ "source": "https://github.com/symfony/http-foundation/tree/v7.2.5"
},
"funding": [
{
@@ -4506,20 +4506,20 @@
"type": "tidelift"
}
],
- "time": "2025-01-17T10:56:55+00:00"
+ "time": "2025-03-25T15:54:33+00:00"
},
{
"name": "symfony/http-kernel",
- "version": "v7.2.4",
+ "version": "v7.2.5",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-kernel.git",
- "reference": "9f1103734c5789798fefb90e91de4586039003ed"
+ "reference": "b1fe91bc1fa454a806d3f98db4ba826eb9941a54"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/http-kernel/zipball/9f1103734c5789798fefb90e91de4586039003ed",
- "reference": "9f1103734c5789798fefb90e91de4586039003ed",
+ "url": "https://api.github.com/repos/symfony/http-kernel/zipball/b1fe91bc1fa454a806d3f98db4ba826eb9941a54",
+ "reference": "b1fe91bc1fa454a806d3f98db4ba826eb9941a54",
"shasum": ""
},
"require": {
@@ -4604,7 +4604,7 @@
"description": "Provides a structured process for converting a Request into a Response",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/http-kernel/tree/v7.2.4"
+ "source": "https://github.com/symfony/http-kernel/tree/v7.2.5"
},
"funding": [
{
@@ -4620,7 +4620,7 @@
"type": "tidelift"
}
],
- "time": "2025-02-26T11:01:22+00:00"
+ "time": "2025-03-28T13:32:50+00:00"
},
{
"name": "symfony/mailer",
@@ -5424,16 +5424,16 @@
},
{
"name": "symfony/process",
- "version": "v7.2.4",
+ "version": "v7.2.5",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
- "reference": "d8f411ff3c7ddc4ae9166fb388d1190a2df5b5cf"
+ "reference": "87b7c93e57df9d8e39a093d32587702380ff045d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/process/zipball/d8f411ff3c7ddc4ae9166fb388d1190a2df5b5cf",
- "reference": "d8f411ff3c7ddc4ae9166fb388d1190a2df5b5cf",
+ "url": "https://api.github.com/repos/symfony/process/zipball/87b7c93e57df9d8e39a093d32587702380ff045d",
+ "reference": "87b7c93e57df9d8e39a093d32587702380ff045d",
"shasum": ""
},
"require": {
@@ -5465,7 +5465,7 @@
"description": "Executes commands in sub-processes",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/process/tree/v7.2.4"
+ "source": "https://github.com/symfony/process/tree/v7.2.5"
},
"funding": [
{
@@ -5481,7 +5481,7 @@
"type": "tidelift"
}
],
- "time": "2025-02-05T08:33:46+00:00"
+ "time": "2025-03-13T12:21:46+00:00"
},
{
"name": "symfony/routing",
@@ -7214,38 +7214,39 @@
},
{
"name": "nunomaduro/collision",
- "version": "v8.7.0",
+ "version": "v8.8.0",
"source": {
"type": "git",
"url": "https://github.com/nunomaduro/collision.git",
- "reference": "586cb8181a257a2152b6a855ca8d9598878a1a26"
+ "reference": "4cf9f3b47afff38b139fb79ce54fc71799022ce8"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nunomaduro/collision/zipball/586cb8181a257a2152b6a855ca8d9598878a1a26",
- "reference": "586cb8181a257a2152b6a855ca8d9598878a1a26",
+ "url": "https://api.github.com/repos/nunomaduro/collision/zipball/4cf9f3b47afff38b139fb79ce54fc71799022ce8",
+ "reference": "4cf9f3b47afff38b139fb79ce54fc71799022ce8",
"shasum": ""
},
"require": {
- "filp/whoops": "^2.17.0",
+ "filp/whoops": "^2.18.0",
"nunomaduro/termwind": "^2.3.0",
"php": "^8.2.0",
- "symfony/console": "^7.2.1"
+ "symfony/console": "^7.2.5"
},
"conflict": {
- "laravel/framework": "<11.39.1 || >=13.0.0",
- "phpunit/phpunit": "<11.5.3 || >=12.0.0"
+ "laravel/framework": "<11.44.2 || >=13.0.0",
+ "phpunit/phpunit": "<11.5.15 || >=13.0.0"
},
"require-dev": {
- "larastan/larastan": "^2.10.0",
- "laravel/framework": "^11.44.2",
+ "brianium/paratest": "^7.8.3",
+ "larastan/larastan": "^3.2",
+ "laravel/framework": "^11.44.2 || ^12.6",
"laravel/pint": "^1.21.2",
"laravel/sail": "^1.41.0",
"laravel/sanctum": "^4.0.8",
"laravel/tinker": "^2.10.1",
- "orchestra/testbench-core": "^9.12.0",
- "pestphp/pest": "^3.7.4",
- "sebastian/environment": "^6.1.0 || ^7.2.0"
+ "orchestra/testbench-core": "^9.12.0 || ^10.1",
+ "pestphp/pest": "^3.8.0",
+ "sebastian/environment": "^7.2.0 || ^8.0"
},
"type": "library",
"extra": {
@@ -7308,7 +7309,7 @@
"type": "patreon"
}
],
- "time": "2025-03-14T22:37:40+00:00"
+ "time": "2025-04-03T14:33:09+00:00"
},
{
"name": "phar-io/manifest",
@@ -9212,16 +9213,16 @@
},
{
"name": "symfony/yaml",
- "version": "v7.2.3",
+ "version": "v7.2.5",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
- "reference": "ac238f173df0c9c1120f862d0f599e17535a87ec"
+ "reference": "4c4b6f4cfcd7e52053f0c8bfad0f7f30fb924912"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/yaml/zipball/ac238f173df0c9c1120f862d0f599e17535a87ec",
- "reference": "ac238f173df0c9c1120f862d0f599e17535a87ec",
+ "url": "https://api.github.com/repos/symfony/yaml/zipball/4c4b6f4cfcd7e52053f0c8bfad0f7f30fb924912",
+ "reference": "4c4b6f4cfcd7e52053f0c8bfad0f7f30fb924912",
"shasum": ""
},
"require": {
@@ -9264,7 +9265,7 @@
"description": "Loads and dumps YAML files",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/yaml/tree/v7.2.3"
+ "source": "https://github.com/symfony/yaml/tree/v7.2.5"
},
"funding": [
{
@@ -9280,7 +9281,7 @@
"type": "tidelift"
}
],
- "time": "2025-01-07T12:55:42+00:00"
+ "time": "2025-03-03T07:12:39+00:00"
},
{
"name": "theseer/tokenizer",
diff --git a/config/app.php b/config/app.php
index ee550c1..2dbd3c5 100644
--- a/config/app.php
+++ b/config/app.php
@@ -125,4 +125,16 @@
'mapa_url' => env('MAPA_URL'),
+ 'rabbitmq' => [
+ 'host' => env('RABBITMQ_DEFAULT_HOST'),
+ 'port' => env('RABBITMQ_DEFAULT_PORT'),
+ 'user' => env('RABBITMQ_DEFAULT_USER'),
+ 'pass' => env('RABBITMQ_DEFAULT_PASS'),
+ 'queues' => [
+ 'accountability' => env('RABBITMQ_QUEUE_PC'),
+ 'published_recourses' => env('RABBITMQ_QUEUE_PUBLISHED_RECOURSES'),
+ ],
+ 'route_key_prop' => env('RABBITMQ_QUEUE_PC_ROUTE_KEY_PROP'),
+ 'route_key_adm' => env('RABBITMQ_QUEUE_PC_ROUTE_KEY_ADM'),
+ ],
];
diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php
index d01a0ef..5b566ca 100644
--- a/database/seeders/DatabaseSeeder.php
+++ b/database/seeders/DatabaseSeeder.php
@@ -13,8 +13,6 @@ class DatabaseSeeder extends Seeder
*/
public function run(): void
{
- // User::factory(10)->create();
-
User::factory()->create([
'name' => 'Test User',
'email' => 'test@example.com',
diff --git a/lang/pt_BR/validation.php b/lang/pt_BR/validation.php
index 056d64a..778243b 100644
--- a/lang/pt_BR/validation.php
+++ b/lang/pt_BR/validation.php
@@ -13,154 +13,154 @@
|
*/
- 'accepted' => 'O campo :attribute deve ser aceito.',
- 'accepted_if' => 'O :attribute deve ser aceito quando :other for :value.',
- 'active_url' => 'O campo :attribute não é uma URL válida.',
- 'after' => 'O campo :attribute deve ser uma data posterior a :date.',
- 'after_or_equal' => 'O campo :attribute deve ser uma data posterior ou igual a :date.',
- 'alpha' => 'O campo :attribute só pode conter letras.',
- 'alpha_dash' => 'O campo :attribute só pode conter letras, números e traços.',
- 'alpha_num' => 'O campo :attribute só pode conter letras e números.',
- 'array' => 'O campo :attribute deve ser uma matriz.',
- 'ascii' => 'O campo :attribute deve conter somente caracteres alfanuméricos.',
- 'before' => 'O campo :attribute deve ser uma data anterior :date.',
- 'before_or_equal' => 'O campo :attribute deve ser uma data anterior ou igual a :date.',
- 'between' => [
+ 'accepted' => 'O campo :attribute deve ser aceito.',
+ 'accepted_if' => 'O :attribute deve ser aceito quando :other for :value.',
+ 'active_url' => 'O campo :attribute não é uma URL válida.',
+ 'after' => 'O campo :attribute deve ser uma data posterior a :date.',
+ 'after_or_equal' => 'O campo :attribute deve ser uma data posterior ou igual a :date.',
+ 'alpha' => 'O campo :attribute só pode conter letras.',
+ 'alpha_dash' => 'O campo :attribute só pode conter letras, números e traços.',
+ 'alpha_num' => 'O campo :attribute só pode conter letras e números.',
+ 'array' => 'O campo :attribute deve ser uma matriz.',
+ 'ascii' => 'O campo :attribute deve conter somente caracteres alfanuméricos.',
+ 'before' => 'O campo :attribute deve ser uma data anterior :date.',
+ 'before_or_equal' => 'O campo :attribute deve ser uma data anterior ou igual a :date.',
+ 'between' => [
'numeric' => 'O campo :attribute deve ser entre :min e :max.',
- 'file' => 'O campo :attribute deve ser entre :min e :max kilobytes.',
- 'string' => 'O campo :attribute deve ser entre :min e :max caracteres.',
- 'array' => 'O campo :attribute deve ter entre :min e :max itens.',
+ 'file' => 'O campo :attribute deve ser entre :min e :max kilobytes.',
+ 'string' => 'O campo :attribute deve ser entre :min e :max caracteres.',
+ 'array' => 'O campo :attribute deve ter entre :min e :max itens.',
],
- 'boolean' => 'O campo :attribute deve ser verdadeiro ou falso.',
- 'can' => 'O campo :attribute contém valores não autorizado.',
- 'confirmed' => 'O campo :attribute de confirmação não confere.',
- 'contains' => 'O campo :attribute está faltando um valor obrigatório.',
- 'current_password' => 'A senha está incorreta.',
- 'date' => 'O campo :attribute não é uma data válida.',
- 'date_equals' => 'O campo :attribute deve ser uma data igual a :date.',
- 'date_format' => 'O campo :attribute não corresponde ao formato :format.',
- 'decimal' => 'O campo :attribute deve ter :decimal casas decimais.',
- 'declined' => 'O :attribute deve ser recusado.',
- 'declined_if' => 'O :attribute deve ser recusado quando :other for :value.',
- 'different' => 'Os campos :attribute e :other devem ser diferentes.',
- 'digits' => 'O campo :attribute deve ter :digits dígitos.',
- 'digits_between' => 'O campo :attribute deve ter entre :min e :max dígitos.',
- 'dimensions' => 'O campo :attribute tem dimensões de imagem inválidas.',
- 'distinct' => 'O campo :attribute tem um valor duplicado.',
- 'doesnt_end_with' => 'O campo :attribute não pode terminar com um dos seguintes: :values.',
- 'doesnt_start_with' => 'O :attribute não pode começar com um dos seguintes: :values.',
- 'email' => 'O campo :attribute deve ser um endereço de e-mail válido.',
- 'ends_with' => 'O campo :attribute deve terminar com um dos seguintes: :values',
- 'enum' => 'O :attribute selecionado é inválido.',
- 'exists' => 'O campo :attribute selecionado é inválido.',
- 'extensions' => 'O campo :attribute deve conter uma das seguintes extensões: :values.',
- 'file' => 'O campo :attribute deve ser um arquivo.',
- 'filled' => 'O campo :attribute deve ter um valor.',
+ 'boolean' => 'O campo :attribute deve ser verdadeiro ou falso.',
+ 'can' => 'O campo :attribute contém valores não autorizado.',
+ 'confirmed' => 'O campo :attribute de confirmação não confere.',
+ 'contains' => 'O campo :attribute está faltando um valor obrigatório.',
+ 'current_password' => 'A senha está incorreta.',
+ 'date' => 'O campo :attribute não é uma data válida.',
+ 'date_equals' => 'O campo :attribute deve ser uma data igual a :date.',
+ 'date_format' => 'O campo :attribute não corresponde ao formato :format.',
+ 'decimal' => 'O campo :attribute deve ter :decimal casas decimais.',
+ 'declined' => 'O :attribute deve ser recusado.',
+ 'declined_if' => 'O :attribute deve ser recusado quando :other for :value.',
+ 'different' => 'Os campos :attribute e :other devem ser diferentes.',
+ 'digits' => 'O campo :attribute deve ter :digits dígitos.',
+ 'digits_between' => 'O campo :attribute deve ter entre :min e :max dígitos.',
+ 'dimensions' => 'O campo :attribute tem dimensões de imagem inválidas.',
+ 'distinct' => 'O campo :attribute tem um valor duplicado.',
+ 'doesnt_end_with' => 'O campo :attribute não pode terminar com um dos seguintes: :values.',
+ 'doesnt_start_with' => 'O :attribute não pode começar com um dos seguintes: :values.',
+ 'email' => 'O campo :attribute deve ser um endereço de e-mail válido.',
+ 'ends_with' => 'O campo :attribute deve terminar com um dos seguintes: :values',
+ 'enum' => 'O :attribute selecionado é inválido.',
+ 'exists' => 'O campo :attribute selecionado é inválido.',
+ 'extensions' => 'O campo :attribute deve conter uma das seguintes extensões: :values.',
+ 'file' => 'O campo :attribute deve ser um arquivo.',
+ 'filled' => 'O campo :attribute deve ter um valor.',
'gt' => [
'numeric' => 'O campo :attribute deve ser maior que :value.',
- 'file' => 'O campo :attribute deve ser maior que :value kilobytes.',
- 'string' => 'O campo :attribute deve ser maior que :value caracteres.',
- 'array' => 'O campo :attribute deve conter mais de :value itens.',
+ 'file' => 'O campo :attribute deve ser maior que :value kilobytes.',
+ 'string' => 'O campo :attribute deve ser maior que :value caracteres.',
+ 'array' => 'O campo :attribute deve conter mais de :value itens.',
],
'gte' => [
'numeric' => 'O campo :attribute deve ser maior ou igual a :value.',
- 'file' => 'O campo :attribute deve ser maior ou igual a :value kilobytes.',
- 'string' => 'O campo :attribute deve ser maior ou igual a :value caracteres.',
- 'array' => 'O campo :attribute deve conter :value itens ou mais.',
+ 'file' => 'O campo :attribute deve ser maior ou igual a :value kilobytes.',
+ 'string' => 'O campo :attribute deve ser maior ou igual a :value caracteres.',
+ 'array' => 'O campo :attribute deve conter :value itens ou mais.',
],
- 'hex_color' => 'O campo :attribute deve ser uma cor hexadecimal válida.',
- 'image' => 'O campo :attribute deve ser uma imagem.',
- 'in' => 'O campo :attribute selecionado é inválido.',
- 'in_array' => 'O campo :attribute não existe em :other.',
- 'integer' => 'O campo :attribute deve ser um número inteiro.',
- 'ip' => 'O campo :attribute deve ser um endereço de IP válido.',
- 'ipv4' => 'O campo :attribute deve ser um endereço IPv4 válido.',
- 'ipv6' => 'O campo :attribute deve ser um endereço IPv6 válido.',
- 'json' => 'O campo :attribute deve ser uma string JSON válida.',
+ 'hex_color' => 'O campo :attribute deve ser uma cor hexadecimal válida.',
+ 'image' => 'O campo :attribute deve ser uma imagem.',
+ 'in' => 'O campo :attribute selecionado é inválido.',
+ 'in_array' => 'O campo :attribute não existe em :other.',
+ 'integer' => 'O campo :attribute deve ser um número inteiro.',
+ 'ip' => 'O campo :attribute deve ser um endereço de IP válido.',
+ 'ipv4' => 'O campo :attribute deve ser um endereço IPv4 válido.',
+ 'ipv6' => 'O campo :attribute deve ser um endereço IPv6 válido.',
+ 'json' => 'O campo :attribute deve ser uma string JSON válida.',
'list' => 'O campo :attribute deve ser uma lista.',
'lowercase' => 'O campo :attribute deve estar em letras minúsculas.',
'lt' => [
'numeric' => 'O campo :attribute deve ser menor que :value.',
- 'file' => 'O campo :attribute deve ser menor que :value kilobytes.',
- 'string' => 'O campo :attribute deve ser menor que :value caracteres.',
- 'array' => 'O campo :attribute deve conter menos de :value itens.',
+ 'file' => 'O campo :attribute deve ser menor que :value kilobytes.',
+ 'string' => 'O campo :attribute deve ser menor que :value caracteres.',
+ 'array' => 'O campo :attribute deve conter menos de :value itens.',
],
'lte' => [
'numeric' => 'O campo :attribute deve ser menor ou igual a :value.',
- 'file' => 'O campo :attribute deve ser menor ou igual a :value kilobytes.',
- 'string' => 'O campo :attribute deve ser menor ou igual a :value caracteres.',
- 'array' => 'O campo :attribute não deve conter mais que :value itens.',
+ 'file' => 'O campo :attribute deve ser menor ou igual a :value kilobytes.',
+ 'string' => 'O campo :attribute deve ser menor ou igual a :value caracteres.',
+ 'array' => 'O campo :attribute não deve conter mais que :value itens.',
],
'mac_address' => 'O campo :attribute deve ser um MAC address válido.',
'max' => [
'numeric' => 'O campo :attribute não pode ser superior a :max.',
- 'file' => 'O campo :attribute não pode ser superior a :max kilobytes.',
- 'string' => 'O campo :attribute não pode ser superior a :max caracteres.',
- 'array' => 'O campo :attribute não pode ter mais do que :max itens.',
+ 'file' => 'O campo :attribute não pode ser superior a :max kilobytes.',
+ 'string' => 'O campo :attribute não pode ser superior a :max caracteres.',
+ 'array' => 'O campo :attribute não pode ter mais do que :max itens.',
],
- 'max_digits' => 'O campo :attribute não pode ser superior a :max dígitos',
- 'mimes' => 'O campo :attribute deve ser um arquivo do tipo: :values.',
- 'mimetypes' => 'O campo :attribute deve ser um arquivo do tipo: :values.',
+ 'max_digits' => 'O campo :attribute não pode ser superior a :max dígitos',
+ 'mimes' => 'O campo :attribute deve ser um arquivo do tipo: :values.',
+ 'mimetypes' => 'O campo :attribute deve ser um arquivo do tipo: :values.',
'min' => [
'numeric' => 'O campo :attribute deve ser pelo menos :min.',
- 'file' => 'O campo :attribute deve ter pelo menos :min kilobytes.',
- 'string' => 'O campo :attribute deve ter pelo menos :min caracteres.',
- 'array' => 'O campo :attribute deve ter pelo menos :min itens.',
+ 'file' => 'O campo :attribute deve ter pelo menos :min kilobytes.',
+ 'string' => 'O campo :attribute deve ter pelo menos :min caracteres.',
+ 'array' => 'O campo :attribute deve ter pelo menos :min itens.',
],
- 'missing' => 'O campo :attribute deve estar ausente.',
- 'missing_if' => 'O campo :attribute deve estar ausente quando :other for :value.',
- 'missing_unless' => 'O campo :attribute deve estar ausente, a menos que :other seja :value.',
- 'missing_with' => 'O campo :attribute não deve estar presente quando houver :values.',
- 'missing_with_all' => 'O campo :attribute deve estar ausente quando :values estiverem presentes.',
- 'min_digits' => 'O campo :attribute deve ter pelo menos :min dígitos',
- 'not_in' => 'O campo :attribute selecionado é inválido.',
- 'multiple_of' => 'O campo :attribute deve ser um múltiplo de :value.',
- 'not_regex' => 'O campo :attribute possui um formato inválido.',
- 'numeric' => 'O campo :attribute deve ser um número.',
+ 'missing' => 'O campo :attribute deve estar ausente.',
+ 'missing_if' => 'O campo :attribute deve estar ausente quando :other for :value.',
+ 'missing_unless' => 'O campo :attribute deve estar ausente, a menos que :other seja :value.',
+ 'missing_with' => 'O campo :attribute não deve estar presente quando houver :values.',
+ 'missing_with_all' => 'O campo :attribute deve estar ausente quando :values estiverem presentes.',
+ 'min_digits' => 'O campo :attribute deve ter pelo menos :min dígitos',
+ 'not_in' => 'O campo :attribute selecionado é inválido.',
+ 'multiple_of' => 'O campo :attribute deve ser um múltiplo de :value.',
+ 'not_regex' => 'O campo :attribute possui um formato inválido.',
+ 'numeric' => 'O campo :attribute deve ser um número.',
'password' => [
- 'letters' => 'O campo :attribute deve conter pelo menos uma letra.',
- 'mixed' => 'O campo :attribute deve conter pelo menos uma letra maiúscula e uma letra minúscula.',
- 'numbers' => 'O campo :attribute deve conter pelo menos um número.',
- 'symbols' => 'O campo :attribute deve conter pelo menos um símbolo.',
- 'uncompromised' => 'A senha que você inseriu em :attribute está em um vazamento de dados.'
- . ' Por favor escolha uma senha diferente.',
+ 'letters' => 'O campo :attribute deve conter pelo menos uma letra.',
+ 'mixed' => 'O campo :attribute deve conter pelo menos uma letra maiúscula e uma letra minúscula.',
+ 'numbers' => 'O campo :attribute deve conter pelo menos um número.',
+ 'symbols' => 'O campo :attribute deve conter pelo menos um símbolo.',
+ 'uncompromised' => 'A senha que você inseriu em :attribute está em um vazamento de dados.'
+ .' Por favor escolha uma senha diferente.',
],
- 'present' => 'O campo :attribute deve estar presente.',
- 'present_if' => 'O campo :attribute deve estar presente quando :other for :value.',
- 'present_unless' => 'O campo :attribute deve estar presente, a menos que :other seja :value.',
- 'present_with' => 'O campo :attribute deve estar presente quando :values estiver presente.',
- 'present_with_all' => 'O campo :attribute deve estar presente quando :values estiverem presentes.',
- 'regex' => 'O campo :attribute tem um formato inválido.',
- 'required' => 'O campo :attribute é obrigatório.',
- 'required_array_keys' => 'O campo :attribute deve conter entradas para: :values.',
- 'required_if' => 'O campo :attribute é obrigatório quando :other for :value.',
+ 'present' => 'O campo :attribute deve estar presente.',
+ 'present_if' => 'O campo :attribute deve estar presente quando :other for :value.',
+ 'present_unless' => 'O campo :attribute deve estar presente, a menos que :other seja :value.',
+ 'present_with' => 'O campo :attribute deve estar presente quando :values estiver presente.',
+ 'present_with_all' => 'O campo :attribute deve estar presente quando :values estiverem presentes.',
+ 'regex' => 'O campo :attribute tem um formato inválido.',
+ 'required' => 'O campo :attribute é obrigatório.',
+ 'required_array_keys' => 'O campo :attribute deve conter entradas para: :values.',
+ 'required_if' => 'O campo :attribute é obrigatório quando :other for :value.',
'required_if_accepted' => 'O campo :attribute é obrigatório quando :other for aceito.',
'required_if_declined' => 'O campo :attribute é obrigatório quando :other for recusado.',
- 'required_unless' => 'O campo :attribute é obrigatório exceto quando :other for :values.',
- 'required_with' => 'O campo :attribute é obrigatório quando :values está presente.',
- 'required_with_all' => 'O campo :attribute é obrigatório quando :values está presente.',
- 'required_without' => 'O campo :attribute é obrigatório quando :values não está presente.',
+ 'required_unless' => 'O campo :attribute é obrigatório exceto quando :other for :values.',
+ 'required_with' => 'O campo :attribute é obrigatório quando :values está presente.',
+ 'required_with_all' => 'O campo :attribute é obrigatório quando :values está presente.',
+ 'required_without' => 'O campo :attribute é obrigatório quando :values não está presente.',
'required_without_all' => 'O campo :attribute é obrigatório quando nenhum dos :values estão presentes.',
- 'prohibited' => 'O campo :attribute é proibido.',
- 'prohibited_if' => 'O campo :attribute é proibido quando :other for :value.',
- 'prohibited_unless' => 'O campo :attribute é proibido exceto quando :other for :values.',
- 'prohibits' => 'O campo :attribute proíbe :other de estar presente.',
- 'same' => 'Os campos :attribute e :other devem corresponder.',
- 'size' => [
+ 'prohibited' => 'O campo :attribute é proibido.',
+ 'prohibited_if' => 'O campo :attribute é proibido quando :other for :value.',
+ 'prohibited_unless' => 'O campo :attribute é proibido exceto quando :other for :values.',
+ 'prohibits' => 'O campo :attribute proíbe :other de estar presente.',
+ 'same' => 'Os campos :attribute e :other devem corresponder.',
+ 'size' => [
'numeric' => 'O campo :attribute deve ser :size.',
- 'file' => 'O campo :attribute deve ser :size kilobytes.',
- 'string' => 'O campo :attribute deve ser :size caracteres.',
- 'array' => 'O campo :attribute deve conter :size itens.',
+ 'file' => 'O campo :attribute deve ser :size kilobytes.',
+ 'string' => 'O campo :attribute deve ser :size caracteres.',
+ 'array' => 'O campo :attribute deve conter :size itens.',
],
- 'starts_with' => 'O campo :attribute deve começar com um dos seguintes valores: :values',
- 'string' => 'O campo :attribute deve ser uma string.',
- 'timezone' => 'O campo :attribute deve ser uma zona válida.',
- 'unique' => 'O campo :attribute já está sendo utilizado.',
- 'uploaded' => 'Ocorreu uma falha no upload do campo :attribute.',
- 'uppercase' => 'O campo :attribute deve conter letras maiúsculas.',
- 'url' => 'O campo :attribute tem um formato inválido.',
- 'ulid' => 'O campo :attribute deve ser um ULID válido.',
- 'uuid' => 'O campo :attribute deve ser um UUID válido.',
+ 'starts_with' => 'O campo :attribute deve começar com um dos seguintes valores: :values',
+ 'string' => 'O campo :attribute deve ser uma string.',
+ 'timezone' => 'O campo :attribute deve ser uma zona válida.',
+ 'unique' => 'O campo :attribute já está sendo utilizado.',
+ 'uploaded' => 'Ocorreu uma falha no upload do campo :attribute.',
+ 'uppercase' => 'O campo :attribute deve conter letras maiúsculas.',
+ 'url' => 'O campo :attribute tem um formato inválido.',
+ 'ulid' => 'O campo :attribute deve ser um ULID válido.',
+ 'uuid' => 'O campo :attribute deve ser um UUID válido.',
/*
|--------------------------------------------------------------------------
@@ -191,43 +191,43 @@
*/
'attributes' => [
- 'address' => 'endereço',
- 'age' => 'idade',
- 'body' => 'conteúdo',
- 'cell' => 'célula',
- 'city' => 'cidade',
- 'country' => 'país',
- 'date' => 'data',
- 'day' => 'dia',
- 'excerpt' => 'resumo',
+ 'address' => 'endereço',
+ 'age' => 'idade',
+ 'body' => 'conteúdo',
+ 'cell' => 'célula',
+ 'city' => 'cidade',
+ 'country' => 'país',
+ 'date' => 'data',
+ 'day' => 'dia',
+ 'excerpt' => 'resumo',
'first_name' => 'primeiro nome',
- 'gender' => 'gênero',
+ 'gender' => 'gênero',
'marital_status' => 'estado civil',
'profession' => 'profissão',
'nationality' => 'nacionalidade',
- 'hour' => 'hora',
+ 'hour' => 'hora',
'last_name' => 'sobrenome',
- 'message' => 'mensagem',
- 'minute' => 'minuto',
- 'mobile' => 'celular',
- 'month' => 'mês',
- 'name' => 'nome',
- 'zipcode' => 'cep',
- 'company_name' => 'razão social',
+ 'message' => 'mensagem',
+ 'minute' => 'minuto',
+ 'mobile' => 'celular',
+ 'month' => 'mês',
+ 'name' => 'nome',
+ 'zipcode' => 'cep',
+ 'company_name' => 'razão social',
'neighborhood' => 'bairro',
- 'number' => 'número',
- 'password' => 'senha',
- 'phone' => 'telefone',
- 'second' => 'segundo',
- 'sex' => 'sexo',
- 'state' => 'estado',
- 'street' => 'rua',
- 'subject' => 'assunto',
- 'text' => 'texto',
- 'time' => 'hora',
- 'title' => 'título',
- 'username' => 'usuário',
- 'year' => 'ano',
+ 'number' => 'número',
+ 'password' => 'senha',
+ 'phone' => 'telefone',
+ 'second' => 'segundo',
+ 'sex' => 'sexo',
+ 'state' => 'estado',
+ 'street' => 'rua',
+ 'subject' => 'assunto',
+ 'text' => 'texto',
+ 'time' => 'hora',
+ 'title' => 'título',
+ 'username' => 'usuário',
+ 'year' => 'ano',
'description' => 'descrição',
'password_confirmation' => 'confirmação da senha',
'current_password' => 'senha atual',
@@ -235,7 +235,7 @@
'modality' => 'modalidade',
'category' => 'categoria',
'blood_type' => 'tipo sanguíneo',
- 'birth_date' => 'data de nascimento'
+ 'birth_date' => 'data de nascimento',
],
];
diff --git a/phpunit.xml b/phpunit.xml
index 5c3671d..6120840 100644
--- a/phpunit.xml
+++ b/phpunit.xml
@@ -28,4 +28,9 @@
+
+
+
+
+
diff --git a/pint.json b/pint.json
index e69de29..93061b6 100644
--- a/pint.json
+++ b/pint.json
@@ -0,0 +1,3 @@
+{
+ "preset": "laravel"
+}
diff --git a/resources/views/emails/deadline-for-accountability.blade.php b/resources/views/emails/deadline-for-accountability.blade.php
index e2a50d8..9ce2ba2 100644
--- a/resources/views/emails/deadline-for-accountability.blade.php
+++ b/resources/views/emails/deadline-for-accountability.blade.php
@@ -12,7 +12,7 @@
A Secult vem por meio deste informar que já se passaram
{{$info->days_current}} ({{$days_current}})
dias da data do pagamento do seu projeto cultural.
- {{ $complment_text }}
+ {{ $complement_text }}
{{ $title_report }}
que deverá ser enviado através da plataforma Mapa Cultural.
diff --git a/routes/api.php b/routes/api.php
index e64fb65..7b991b7 100644
--- a/routes/api.php
+++ b/routes/api.php
@@ -1,9 +1,10 @@
middleware('guest')
diff --git a/routes/auth.php b/routes/auth.php
index ae6cc20..9cf5ffd 100644
--- a/routes/auth.php
+++ b/routes/auth.php
@@ -9,29 +9,29 @@
use Illuminate\Support\Facades\Route;
Route::post('/register', [RegisteredUserController::class, 'store'])
- ->middleware('guest')
- ->name('register');
+ ->middleware('guest')
+ ->name('register');
Route::post('/login', [AuthenticatedSessionController::class, 'store'])
- ->middleware('guest')
- ->name('login');
+ ->middleware('guest')
+ ->name('login');
Route::post('/forgot-password', [PasswordResetLinkController::class, 'store'])
- ->middleware('guest')
- ->name('password.email');
+ ->middleware('guest')
+ ->name('password.email');
Route::post('/reset-password', [NewPasswordController::class, 'store'])
- ->middleware('guest')
- ->name('password.store');
+ ->middleware('guest')
+ ->name('password.store');
Route::get('/verify-email/{id}/{hash}', VerifyEmailController::class)
- ->middleware(['auth', 'signed', 'throttle:6,1'])
- ->name('verification.verify');
+ ->middleware(['auth', 'signed', 'throttle:6,1'])
+ ->name('verification.verify');
Route::post('/email/verification-notification', [EmailVerificationNotificationController::class, 'store'])
- ->middleware(['auth', 'throttle:6,1'])
- ->name('verification.send');
+ ->middleware(['auth', 'throttle:6,1'])
+ ->name('verification.send');
Route::post('/logout', [AuthenticatedSessionController::class, 'destroy'])
- ->middleware('auth')
- ->name('logout');
+ ->middleware('auth')
+ ->name('logout');
diff --git a/routes/console.php b/routes/console.php
index 3e30e4e..ea1bdd4 100644
--- a/routes/console.php
+++ b/routes/console.php
@@ -1,11 +1,9 @@
purpose('Display an inspiring quote')->hourly();
Schedule::call(function () {
- $response = Http::get( config('app.mapa_url') . 'bigsheet/infoForNotificationsAccountability', [
- 'access_token' => config('jwt.secret')
+ $response = Http::get(config('app.mapa_url').'/bigsheet/infoForNotificationsAccountability', [
+ 'access_token' => config('jwt.secret'),
]);
$infos = $response->json();
diff --git a/routes/web.php b/routes/web.php
index c2b1e86..1128a7c 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -7,17 +7,16 @@
return ['Laravel' => app()->version()];
});
Route::get('/test', function () {
-// $words = SpellNumber::integer(85)->toLetters(); // 'pt' para português,
-// dump(SpellNumber);
- $e = new Extensive();
- dump($e->extensive( 185421.99 )); // mil e um reais
+ // $words = SpellNumber::integer(85)->toLetters(); // 'pt' para português,
+ // dump(SpellNumber);
+ $e = new Extensive;
+ dump($e->extensive(185421.99)); // mil e um reais
- dd($e->extensive( 54001.99, Extensive::MALE_NUMBER ));
+ dd($e->extensive(54001.99, Extensive::MALE_NUMBER));
Route::view('/welcome', 'emails.deadline-for-accountability', [
- 'days' => ''
+ 'days' => '',
]);
});
-
require __DIR__.'/auth.php';
diff --git a/tests/Feature/PC/EmailTest.php b/tests/Feature/PC/EmailTest.php
index 2cf6ad4..c923259 100644
--- a/tests/Feature/PC/EmailTest.php
+++ b/tests/Feature/PC/EmailTest.php
@@ -2,31 +2,29 @@
namespace Tests\Feature\PC;
-use Illuminate\Foundation\Testing\RefreshDatabase;
-use Illuminate\Foundation\Testing\WithFaker;
+use App\Jobs\NotificationAccountability;
use Illuminate\Support\Facades\Http;
use Tests\TestCase;
-use App\Jobs\NotificationAccountability;
class EmailTest extends TestCase
{
/**
* A basic feature test example.
*/
- public function test_return_api_and_passing_params_to_metod(): void
+ public function test_return_api_and_passing_params_to_method(): void
{
- $response = Http::get( 'http://172.19.18.161:8088/bigsheet/infoForNotificationsAccountability/', [
- 'access_token' => config('jwt.secret')
+ $response = Http::get(config('app.mapa_url').'/bigsheet/infoForNotificationsAccountability/', [
+ 'access_token' => config('jwt.secret'),
]);
- // Confirma que o status da resposta foi 200 (opcional, dependendo do teste)
+
$this->assertEquals(200, $response->status());
- // Converte o corpo da resposta para um array JSON
+
$jsonResponse = $response->json();
NotificationAccountability::dispatch($jsonResponse);
- $this->assertIsArray($jsonResponse); // Confirma que a resposta é um array
- // Se tiver array preenchido no retorno
- if(count($jsonResponse) > 0){
+ $this->assertIsArray($jsonResponse);
+
+ if (count($jsonResponse) > 0) {
// Verifica se a resposta contém uma chave específica
$this->assertArrayHasKey('registration_number', $jsonResponse[0]);
}
diff --git a/tests/TestCase.php b/tests/TestCase.php
index fe1ffc2..ee63ad0 100644
--- a/tests/TestCase.php
+++ b/tests/TestCase.php
@@ -4,7 +4,4 @@
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
-abstract class TestCase extends BaseTestCase
-{
- //
-}
+abstract class TestCase extends BaseTestCase {}
diff --git a/tests/Unit/Console/Commands/ConsumePublishedRecourseEmailsTest.php b/tests/Unit/Console/Commands/ConsumePublishedRecourseEmailsTest.php
new file mode 100644
index 0000000..2e03e81
--- /dev/null
+++ b/tests/Unit/Console/Commands/ConsumePublishedRecourseEmailsTest.php
@@ -0,0 +1,128 @@
+start();
+
+ sleep(1);
+ $this->assertTrue($process->isRunning());
+
+ $process->signal(SIGINT);
+
+ // Give it a moment to process the signal
+ sleep(1);
+
+ $this->assertFalse($process->isRunning());
+ $this->assertEquals(130, $process->getExitCode());
+ }
+
+ public function test_send_email_true(): void
+ {
+ Mail::fake();
+
+ // Create a mock AMQPMessage for prop route
+ $msgMock = $this->createMockAMQPMessage(
+ json_encode([
+ 'email' => 'test@email.test',
+ 'agentId' => 123456,
+ 'opportunityName' => 'Test Opportunity',
+ ]),
+ );
+
+ $command = new ConsumePublishedRecourseEmails;
+
+ $reflection = new \ReflectionClass($command);
+ $method = $reflection->getMethod('sendEmail');
+ $method->setAccessible(true);
+ $method->invoke($command, json_decode($msgMock->body, true));
+
+ // Asserts that the email was not sent
+ Mail::assertSent(PublishedRecourse::class);
+ }
+
+ public function test_send_email_false(): void
+ {
+ Mail::fake();
+
+ // Create a mock AMQPMessage for prop route
+ $msgMock = $this->createMockAMQPMessage(
+ json_encode([
+ 'emal' => 'test@email.fail',
+ 'agent' => 123456,
+ ]),
+ );
+
+ $command = new ConsumePublishedRecourseEmails;
+
+ $reflection = new \ReflectionClass($command);
+ $method = $reflection->getMethod('sendEmail');
+ $method->setAccessible(true);
+ $send = $method->invoke($command, json_decode($msgMock->body, true));
+
+ // Asserts that the email was not sent
+ $this->assertFalse($send);
+ Mail::assertNotSent(PublishedRecourse::class);
+ }
+
+ public function test_process_message_with_success(): void
+ {
+ Mail::fake();
+
+ $msgMock = $this->createMockAMQPMessage(
+ json_encode([
+ 'email' => 'test@example.com',
+ 'agentId' => 123456,
+ 'opportunityName' => 'Test Opportunity',
+ ])
+ );
+ $msgMock->shouldReceive('ack')
+ ->once()
+ ->andReturnNull();
+
+ $output = $this->createMock(OutputStyle::class);
+ $command = new ConsumePublishedRecourseEmails;
+ $command->setOutput($output);
+
+ $reflection = new \ReflectionClass($command);
+ $method = $reflection->getMethod('processMessage');
+ $method->setAccessible(true);
+ $method->invoke($command, $msgMock);
+
+ Mail::assertSent(PublishedRecourse::class);
+ }
+
+// public function test_process_message_with_failure(): void
+// {
+ // @TODO: Needs discovery
+// }
+
+ private function createMockAMQPMessage(string $body): MockInterface
+ {
+ $channelMock = Mockery::mock(AMQPChannel::class);
+
+ $msgMock = Mockery::mock(AMQPMessage::class);
+ $msgMock->body = $body;
+ $msgMock->delivery_info = [
+ 'channel' => $channelMock,
+ 'delivery_tag' => 1,
+ ];
+
+ return $msgMock;
+ }
+}
diff --git a/tests/Unit/Console/Commands/ConsumerCommandTest.php b/tests/Unit/Console/Commands/ConsumerCommandTest.php
new file mode 100644
index 0000000..e3e2fa9
--- /dev/null
+++ b/tests/Unit/Console/Commands/ConsumerCommandTest.php
@@ -0,0 +1,111 @@
+start();
+
+ sleep(1);
+ $this->assertTrue($process->isRunning());
+
+ $process->signal(SIGINT);
+
+ // Give it a moment to process the signal
+ sleep(1);
+
+ $this->assertFalse($process->isRunning());
+ $this->assertEquals(130, $process->getExitCode());
+ }
+
+ public function test_process_message_for_prop_route()
+ {
+ Mail::fake();
+
+ // Create a mock AMQPMessage for prop route
+ $msgMock = $this->createMockAMQPMessage(
+ json_encode([
+ 'email' => 'test@example.com',
+ 'name' => 'Test User',
+ 'number' => '12345',
+ 'days' => 30,
+ ]),
+ config('app.rabbitmq.route_key_prop'),
+ );
+
+ // Create a partial mock of the command
+ $command = new ConsumerCommand;
+
+ // Use reflection to call the protected method
+ $reflection = new \ReflectionClass($command);
+ $method = $reflection->getMethod('processMessage');
+ $method->setAccessible(true);
+ $method->invoke($command, $msgMock);
+
+ // Assert mail was sent
+ Mail::assertSent(EmailRegistrationOpp::class);
+ }
+
+ public function test_process_message_for_adm_route()
+ {
+ Mail::fake();
+
+ // Create a mock AMQPMessage for adm route
+ $msgMock = $this->createMockAMQPMessage(
+ json_encode([
+ 'comission' => 'comission@example.com',
+ 'owner' => 'owner@example.com',
+ 'registration' => '54321',
+ ]),
+ config('app.rabbitmq.route_key_adm')
+ );
+
+ // Create a partial mock of the command
+ $command = new ConsumerCommand;
+
+ // Use reflection to call the protected method
+ $reflection = new \ReflectionClass($command);
+ $method = $reflection->getMethod('processMessage');
+ $method->setAccessible(true);
+ $method->invoke($command, $msgMock);
+
+ // Assert mail was sent
+ Mail::assertSent(AnswerNotification::class);
+ }
+
+ /**
+ * Create a mock AMQPMessage for testing
+ */
+ private function createMockAMQPMessage(string $body, string $routingKey): MockInterface
+ {
+ $channelMock = Mockery::mock(AMQPChannel::class);
+ $channelMock->shouldReceive('basic_ack')
+ ->once()
+ ->andReturnNull();
+
+ $msgMock = Mockery::mock(AMQPMessage::class);
+ $msgMock->body = $body;
+ $msgMock->shouldReceive('getRoutingKey')
+ ->andReturn($routingKey);
+ $msgMock->delivery_info = [
+ 'channel' => $channelMock,
+ 'delivery_tag' => 1,
+ ];
+
+ return $msgMock;
+ }
+}
diff --git a/tests/Unit/ExampleTest.php b/tests/Unit/ExampleTest.php
deleted file mode 100644
index 5773b0c..0000000
--- a/tests/Unit/ExampleTest.php
+++ /dev/null
@@ -1,16 +0,0 @@
-assertTrue(true);
- }
-}
diff --git a/tests/Unit/Mail/AnswerNotificationTest.php b/tests/Unit/Mail/AnswerNotificationTest.php
new file mode 100644
index 0000000..0ba3e84
--- /dev/null
+++ b/tests/Unit/Mail/AnswerNotificationTest.php
@@ -0,0 +1,52 @@
+assertEquals($number, $mail->number);
+ }
+
+ public function test_it_has_the_correct_subject(): void
+ {
+ $mail = new AnswerNotification('12345');
+ $envelope = $mail->envelope();
+
+ $this->assertEquals('Diligência Respondida', $envelope->subject);
+ }
+
+ public function test_it_uses_the_correct_view(): void
+ {
+ $mail = new AnswerNotification('12345');
+ $content = $mail->content();
+
+ $this->assertEquals('emails.answer', $content->view);
+ }
+
+ public function test_it_has_no_attachments(): void
+ {
+ $mail = new AnswerNotification('12345');
+
+ $this->assertEmpty($mail->attachments());
+ }
+
+ public function test_it_passes_number_to_the_view(): void
+ {
+ $number = '12345';
+ $mail = new AnswerNotification($number);
+
+ $rendered = $mail->render();
+
+ // This assumes your view includes the number somewhere
+ // You may need to adjust this assertion based on your view's actual content
+ $this->assertStringContainsString($number, $rendered);
+ }
+}
diff --git a/tests/Unit/Mail/DeadlineForAccountabilityTest.php b/tests/Unit/Mail/DeadlineForAccountabilityTest.php
new file mode 100644
index 0000000..4cd9282
--- /dev/null
+++ b/tests/Unit/Mail/DeadlineForAccountabilityTest.php
@@ -0,0 +1,173 @@
+ 'REFO',
+ 'days_current' => 90,
+ ];
+
+ $mail = new DeadlineForAccountability($info);
+
+ $this->assertInstanceOf(DeadlineForAccountability::class, $mail);
+ }
+
+ public function test_it_sets_correct_envelope_subject_for_refo(): void
+ {
+ $info = (object) [
+ 'notification_type' => 'REFO',
+ 'days_current' => 90,
+ ];
+
+ $mail = new DeadlineForAccountability($info);
+ $envelope = $mail->envelope();
+
+ $this->assertInstanceOf(Envelope::class, $envelope);
+ $this->assertEquals('Mapa Cultural - Prazo para envio da prestação de contas (REFO)', $envelope->subject);
+ }
+
+ public function test_it_sets_correct_envelope_subject_for_raio(): void
+ {
+ $info = (object) [
+ 'notification_type' => 'RAIO',
+ 'days_current' => 90,
+ ];
+
+ $mail = new DeadlineForAccountability($info);
+ $envelope = $mail->envelope();
+
+ $this->assertInstanceOf(Envelope::class, $envelope);
+ $this->assertEquals('Mapa Cultural - Prazo para envio da prestação de contas (RAIO)', $envelope->subject);
+ }
+
+ public function test_it_sets_default_complement_text_when_days_current_is_not_85_or_55(): void
+ {
+ $info = (object) [
+ 'notification_type' => 'REFO',
+ 'days_current' => 90,
+ ];
+
+ $mail = new DeadlineForAccountability($info);
+
+ // Trigger content method to set complementText
+ $mail->content();
+
+ $this->assertEquals('está na hora de preencher e enviar', $mail->complementText);
+ }
+
+ public function test_it_sets_special_complement_text_when_days_current_is_85(): void
+ {
+ $info = (object) [
+ 'notification_type' => 'REFO',
+ 'days_current' => 85,
+ ];
+
+ $mail = new DeadlineForAccountability($info);
+
+ // Trigger content method to set complementText
+ $mail->content();
+
+ $this->assertEquals('faltam 05 (cinco) dias para o envio', $mail->complementText);
+ }
+
+ public function test_it_sets_special_complement_text_when_days_current_is_55(): void
+ {
+ $info = (object) [
+ 'notification_type' => 'REFO',
+ 'days_current' => 55,
+ ];
+
+ $mail = new DeadlineForAccountability($info);
+
+ // Trigger content method to set complementText
+ $mail->content();
+
+ $this->assertEquals('faltam 05 (cinco) dias para o envio', $mail->complementText);
+ }
+
+ public function test_it_sets_correct_title_report_for_refo(): void
+ {
+ $info = (object) [
+ 'notification_type' => 'REFO',
+ 'days_current' => 90,
+ ];
+
+ $mail = new DeadlineForAccountability($info);
+
+ // Trigger content method to set titleReport
+ $mail->content();
+
+ $this->assertEquals('Relatório de Execução Final do Objeto - REFO', $mail->titleReport);
+ }
+
+ public function test_it_sets_correct_title_report_for_raio(): void
+ {
+ $info = (object) [
+ 'notification_type' => 'RAIO',
+ 'days_current' => 90,
+ ];
+
+ $mail = new DeadlineForAccountability($info);
+
+ // Trigger content method to set titleReport
+ $mail->content();
+
+ $this->assertEquals('Relatório de Avaliação Intermediária do Objeto - RAIO', $mail->titleReport);
+ }
+
+ public function test_it_returns_correct_content_view(): void
+ {
+ $info = (object) [
+ 'notification_type' => 'REFO',
+ 'days_current' => 90,
+ ];
+
+ $mail = new DeadlineForAccountability($info);
+ $content = $mail->content();
+
+ $this->assertInstanceOf(Content::class, $content);
+ $this->assertEquals('emails.deadline-for-accountability', $content->view);
+ }
+
+ public function test_it_passes_correct_data_to_view(): void
+ {
+ $info = (object) [
+ 'notification_type' => 'REFO',
+ 'days_current' => 90,
+ ];
+
+ $mail = new DeadlineForAccountability($info);
+ $content = $mail->content();
+
+ $extensive = new Extensive;
+ $expectedDaysCurrent = $extensive->extensive(90, Extensive::MALE_NUMBER);
+
+ $viewData = $content->with;
+ $this->assertSame($info, $viewData['info']);
+ $this->assertEquals($expectedDaysCurrent, $viewData['days_current']);
+ $this->assertEquals('está na hora de preencher e enviar', $viewData['complement_text']);
+ $this->assertEquals('Relatório de Execução Final do Objeto - REFO', $viewData['title_report']);
+ }
+
+ public function test_it_has_no_attachments(): void
+ {
+ $info = (object) [
+ 'notification_type' => 'REFO',
+ 'days_current' => 90,
+ ];
+
+ $mail = new DeadlineForAccountability($info);
+
+ $this->assertEmpty($mail->attachments());
+ }
+}
diff --git a/tests/Unit/Mail/EmailRegistrationOppTest.php b/tests/Unit/Mail/EmailRegistrationOppTest.php
new file mode 100644
index 0000000..3f4d25b
--- /dev/null
+++ b/tests/Unit/Mail/EmailRegistrationOppTest.php
@@ -0,0 +1,90 @@
+assertEquals($nameUser, $mail->nameUser);
+ $this->assertEquals($number, $mail->number);
+ $this->assertEquals($days, $mail->days);
+ }
+
+ public function test_it_sets_correct_envelope_subject(): void
+ {
+ $mail = new EmailRegistrationOpp(
+ nameUser: 'John Doe',
+ number: '12345',
+ days: '30',
+ );
+
+ $envelope = $mail->envelope();
+
+ $this->assertInstanceOf(Envelope::class, $envelope);
+ $this->assertEquals('Diligência Aberta - Resposta Necessária', $envelope->subject);
+ }
+
+ public function test_it_uses_correct_view_template(): void
+ {
+ $mail = new EmailRegistrationOpp(
+ nameUser: 'John Doe',
+ number: '12345',
+ days: '30',
+ );
+
+ $content = $mail->content();
+
+ $this->assertInstanceOf(Content::class, $content);
+ $this->assertEquals('emails.registration', $content->view);
+ }
+
+ public function test_it_passes_properties_to_view(): void
+ {
+ $nameUser = 'John Doe';
+ $number = '12345';
+ $days = '30';
+
+ $mail = new EmailRegistrationOpp(
+ nameUser: $nameUser,
+ number: $number,
+ days: $days,
+ );
+
+ // This test confirms that the properties are accessible to the view
+ // by checking that they're public properties on the mailable
+ $this->assertTrue(property_exists($mail, 'nameUser'));
+ $this->assertTrue(property_exists($mail, 'number'));
+ $this->assertTrue(property_exists($mail, 'days'));
+
+ $this->assertEquals($nameUser, $mail->nameUser);
+ $this->assertEquals($number, $mail->number);
+ $this->assertEquals($days, $mail->days);
+ }
+
+ public function test_it_has_no_attachments(): void
+ {
+ $mail = new EmailRegistrationOpp(
+ nameUser: 'John Doe',
+ number: '12345',
+ days: '30',
+ );
+
+ $this->assertEmpty($mail->attachments());
+ }
+}
diff --git a/tests/Unit/Mail/PublishedRecourseTest.php b/tests/Unit/Mail/PublishedRecourseTest.php
new file mode 100644
index 0000000..1122e36
--- /dev/null
+++ b/tests/Unit/Mail/PublishedRecourseTest.php
@@ -0,0 +1,82 @@
+ 'Test Opportunity',
+ 'agentId' => '12345',
+ ];
+
+ $mail = new PublishedRecourse($data);
+
+ $this->assertInstanceOf(PublishedRecourse::class, $mail);
+ }
+
+ public function test_it_sets_correct_envelope_subject(): void
+ {
+ $data = [
+ 'opportunityName' => 'Test Opportunity',
+ 'agentId' => '12345',
+ ];
+
+ $mail = new PublishedRecourse($data);
+ $envelope = $mail->envelope();
+
+ $this->assertInstanceOf(Envelope::class, $envelope);
+ $this->assertEquals('Resposta do recurso publicada', $envelope->subject);
+ }
+
+ public function test_it_uses_correct_view_template(): void
+ {
+ $data = [
+ 'opportunityName' => 'Test Opportunity',
+ 'agentId' => '12345',
+ ];
+
+ $mail = new PublishedRecourse($data);
+ $content = $mail->content();
+
+ $this->assertInstanceOf(Content::class, $content);
+ $this->assertEquals('emails.published-recourse', $content->view);
+ }
+
+ public function test_it_passes_correct_data_to_view(): void
+ {
+ $opportunityName = 'Test Opportunity';
+ $agentId = '12345';
+
+ $data = [
+ 'opportunityName' => $opportunityName,
+ 'agentId' => $agentId,
+ ];
+
+ $mail = new PublishedRecourse($data);
+ $content = $mail->content();
+
+ $this->assertEquals([
+ 'opportunityName' => $opportunityName,
+ 'agentId' => $agentId,
+ ], $content->with);
+ }
+
+ public function test_it_has_no_attachments(): void
+ {
+ $data = [
+ 'opportunityName' => 'Test Opportunity',
+ 'agentId' => '12345',
+ ];
+
+ $mail = new PublishedRecourse($data);
+
+ $this->assertEmpty($mail->attachments());
+ }
+}
From d736be5feca1b93bec8e8f6db59af36548b773dc Mon Sep 17 00:00:00 2001
From: Jefferson Oliveira
Date: Mon, 28 Apr 2025 12:20:35 -0300
Subject: [PATCH 07/11] =?UTF-8?q?feat:=20comando=20de=20execu=C3=A7=C3=A3o?=
=?UTF-8?q?=20das=20filas=20no=20supervisor?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
docker/php-fpm/supervisord.conf | 10 ++++++++++
docker/prod/php-fpm/supervisord.conf | 11 ++++++++++-
2 files changed, 20 insertions(+), 1 deletion(-)
diff --git a/docker/php-fpm/supervisord.conf b/docker/php-fpm/supervisord.conf
index 4c6b060..214c70b 100644
--- a/docker/php-fpm/supervisord.conf
+++ b/docker/php-fpm/supervisord.conf
@@ -1,5 +1,6 @@
[supervisord]
nodaemon=true
+
### RODAR OS WORKS
[program:diligence_consumer]
command=php artisan diligence:consumer
@@ -15,6 +16,15 @@ 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
+autostart=true
+autorestart=true
+user=www-data
+stdout_logfile=/var/www/html/storage/logs/worker.log
+redirect_stderr=true
+
[supervisord]
nodaemon=true
user=root
diff --git a/docker/prod/php-fpm/supervisord.conf b/docker/prod/php-fpm/supervisord.conf
index aedcdce..c99b341 100644
--- a/docker/prod/php-fpm/supervisord.conf
+++ b/docker/prod/php-fpm/supervisord.conf
@@ -36,4 +36,13 @@ user=www-data
numprocs=1
priority=200
logfile_maxbytes=50MB ; Tamanho máximo do log antes de rotacionar (opcional)
-logfile_backups=5
\ No newline at end of file
+logfile_backups=5
+
+[program:accountability_queue]
+process_name=%(program_name)s
+command=php /var/www/html/artisan queue:work
+autostart=true
+autorestart=true
+user=www-data
+stdout_logfile=/var/www/html/storage/logs/worker.log
+redirect_stderr=true
From c5b68ff6537f5ce4fffeb470ba581828400811df Mon Sep 17 00:00:00 2001
From: Rafael Silva Domingos
Date: Tue, 20 May 2025 10:30:55 -0300
Subject: [PATCH 08/11] Ajustes no dockerfile para diminuir a quantidade de
camadas
---
docker/prod/php-fpm/Dockerfile | 17 +++++++----------
1 file changed, 7 insertions(+), 10 deletions(-)
diff --git a/docker/prod/php-fpm/Dockerfile b/docker/prod/php-fpm/Dockerfile
index 1ea2231..aed3a13 100644
--- a/docker/prod/php-fpm/Dockerfile
+++ b/docker/prod/php-fpm/Dockerfile
@@ -19,16 +19,13 @@ RUN apt-get update && \
libgmp-dev \
mariadb-client \
unzip \
- supervisor
-
-RUN docker-php-ext-install soap exif pcntl zip pdo_mysql pdo_pgsql bcmath intl gmp sockets
-
-RUN pecl install redis && docker-php-ext-enable redis
-RUN pecl install memcached && docker-php-ext-enable memcached
-
-RUN docker-php-ext-install gd && \
- docker-php-ext-configure gd --with-freetype --with-jpeg && \
- docker-php-ext-install gd
+ supervisor \
+ && docker-php-ext-install soap exif pcntl zip pdo_mysql pdo_pgsql bcmath intl gmp sockets \
+ && pecl install redis && docker-php-ext-enable redis \
+ && pecl install memcached \
+ && docker-php-ext-enable memcached \
+ && docker-php-ext-install gd \
+ && docker-php-ext-configure gd --with-freetype --with-jpeg
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
WORKDIR /var/www
From 70ea1420e967701316b7889146f9986b164106fc Mon Sep 17 00:00:00 2001
From: Rafael Silva Domingos
Date: Tue, 20 May 2025 11:37:04 -0300
Subject: [PATCH 09/11] =?UTF-8?q?Ajusta=20diret=C3=B3rio=20da=20aplica?=
=?UTF-8?q?=C3=A7=C3=A3o=20no=20Dockerfile?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
docker/prod/php-fpm/Dockerfile | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/docker/prod/php-fpm/Dockerfile b/docker/prod/php-fpm/Dockerfile
index aed3a13..94038b0 100644
--- a/docker/prod/php-fpm/Dockerfile
+++ b/docker/prod/php-fpm/Dockerfile
@@ -28,15 +28,15 @@ RUN apt-get update && \
&& docker-php-ext-configure gd --with-freetype --with-jpeg
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
-WORKDIR /var/www
-COPY . /var/www
+WORKDIR /var/www/html
+COPY . /var/www/html
COPY ./docker/prod/php-fpm/supervisord.conf /etc/supervisord.conf
COPY ./docker/prod/php-fpm/published.sh /etc/published.sh
COPY ./docker/prod/php-fpm/works.sh /etc/works.sh
COPY ./docker/prod/php-fpm/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
RUN composer install --no-dev --optimize-autoloader
-RUN chown -R www-data:www-data /var/www && chmod -R 755 /var/www/storage
+RUN chown -R www-data:www-data /var/www && chmod -R 755 /var/www/html/storage
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
EXPOSE 9000
From d1996b19bf822c4c99d9670c83544f76282c6186 Mon Sep 17 00:00:00 2001
From: Rafael Silva Domingos
Date: Tue, 20 May 2025 12:01:43 -0300
Subject: [PATCH 10/11] =?UTF-8?q?Cria=20arquivo=20de=20configura=C3=A7?=
=?UTF-8?q?=C3=A3o=20de=20CICD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.github/workflows/cicd | 49 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 49 insertions(+)
create mode 100644 .github/workflows/cicd
diff --git a/.github/workflows/cicd b/.github/workflows/cicd
new file mode 100644
index 0000000..9d78a83
--- /dev/null
+++ b/.github/workflows/cicd
@@ -0,0 +1,49 @@
+name: CICD
+
+on:
+ pull_request:
+ branches:
+ - main
+ types:
+ - closed
+
+ workflow_dispatch:
+
+jobs:
+ BUILD:
+ if: github.event.pull_request.merged == true
+ runs-on: ubuntu-latest
+ steps:
+
+ - uses: actions/checkout@v4.1.1
+
+ - name: Read version file
+ id: get_version
+ run: |
+ VERSION=$(cat version.txt)
+ echo "app_version=$VERSION" >> $GITHUB_ENV
+
+ - name: Docker Login
+ uses: docker/login-action@v3.0.0
+ with:
+ username: ${{ secrets.DOCKERHUB_USER }}
+ password: ${{ secrets.DOCKERHUB_PASSWORD }}
+
+ - name: Criação da Imagem docker
+ uses: docker/build-push-action@v5.0.0
+ with:
+ context: ./
+ file: ./Dockerfile
+ push: true
+ tags: |
+ secultceara/api-email:latest
+ secultceara/api-email:${{ env.app_version }}
+
+ #DEPLOY:
+ # needs: BUILD
+ # runs-on: mapahomolog
+ # steps:
+ # - name: Pull da imagem do dockerhub
+ # run: sudo docker pull secultceara/mapasculturais:homolog
+ # - name: Restart do docker-compose para atualizar o container com a nova imagem
+ # run: cd /opt/docker/mapa5 && sudo docker-compose down && sudo docker-compose up -d
\ No newline at end of file
From e225ac255cea9601b52e1b171c33c9ddbd5a4a82 Mon Sep 17 00:00:00 2001
From: Rafael Silva Domingos
Date: Tue, 20 May 2025 12:05:37 -0300
Subject: [PATCH 11/11] =?UTF-8?q?Corrige=20extens=C3=A3o=20do=20arquivo=20?=
=?UTF-8?q?de=20configura=C3=A7=C3=A3o=20do=20cicd?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.github/workflows/{cicd => cicd.yaml} | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
rename .github/workflows/{cicd => cicd.yaml} (98%)
diff --git a/.github/workflows/cicd b/.github/workflows/cicd.yaml
similarity index 98%
rename from .github/workflows/cicd
rename to .github/workflows/cicd.yaml
index 9d78a83..fc9fa4b 100644
--- a/.github/workflows/cicd
+++ b/.github/workflows/cicd.yaml
@@ -28,7 +28,7 @@ jobs:
with:
username: ${{ secrets.DOCKERHUB_USER }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
-
+
- name: Criação da Imagem docker
uses: docker/build-push-action@v5.0.0
with: