Compare commits
283 commits
resolve_er
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5634d4d232 | ||
|
|
9a1a07307b | ||
|
|
8410447a29 | ||
|
|
f0fb7a26f3 | ||
|
|
f55ca959b8 | ||
|
|
d622f543e9 | ||
|
|
1f1c684008 | ||
|
|
e8c5472d45 | ||
|
|
4ff19d9277 | ||
|
|
7dfd80cf23 | ||
|
|
e19d810a2f | ||
|
|
ab998c975d | ||
|
|
9706922312 | ||
|
|
ebb52b5968 | ||
|
|
6c783247a7 | ||
|
|
6cf790feab | ||
|
|
57c7613455 | ||
|
|
eddeb4f7f6 | ||
|
|
d9d1fea624 | ||
|
|
22d79cfb11 | ||
|
|
22bc49baab | ||
|
|
adb2a8b21c | ||
|
|
7246d7894d | ||
|
|
10b75031e7 | ||
|
|
68a48fdf5a | ||
|
|
a7debacd65 | ||
|
|
dd10d4ba3a | ||
|
|
a7bd6d6420 | ||
|
|
8cfc409d5c | ||
|
|
bc7a1020bc | ||
|
|
e828c8bf66 | ||
|
|
f28dbdd1df | ||
|
|
965226fae6 | ||
|
|
bd9b7cd32e | ||
|
|
8c67989526 | ||
|
|
2212b0ae08 | ||
|
|
c2b25c3503 | ||
|
|
f106c17588 | ||
|
|
8e9d117918 | ||
|
|
0dbb483fc4 | ||
|
|
980717f37c | ||
|
|
020fcdaa03 | ||
|
|
095f80eac1 | ||
|
|
6a973703c4 | ||
|
|
9a853088b1 | ||
|
|
0ec3be521d | ||
|
|
6854af708b | ||
|
|
8f1c920e26 | ||
|
|
efe5e8ace6 | ||
|
|
91f4773c60 | ||
|
|
6b5b4ec619 | ||
|
|
4edd92e572 | ||
|
|
da03fbe273 | ||
|
|
b7f7b7c55d | ||
|
|
49d37a8fa6 | ||
|
|
195a5fcb3e | ||
|
|
e0af4a243a | ||
|
|
0c4d376c22 | ||
|
|
6fabb998ed | ||
|
|
04bd156849 | ||
|
|
a43037d2f9 | ||
|
|
ef57fe9fe5 | ||
|
|
62901a015e | ||
|
|
004af70c30 | ||
|
|
c88f3e8d52 | ||
|
|
fb78d5a77d | ||
|
|
292456bf14 | ||
|
|
a43c6c95b1 | ||
|
|
9b2248b146 | ||
|
|
9ea4786aa8 | ||
|
|
b77c0908f6 | ||
|
|
721e2200f6 | ||
|
|
cbabb40f83 | ||
|
|
e71c0546c5 | ||
|
|
ebeccffac6 | ||
|
|
870986faa4 | ||
|
|
da65fcd12c | ||
|
|
e0e6147576 | ||
|
|
c7493abea0 | ||
|
|
95b69e9496 | ||
|
|
a3123a2bf2 | ||
|
|
33ea75a5ed | ||
|
|
3e09baf6f3 | ||
|
|
1794076c91 | ||
|
|
d5f1891764 | ||
|
|
098e40576e | ||
|
|
3b93ec45c9 | ||
|
|
3b7ca55d73 | ||
|
|
18b66793a0 | ||
|
|
7ee8a2be82 | ||
|
|
7e9cba3d2a | ||
|
|
4e275c3b37 | ||
|
|
87cc2dec86 | ||
|
|
ea41e19724 | ||
|
|
37beca9c5e | ||
|
|
7aa279e9e4 | ||
|
|
65772aeb1d | ||
|
|
ea6ac998d8 | ||
|
|
b14305553f | ||
|
|
aa9483a155 | ||
|
|
9bc3d9e5e0 | ||
|
|
f99dac8aab | ||
|
|
90f27bf560 | ||
|
|
ccc4ed596a | ||
|
|
3f4342f3bb | ||
|
|
e67e4b3cef | ||
|
|
c09214f59a | ||
|
|
950b2babdc | ||
|
|
481c732f3e | ||
|
|
887837dcaf | ||
|
|
13cc9d1394 | ||
|
|
b97f7f575e | ||
|
|
4bdcf60dfa | ||
|
|
17ee6de791 | ||
|
|
460029cf83 | ||
|
|
e54c491c2d | ||
|
|
51f77d3be8 | ||
|
|
435d5626ee | ||
|
|
50ba8eaf8a | ||
|
|
365b839f53 | ||
|
|
f2a65c85b0 | ||
|
|
1a2fe21212 | ||
|
|
4434538cc3 | ||
|
|
d702c02bdb | ||
|
|
b1a6dfb72c | ||
|
|
ec62c6d4b5 | ||
|
|
0f31e03169 | ||
|
|
849420f966 | ||
|
|
844928e945 | ||
|
|
3560e6c7f6 | ||
|
|
cc339201f0 | ||
|
|
e47d9a75e6 | ||
|
|
4d777f6281 | ||
|
|
a3529361b7 | ||
|
|
93a4d54a9e | ||
|
|
46bfa5ef1f | ||
|
|
005378de41 | ||
|
|
ed4b227f9a | ||
|
|
aa3f507483 | ||
|
|
8a34a30ab4 | ||
|
|
88abac9a5d | ||
|
|
9172d75e5d | ||
|
|
4a0c556937 | ||
|
|
085028a465 | ||
|
|
21abe7d761 | ||
|
|
f9ed83ff60 | ||
|
|
df912545e1 | ||
|
|
1ffb5e5bdd | ||
|
|
c6fcd7cfa6 | ||
|
|
8f0a139663 | ||
|
|
7ee190f1d3 | ||
|
|
3d81cd77ce | ||
|
|
fba178b598 | ||
|
|
c6e5c5eeb7 | ||
|
|
3c035aec9d | ||
|
|
1f02f86610 | ||
|
|
efb3914e4f | ||
|
|
dd230c4516 | ||
|
|
6dd7278c4f | ||
|
|
b0f4c37153 | ||
|
|
25ab578c93 | ||
|
|
2d0b300a52 | ||
|
|
52386bbfd4 | ||
|
|
748a5018af | ||
|
|
fbf4a2f96c | ||
|
|
7089b11c5f | ||
|
|
de14d846c5 | ||
|
|
d6ed7c1f04 | ||
|
|
5477affb97 | ||
|
|
77a7871f3d | ||
|
|
c63f2b62e9 | ||
|
|
4c8f5f20f7 | ||
|
|
09d84e31fb | ||
|
|
3e199d0f68 | ||
|
|
7564600ace | ||
|
|
88457bb44a | ||
|
|
ba6f7f8e7b | ||
|
|
f1eddb1cc2 | ||
|
|
7116c5d41f | ||
|
|
bc0d61d438 | ||
|
|
aa49e077bd | ||
|
|
a484335112 | ||
|
|
658fedd3eb | ||
|
|
31510149af | ||
|
|
420947f8e0 | ||
|
|
17c10a1618 | ||
|
|
fb8720d41b | ||
|
|
08afe201f8 | ||
|
|
db39f78281 | ||
|
|
ea29760b95 | ||
|
|
afd8f09d02 | ||
|
|
33cf4f1c93 | ||
|
|
83d4d5442f | ||
|
|
e66af8dc92 | ||
|
|
e595c7e145 | ||
|
|
e1944924c1 | ||
|
|
3a0cc47fa8 | ||
|
|
3a2b5a0af9 | ||
|
|
ca7057ce77 | ||
|
|
0dd283b68d | ||
|
|
7c028a4505 | ||
|
|
b21dd4d260 | ||
|
|
4838b54b4c | ||
|
|
911ee5df4b | ||
|
|
bbfd4360f2 | ||
|
|
3a51ccb0f3 | ||
|
|
1c3f20782b | ||
|
|
673494aeda | ||
|
|
1bd04e2e52 | ||
|
|
aa17aab45f | ||
|
|
ec47d2610f | ||
|
|
560ef30cd8 | ||
|
|
b2908aac9f | ||
|
|
0da4a6fa13 | ||
|
|
b6720bae3d | ||
|
|
a58bf2ff3b | ||
|
|
2b94d780b6 | ||
|
|
74edc5c785 | ||
|
|
781161c5e4 | ||
|
|
2d70ff9f29 | ||
|
|
17a01e1f7a | ||
|
|
e3d828a9e5 | ||
|
|
d17678342e | ||
|
|
b646cb41fe | ||
|
|
5bd7673a18 | ||
|
|
2faf043f68 | ||
|
|
66c889b02a | ||
|
|
74600ef3a7 | ||
|
|
35e18112b9 | ||
|
|
f10b46a012 | ||
|
|
523715a3c1 | ||
|
|
c8b4f97c88 | ||
|
|
65b92edc99 | ||
|
|
2ee245be4c | ||
|
|
766a990361 | ||
|
|
a23509fa09 | ||
|
|
6c8cc25bae | ||
|
|
3c529a7bc0 | ||
|
|
c8d179e7b3 | ||
|
|
8e4d6d4198 | ||
|
|
a3c2697c86 | ||
|
|
c6d89101b4 | ||
|
|
ad43378b52 | ||
|
|
f40f2e2aa5 | ||
|
|
b55d812aaa | ||
|
|
ab08bad87e | ||
|
|
e8b920a8cd | ||
|
|
cb779c83b8 | ||
|
|
a393b24392 | ||
|
|
cd89f6b443 | ||
|
|
d9b316eae4 | ||
|
|
722369cf61 | ||
|
|
0cc315d2ef | ||
|
|
7559a47044 | ||
|
|
55fef3421e | ||
|
|
97d8111f4b | ||
|
|
4354f6a445 | ||
|
|
abdbbae843 | ||
|
|
f150e96d39 | ||
|
|
d2324145a4 | ||
|
|
b6c74efd3d | ||
|
|
57a437db48 | ||
|
|
f3cb8e7974 | ||
|
|
91c1fe5532 | ||
|
|
29a837ff61 | ||
|
|
bbe4478c09 | ||
|
|
28ee9f593d | ||
|
|
eb2d4e5267 | ||
|
|
c19d5829e6 | ||
|
|
c1fb743e34 | ||
|
|
1d07c93799 | ||
|
|
32cb11622c | ||
|
|
911d7a2f6d | ||
|
|
32be1746b5 | ||
|
|
a5d4c58604 | ||
|
|
0d6f34b05a | ||
|
|
606ca09608 | ||
|
|
6523875860 | ||
|
|
83b7e42b90 | ||
|
|
6f20a6b8db | ||
|
|
88f3da4c92 | ||
|
|
bd3133f06c | ||
|
|
bb2cbc5ad8 |
236 changed files with 10798 additions and 3713 deletions
14
.env.example
14
.env.example
|
|
@ -30,19 +30,17 @@ MAIL_PASSWORD=null
|
||||||
MAIL_ENCRYPTION=null
|
MAIL_ENCRYPTION=null
|
||||||
MAIL_FROM_ADDRESS=noreply-sw@ldc.fr
|
MAIL_FROM_ADDRESS=noreply-sw@ldc.fr
|
||||||
MAIL_FROM_NAME="${APP_NAME}"
|
MAIL_FROM_NAME="${APP_NAME}"
|
||||||
MAIL_LIST_SERVICEWEB=equipe.web@ldc.fr
|
MAIL_LIST_SERVICEWEB=digital@ldc.fr
|
||||||
MAIL_ADMIN=equipe.web@ldc.fr
|
MAIL_ADMIN=digital@ldc.fr
|
||||||
|
|
||||||
# Sentry
|
# Sentry
|
||||||
SENTRY_LARAVEL_DSN=
|
SENTRY_LARAVEL_DSN=
|
||||||
|
|
||||||
# ADMIN SECURE
|
# UWIL ADMIN SECURE
|
||||||
# - API ENDPOINT (Optional)
|
# - LIST SEPARATED WITH ',' (Required)
|
||||||
LDC_WEB_API_ENDPOINT=
|
UWIL_ADMIN_SECURE_CIDR_LIST=""
|
||||||
# - API KEY
|
|
||||||
LDC_WEB_API_KEY=
|
|
||||||
# - LIST SEPARATED WITH ',' (Optional)
|
# - LIST SEPARATED WITH ',' (Optional)
|
||||||
LDC_WEB_CIDR_MANUAL_ALLOWED_LIST=
|
UWIL_ADMIN_SECURE_CIDR_PROJECT_ALLOWED_LIST=
|
||||||
|
|
||||||
# GITLAB API
|
# GITLAB API
|
||||||
GITLAB_URL=
|
GITLAB_URL=
|
||||||
|
|
|
||||||
4
.gitignore
vendored
4
.gitignore
vendored
|
|
@ -22,3 +22,7 @@ Homestead.yaml
|
||||||
npm-debug.log
|
npm-debug.log
|
||||||
yarn-error.log
|
yarn-error.log
|
||||||
storage/samlidp/*
|
storage/samlidp/*
|
||||||
|
.npmrc
|
||||||
|
.zshrc
|
||||||
|
.npm/
|
||||||
|
.composer/
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ include:
|
||||||
file: 'security/security.yml'
|
file: 'security/security.yml'
|
||||||
- project: 'ldc-web/shared-ci'
|
- project: 'ldc-web/shared-ci'
|
||||||
ref: 'main'
|
ref: 'main'
|
||||||
file: 'build/build.yml'
|
file: "build/docker-multistage.yml"
|
||||||
- project: 'ldc-web/shared-ci'
|
- project: 'ldc-web/shared-ci'
|
||||||
ref: 'main'
|
ref: 'main'
|
||||||
file: 'test/test.yml'
|
file: 'test/test.yml'
|
||||||
|
|
|
||||||
44
Dockerfile
44
Dockerfile
|
|
@ -1,5 +1,43 @@
|
||||||
FROM registry.s-web.fr/ldc-web/projets/ldc-web-images-docker/ldcweb-production-8.3:latest
|
FROM composer:2.9.2 AS vendor
|
||||||
COPY --chown=www-data:www-data . /app/srcs
|
|
||||||
|
ARG GITLAB_USER
|
||||||
|
ARG GITLAB_PASSWORD
|
||||||
|
|
||||||
|
COPY database/ database/
|
||||||
|
|
||||||
|
COPY composer.json composer.json
|
||||||
|
COPY composer.lock composer.lock
|
||||||
|
|
||||||
|
RUN composer config gitlab-token.lab.s-web.fr ${GITLAB_USER} ${GITLAB_PASSWORD}
|
||||||
|
RUN composer install \
|
||||||
|
--ignore-platform-reqs \
|
||||||
|
--no-interaction \
|
||||||
|
--no-plugins \
|
||||||
|
--no-scripts \
|
||||||
|
--no-dev \
|
||||||
|
--prefer-dist
|
||||||
|
|
||||||
|
FROM node:20.18 AS frontend
|
||||||
|
|
||||||
|
ARG GITLAB_PASSWORD
|
||||||
|
|
||||||
|
RUN mkdir -p /app/public/build
|
||||||
|
|
||||||
|
COPY package*.json tsconfig.json vite.config.ts .eslintrc.json .stylelintrc.json /app/
|
||||||
|
COPY resources/ /app/resources/
|
||||||
|
WORKDIR /app
|
||||||
|
RUN npm config set @uwil:registry https://lab.s-web.fr/api/v4/groups/ldc-web/-/packages/npm/
|
||||||
|
RUN npm config set -- '//lab.s-web.fr/api/v4/groups/ldc-web/-/packages/npm/:_authToken' "${GITLAB_PASSWORD}"
|
||||||
|
RUN npm ci --no-audit --no-fund --loglevel=error && npm run prod
|
||||||
|
|
||||||
|
FROM registry.s-web.fr/ldc-web/projets/ldc-web-images-docker/uwil-production-8.5:${PHP_8_5_TAG}
|
||||||
|
|
||||||
|
ARG USER=www-data
|
||||||
|
|
||||||
|
COPY --chown=${USER}:${USER} . /app/srcs
|
||||||
|
COPY --from=vendor --chown=${USER}:${USER} /app/vendor/ /app/srcs/vendor/
|
||||||
|
COPY --from=frontend --chown=${USER}:${USER} /app/public/build/ /app/srcs/public/build/
|
||||||
|
|
||||||
USER root
|
USER root
|
||||||
RUN chmod -R 755 /app/srcs/storage
|
RUN chmod -R 755 /app/srcs/storage
|
||||||
USER www-data
|
USER ${USER}
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,16 @@
|
||||||
|
|
||||||
PROD : support.uwil.fr
|
PROD : support.uwil.fr
|
||||||
|
|
||||||
|
RE7 : support-web.re7-s-web.fr
|
||||||
|
|
||||||
## Gitlab Intégration
|
## Gitlab Intégration
|
||||||
Le token de groupe pour l'intégration est valable 1 an max
|
Le token de groupe pour l'intégration est valable 11 mois
|
||||||
|
|
||||||
Il faut le renouveler ici : https://lab.s-web.fr/groups/ldc-web/projets/-/settings/access_tokens et le nommer SW Intégration
|
Il faut le renouveler ici : https://lab.s-web.fr/groups/ldc-web/projets/-/settings/access_tokens et le nommer SW Intégration
|
||||||
|
|
||||||
|
Role : Guest
|
||||||
|
Scope : api
|
||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
|
|
||||||
- App\Models\Message:booted(): investigate why this make errors on prod,
|
- App\Models\Message:booted(): investigate why this make errors on prod,
|
||||||
|
|
|
||||||
4633
_ide_helper.php
Normal file
4633
_ide_helper.php
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -20,7 +20,7 @@ class CreateUser extends Command
|
||||||
/**
|
/**
|
||||||
* The console command description.
|
* The console command description.
|
||||||
*
|
*
|
||||||
* @var string|null
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $description = 'Create a user';
|
protected $description = 'Create a user';
|
||||||
|
|
||||||
|
|
@ -34,21 +34,21 @@ class CreateUser extends Command
|
||||||
/**
|
/**
|
||||||
* The email of the new user.
|
* The email of the new user.
|
||||||
*
|
*
|
||||||
* @var string|null
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $email;
|
protected $email;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The password of the new user.
|
* The password of the new user.
|
||||||
*
|
*
|
||||||
* @var string|null
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $password;
|
protected $password;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The role of the new user.
|
* The role of the new user.
|
||||||
*
|
*
|
||||||
* @var \App\Enums\Users\RoleEnum|null
|
* @var integer
|
||||||
*/
|
*/
|
||||||
protected $role;
|
protected $role;
|
||||||
|
|
||||||
|
|
@ -59,7 +59,7 @@ class CreateUser extends Command
|
||||||
*/
|
*/
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
$this->name = "";
|
$this->name = null;
|
||||||
$this->addName();
|
$this->addName();
|
||||||
|
|
||||||
$this->email = null;
|
$this->email = null;
|
||||||
|
|
@ -72,10 +72,10 @@ class CreateUser extends Command
|
||||||
$this->addRole();
|
$this->addRole();
|
||||||
|
|
||||||
$user = new User([
|
$user = new User([
|
||||||
'name' => $this->name,
|
'name' => $this->name,
|
||||||
'email' => $this->email,
|
'email' => $this->email,
|
||||||
'password' => $this->password,
|
'password' => $this->password,
|
||||||
'role' => $this->role
|
'role' => $this->role
|
||||||
]);
|
]);
|
||||||
$user->saveOrFail();
|
$user->saveOrFail();
|
||||||
|
|
||||||
|
|
@ -90,7 +90,7 @@ class CreateUser extends Command
|
||||||
*/
|
*/
|
||||||
private function addName(): void
|
private function addName(): void
|
||||||
{
|
{
|
||||||
while (empty($this->name)) {
|
while (is_null($this->name)) {
|
||||||
try {
|
try {
|
||||||
$tmp = $this->ask('Type the wanted user name', 'Admin');
|
$tmp = $this->ask('Type the wanted user name', 'Admin');
|
||||||
$validator = Validator::make(['name' => $tmp], [
|
$validator = Validator::make(['name' => $tmp], [
|
||||||
|
|
@ -117,7 +117,7 @@ class CreateUser extends Command
|
||||||
{
|
{
|
||||||
while (is_null($this->email)) {
|
while (is_null($this->email)) {
|
||||||
try {
|
try {
|
||||||
$tmp = $this->ask('Type the wanted user email', 'equipe.web@ldc.fr');
|
$tmp = $this->ask('Type the wanted user email', 'digital@ldc.fr');
|
||||||
$validator = Validator::make(['email' => $tmp], [
|
$validator = Validator::make(['email' => $tmp], [
|
||||||
'email' => 'required|unique:users,email|email:rfc,dns'
|
'email' => 'required|unique:users,email|email:rfc,dns'
|
||||||
]);
|
]);
|
||||||
|
|
|
||||||
38
app/Console/Commands/ExportTicketsState.php
Normal file
38
app/Console/Commands/ExportTicketsState.php
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
|
use App\Jobs\ExportTicketsState as JobsExportTicketsState;
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
|
||||||
|
class ExportTicketsState extends Command
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The name and signature of the console command.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $signature = 'tickets:export-state';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The console command description.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $description = 'Export the state of tickets to a CSV file';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the console command.
|
||||||
|
*
|
||||||
|
* @return integer
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
$this->info('Running the Job, this could take some time.');
|
||||||
|
$job = new JobsExportTicketsState();
|
||||||
|
$job->handle();
|
||||||
|
$this->info('Job completed');
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -19,7 +19,7 @@ class TestMail extends Command
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $description = 'Send test email to equipe.web@ldc.fr';
|
protected $description = 'Send test email to digital@ldc.fr';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute the console command.
|
* Execute the console command.
|
||||||
|
|
@ -29,7 +29,7 @@ class TestMail extends Command
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
Mail::raw(sprintf('UWIL mail-test from %s %s', \config('app.name'), \config('app.url')), function ($msg) {
|
Mail::raw(sprintf('UWIL mail-test from %s %s', \config('app.name'), \config('app.url')), function ($msg) {
|
||||||
$msg->to('equipe.web@ldc.fr')->subject('Test Email');
|
$msg->to('digital@ldc.fr')->subject('Test Email');
|
||||||
});
|
});
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
334
app/Console/Commands/UpdateGitlabDatas.php
Normal file
334
app/Console/Commands/UpdateGitlabDatas.php
Normal file
|
|
@ -0,0 +1,334 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
|
use App\Enums\Tickets\TicketStatusEnum;
|
||||||
|
use App\Models\GitlabIssues;
|
||||||
|
use App\Models\GitlabLabels;
|
||||||
|
use App\Models\GitlabMilestones;
|
||||||
|
use App\Models\GitlabProjects;
|
||||||
|
use App\Models\Ticket;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use GrahamCampbell\GitLab\Facades\GitLab;
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
use Illuminate\Support\Facades\Cache;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
|
class UpdateGitlabDatas extends Command
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The name and signature of the console command.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $signature = 'app:update-gitlab-datas {--is-cron}';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The console command description.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $description = 'Fetch some Gitlab datas';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the console command.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function handle(): void
|
||||||
|
{
|
||||||
|
$isCron = $this->option('is-cron');
|
||||||
|
|
||||||
|
$groupId = 23;
|
||||||
|
|
||||||
|
$this->updateProjectsByGroup($groupId);
|
||||||
|
|
||||||
|
$this->updateLabelsByGroup($groupId);
|
||||||
|
|
||||||
|
$projects = GitlabProjects::all();
|
||||||
|
|
||||||
|
foreach ($projects as $project) {
|
||||||
|
$this->updateMilestonesByProject($project);
|
||||||
|
$this->updateIssuesByProject($project, $isCron);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->syncTicketStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* updateProjectsByGroup function
|
||||||
|
*
|
||||||
|
* @param integer $groupId
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function updateProjectsByGroup(int $groupId): void
|
||||||
|
{
|
||||||
|
$allProjects = [];
|
||||||
|
$page = 1;
|
||||||
|
do {
|
||||||
|
$projects = GitLab::groups()->projects($groupId, [
|
||||||
|
'order_by' => 'created_at',
|
||||||
|
'sort' => 'asc',
|
||||||
|
'per_page' => 100,
|
||||||
|
'page' => $page,
|
||||||
|
'include_subgroups' => true
|
||||||
|
]);
|
||||||
|
$allProjects = array_merge($allProjects, $projects);
|
||||||
|
$page++;
|
||||||
|
} while (!empty($projects));
|
||||||
|
|
||||||
|
$this->info(sprintf(
|
||||||
|
"Fetched %d projects in group %d.",
|
||||||
|
count($allProjects),
|
||||||
|
$groupId
|
||||||
|
));
|
||||||
|
|
||||||
|
foreach ($allProjects as $project) {
|
||||||
|
GitlabProjects::upsert(
|
||||||
|
[
|
||||||
|
'name' => $project['name'],
|
||||||
|
'url' => $project['web_url'],
|
||||||
|
'is_archived' => $project['archived'],
|
||||||
|
'gitlab_id' => $project['id']
|
||||||
|
],
|
||||||
|
['gitlab_id']
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->info("Gitlab Projects upsert complete.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* updateLabelsByGroup function
|
||||||
|
*
|
||||||
|
* @param integer $groupId
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function updateLabelsByGroup(int $groupId): void
|
||||||
|
{
|
||||||
|
$allLabels = [];
|
||||||
|
$page = 1;
|
||||||
|
do {
|
||||||
|
$labels = GitLab::groups()->labels($groupId, [
|
||||||
|
'per_page' => 100,
|
||||||
|
'page' => $page,
|
||||||
|
]);
|
||||||
|
$allLabels = array_merge($allLabels, $labels);
|
||||||
|
$page++;
|
||||||
|
} while (!empty($labels));
|
||||||
|
|
||||||
|
$this->info(sprintf(
|
||||||
|
"Fetched %d labels in group %d.",
|
||||||
|
count($allLabels),
|
||||||
|
$groupId
|
||||||
|
));
|
||||||
|
|
||||||
|
foreach ($allLabels as $project) {
|
||||||
|
GitlabLabels::upsert(
|
||||||
|
[
|
||||||
|
'name' => $project['name'],
|
||||||
|
'gitlab_id' => $project['id']
|
||||||
|
],
|
||||||
|
['gitlab_id']
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->info("Gitlab labels upsert complete.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* updateIssuesByProject function
|
||||||
|
*
|
||||||
|
* @param GitlabProjects $project
|
||||||
|
* @param boolean $isCron
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function updateIssuesByProject(GitlabProjects $project, bool $isCron = false): void
|
||||||
|
{
|
||||||
|
$projectId = $project->gitlab_id;
|
||||||
|
$allIssues = [];
|
||||||
|
$page = 1;
|
||||||
|
|
||||||
|
do {
|
||||||
|
$params = [
|
||||||
|
'order_by' => 'created_at',
|
||||||
|
'sort' => 'asc',
|
||||||
|
'per_page' => 100,
|
||||||
|
'page' => $page,
|
||||||
|
'state' => 'all',
|
||||||
|
];
|
||||||
|
if ($isCron) {
|
||||||
|
$params = array_merge($params, ['updated_after' => now()->subDay()]);
|
||||||
|
}
|
||||||
|
$issues = GitLab::projects()->issues($projectId, $params);
|
||||||
|
$allIssues = array_merge($allIssues, $issues);
|
||||||
|
$page++;
|
||||||
|
} while (!empty($issues));
|
||||||
|
|
||||||
|
$this->info(sprintf(
|
||||||
|
"Fetched %d issues in project %d.",
|
||||||
|
count($allIssues),
|
||||||
|
$projectId
|
||||||
|
));
|
||||||
|
|
||||||
|
foreach ($allIssues as $issue) {
|
||||||
|
GitlabIssues::upsert(
|
||||||
|
[
|
||||||
|
'title' => $issue['title'],
|
||||||
|
'url' => $issue['web_url'],
|
||||||
|
'estimate_time' => $issue['time_stats']['time_estimate'] ?? 0,
|
||||||
|
'spent_time' => $issue['time_stats']['total_time_spent'] ?? 0,
|
||||||
|
'is_closed' => $issue['state'] === 'closed',
|
||||||
|
'gitlab_id' => $issue['id'],
|
||||||
|
'gitlab_iid' => $issue['iid'],
|
||||||
|
'milestone_iid' => $issue['milestone']['iid'] ?? null,
|
||||||
|
'gitlab_project_id' => $projectId,
|
||||||
|
'g_created_at' => Carbon::parse($issue['created_at'])->format('Y-m-d'),
|
||||||
|
'g_updated_at' => Carbon::parse($issue['updated_at'])->format('Y-m-d'),
|
||||||
|
'g_closed_at' => !is_null($issue['closed_at'])
|
||||||
|
? Carbon::parse($issue['closed_at'])->format('Y-m-d')
|
||||||
|
: null,
|
||||||
|
'g_due_date' => !is_null($issue['due_date'])
|
||||||
|
? Carbon::parse($issue['due_date'])->format('Y-m-d')
|
||||||
|
: null
|
||||||
|
],
|
||||||
|
['gitlab_id']
|
||||||
|
);
|
||||||
|
|
||||||
|
$issueModel = GitlabIssues::where('gitlab_id', $issue['id'])->firstOrFail();
|
||||||
|
$labelIds = [];
|
||||||
|
|
||||||
|
foreach ($issue['labels'] as $labelName) {
|
||||||
|
$label = Cache::remember("gitlab_label_{$labelName}", 300, function () use ($labelName) {
|
||||||
|
return GitlabLabels::where('name', $labelName)->first();
|
||||||
|
});
|
||||||
|
|
||||||
|
if ($label) {
|
||||||
|
$labelIds[] = $label;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$issueModel->gitlabLabels()->sync($labelIds);
|
||||||
|
}//end foreach
|
||||||
|
|
||||||
|
$this->info("Gitlab issues upsert complete.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* updateMilestonesByProject function
|
||||||
|
*
|
||||||
|
* @param GitlabProjects $project
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function updateMilestonesByProject(GitlabProjects $project): void
|
||||||
|
{
|
||||||
|
$projectId = $project->gitlab_id;
|
||||||
|
$allMilestones = [];
|
||||||
|
$page = 1;
|
||||||
|
|
||||||
|
do {
|
||||||
|
$milestones = [];
|
||||||
|
|
||||||
|
try {
|
||||||
|
$milestones = GitLab::milestones()->all($projectId, [
|
||||||
|
'per_page' => 100,
|
||||||
|
'page' => $page
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
if ($e->getCode() === 404) {
|
||||||
|
if ($project->delete()) {
|
||||||
|
Log::warning(sprintf(
|
||||||
|
"Project not found (%s), it has been deleted.",
|
||||||
|
$projectId
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
Log::warning(sprintf(
|
||||||
|
"Project not found (%s).",
|
||||||
|
$projectId
|
||||||
|
));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log::error(sprintf(
|
||||||
|
'API Error for project %s, Message: %d',
|
||||||
|
$projectId,
|
||||||
|
$e->getMessage()
|
||||||
|
));
|
||||||
|
report($e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$allMilestones = array_merge($allMilestones, $milestones);
|
||||||
|
$page++;
|
||||||
|
} while (!empty($milestones));
|
||||||
|
|
||||||
|
$this->info(sprintf(
|
||||||
|
"Fetched %d milestones in project %d.",
|
||||||
|
count($allMilestones),
|
||||||
|
$projectId
|
||||||
|
));
|
||||||
|
|
||||||
|
foreach ($allMilestones as $milestone) {
|
||||||
|
GitlabMilestones::upsert(
|
||||||
|
[
|
||||||
|
'title' => $milestone['title'],
|
||||||
|
'url' => $milestone['web_url'],
|
||||||
|
'is_closed' => $milestone['state'] === 'closed',
|
||||||
|
'gitlab_id' => $milestone['id'],
|
||||||
|
'gitlab_iid' => $milestone['iid'],
|
||||||
|
'gitlab_project_id' => $projectId,
|
||||||
|
'g_created_at' => Carbon::parse($milestone['created_at'])->format('Y-m-d'),
|
||||||
|
'g_updated_at' => Carbon::parse($milestone['updated_at'])->format('Y-m-d'),
|
||||||
|
'g_start_date' => !is_null($milestone['start_date'])
|
||||||
|
? Carbon::parse($milestone['start_date'])->format('Y-m-d')
|
||||||
|
: null,
|
||||||
|
'g_due_date' => !is_null($milestone['due_date'])
|
||||||
|
? Carbon::parse($milestone['due_date'])->format('Y-m-d')
|
||||||
|
: null
|
||||||
|
],
|
||||||
|
['gitlab_id']
|
||||||
|
);
|
||||||
|
}//end foreach
|
||||||
|
|
||||||
|
$this->info("Gitlab milestones upsert complete.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronizes ticket statuses based on GitLab issue labels.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function syncTicketStatus(): void
|
||||||
|
{
|
||||||
|
$tickets = Ticket::whereNotNull('gitlab_issue')->whereNot('status', TicketStatusEnum::archived)->get();
|
||||||
|
|
||||||
|
foreach ($tickets as $ticket) {
|
||||||
|
$gitlabIssue = GitlabIssues::where('url', $ticket->gitlab_issue)->with('gitlabLabels')->first();
|
||||||
|
|
||||||
|
$gitlabIssueLabels = $gitlabIssue ? $gitlabIssue->gitlabLabels->pluck('name') : [];
|
||||||
|
|
||||||
|
if ($gitlabIssueLabels) {
|
||||||
|
match (true) {
|
||||||
|
$gitlabIssueLabels->contains('g-wip') => $this->updateTicketStatus($ticket, TicketStatusEnum::inDev),
|
||||||
|
$gitlabIssueLabels->contains('g-production') => $this->updateTicketStatus($ticket, TicketStatusEnum::production),
|
||||||
|
default => null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the ticket status only if it has changed.
|
||||||
|
*
|
||||||
|
* @param Ticket $ticket The ticket to update.
|
||||||
|
* @param TicketStatusEnum $status The new status to apply.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function updateTicketStatus(Ticket $ticket, TicketStatusEnum $status): void
|
||||||
|
{
|
||||||
|
if ($ticket->status !== $status && $ticket->status !== TicketStatusEnum::waiting) {
|
||||||
|
$ticket->status = $status;
|
||||||
|
$ticket->saveOrFail();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
namespace App\Console;
|
namespace App\Console;
|
||||||
|
|
||||||
use App\Jobs\AutoCloseOldTickets;
|
use App\Jobs\AutoCloseOldTickets;
|
||||||
|
use App\Jobs\ExportTicketsState;
|
||||||
use App\Jobs\WarnBeforeAutoCloseTicket;
|
use App\Jobs\WarnBeforeAutoCloseTicket;
|
||||||
use Illuminate\Console\Scheduling\Schedule;
|
use Illuminate\Console\Scheduling\Schedule;
|
||||||
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
||||||
|
|
@ -24,8 +25,10 @@ class Kernel extends ConsoleKernel
|
||||||
*/
|
*/
|
||||||
protected function schedule(Schedule $schedule)
|
protected function schedule(Schedule $schedule)
|
||||||
{
|
{
|
||||||
|
$schedule->job(ExportTicketsState::class)->weekly()->fridays()->at('14:00');
|
||||||
$schedule->job(AutoCloseOldTickets::class)->dailyAt('08:00');
|
$schedule->job(AutoCloseOldTickets::class)->dailyAt('08:00');
|
||||||
$schedule->job(WarnBeforeAutoCloseTicket::class)->dailyAt('08:05');
|
$schedule->job(WarnBeforeAutoCloseTicket::class)->dailyAt('08:05');
|
||||||
|
$schedule->command('app:update-gitlab-datas --is-cron')->hourly()->between('7:00', '19:00');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
13
app/Dto/BrevoWebHookDto.php
Normal file
13
app/Dto/BrevoWebHookDto.php
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Dto;
|
||||||
|
|
||||||
|
final readonly class BrevoWebHookDto
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public readonly string $plainTextContent,
|
||||||
|
public readonly ?string $brand
|
||||||
|
) {}
|
||||||
|
}
|
||||||
|
|
@ -12,12 +12,10 @@ enum AccountTypeEnum: int
|
||||||
case seo = 1;
|
case seo = 1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optionnal labels definition.
|
* Optionnal labels definition
|
||||||
*
|
|
||||||
* @phpstan-ignore-next-line
|
|
||||||
*/
|
*/
|
||||||
private const LABELS = [
|
private const LABELS = [
|
||||||
self::development->name => "Jours de développement",
|
self::development->name => "Jours de développement",
|
||||||
self::seo->name => "Jours de seo",
|
self::seo->name => "Jours de seo",
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,12 +12,10 @@ enum BalanceOperationEnum: int
|
||||||
case debit = 1;
|
case debit = 1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optionnal labels definition.
|
* Optionnal labels definition
|
||||||
*
|
|
||||||
* @phpstan-ignore-next-line
|
|
||||||
*/
|
*/
|
||||||
private const LABELS = [
|
private const LABELS = [
|
||||||
self::credit->name => "Créditer un compte",
|
self::credit->name => "Créditer un compte",
|
||||||
self::debit->name => "Débiter un compte",
|
self::debit->name => "Débiter un compte",
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,13 +13,11 @@ enum EstimationStatusEnum: int
|
||||||
case refused = 2;
|
case refused = 2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optionnal labels definition.
|
* Optionnal labels definition
|
||||||
*
|
|
||||||
* @phpstan-ignore-next-line
|
|
||||||
*/
|
*/
|
||||||
private const LABELS = [
|
private const LABELS = [
|
||||||
self::pending->name => "En attente",
|
self::pending->name => "En attente",
|
||||||
self::accepted->name => "Acceptée",
|
self::accepted->name => "Acceptée",
|
||||||
self::refused->name => "Refusée",
|
self::refused->name => "Refusée",
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
49
app/Enums/Credit/EstimationTimeEnum.php
Normal file
49
app/Enums/Credit/EstimationTimeEnum.php
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Enums\Credit;
|
||||||
|
|
||||||
|
use App\Traits\Enums\BaseEnum;
|
||||||
|
|
||||||
|
enum EstimationTimeEnum: int
|
||||||
|
{
|
||||||
|
use BaseEnum;
|
||||||
|
|
||||||
|
case halfHour = 0.0625;
|
||||||
|
case hour = 0.125;
|
||||||
|
case hourAndHalf = 0.1875;
|
||||||
|
case twoHours = 0.25;
|
||||||
|
case twoHoursAndHalf = 0.3125;
|
||||||
|
case threeHours = 0.375;
|
||||||
|
case threeHoursAndHalf = 0.4375;
|
||||||
|
case fourHours = 0.5;
|
||||||
|
case fourHoursAndHalf = 0.5625;
|
||||||
|
case fiveHours = 0.625;
|
||||||
|
case fiveHoursAndHalf = 0.6875;
|
||||||
|
case sixHours = 0.75;
|
||||||
|
case sixHoursAndHalf = 0.8125;
|
||||||
|
case sevenHours = 0.875;
|
||||||
|
case sevenHoursAndHalf = 0.9375;
|
||||||
|
case eightHours = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optionnal labels definition
|
||||||
|
*/
|
||||||
|
private const LABELS = [
|
||||||
|
self::halfHour->name => "Une demi-heure",
|
||||||
|
self::hour->name => "Une heure",
|
||||||
|
self::hourAndHalf->name => "Une heure et demie",
|
||||||
|
self::twoHours->name => "Deux heures",
|
||||||
|
self::twoHoursAndHalf->name => "Deux heures et demie",
|
||||||
|
self::threeHours->name => "Trois heures",
|
||||||
|
self::twoHoursAndHalf->name => "Trois heures et demie",
|
||||||
|
self::fourHours->name => "Quatre heures",
|
||||||
|
self::fourHoursAndHalf->name => "Quatre heures et demie",
|
||||||
|
self::fiveHours->name => "Cinq heures",
|
||||||
|
self::fiveHoursAndHalf->name => "Cinq heures et demie",
|
||||||
|
self::sixHours->name => "Six heures",
|
||||||
|
self::sixHoursAndHalf->name => "Six heures et demie",
|
||||||
|
self::sevenHours->name => "Sept heures",
|
||||||
|
self::sevenHoursAndHalf->name => "Sept heures et demi",
|
||||||
|
self::eightHours->name => "Huit heures",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
@ -18,21 +18,21 @@ enum InfoColorsEnum: int
|
||||||
case dark = 7;
|
case dark = 7;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optionnal labels definition.
|
* Optionnal labels definition
|
||||||
*/
|
*/
|
||||||
private const CLASSES = [
|
private const CLASSES = [
|
||||||
self::primary->name => "primary",
|
self::primary->name => "primary",
|
||||||
self::secondary->name => "secondary",
|
self::secondary->name => "secondary",
|
||||||
self::success->name => "success",
|
self::success->name => "success",
|
||||||
self::danger->name => "danger",
|
self::danger->name => "danger",
|
||||||
self::warning->name => "warning",
|
self::warning->name => "warning",
|
||||||
self::info->name => "info",
|
self::info->name => "info",
|
||||||
self::light->name => "light",
|
self::light->name => "light",
|
||||||
self::dark->name => "dark",
|
self::dark->name => "dark",
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get Class.
|
* Get Class
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
|
|
@ -42,7 +42,7 @@ enum InfoColorsEnum: int
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get enum classes.
|
* Get enum classes
|
||||||
*
|
*
|
||||||
* @return array<string>
|
* @return array<string>
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -8,20 +8,22 @@ enum InvoiceStatusEnum: int
|
||||||
{
|
{
|
||||||
use BaseEnum;
|
use BaseEnum;
|
||||||
|
|
||||||
case opened = 1;
|
case opened = 1;
|
||||||
case refused = 2;
|
case refused = 2;
|
||||||
case canceled = 3;
|
case canceled = 3;
|
||||||
case archived = 4;
|
case archived = 4;
|
||||||
|
case awaiting_signature = 5;
|
||||||
|
case awaiting_invoicing = 6;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optionnal labels definition.
|
* Optionnal labels definition.
|
||||||
*
|
|
||||||
* @phpstan-ignore-next-line
|
|
||||||
*/
|
*/
|
||||||
private const LABELS = [
|
private const LABELS = [
|
||||||
self::opened->name => "Ouvert (nouveaux ou en cours)",
|
self::opened->name => "Ouvert (nouveaux ou en cours)",
|
||||||
self::refused->name => "Refusé (par le client ou aucune réponse de sa part)",
|
self::refused->name => "Refusé (par le client ou aucune réponse de sa part)",
|
||||||
self::canceled->name => "Annulé (supprimé)",
|
self::canceled->name => "Annulé (supprimé)",
|
||||||
self::archived->name => "Archivé (validé et envoyé à la comptabilité)",
|
self::archived->name => "Archivé (validé et envoyé à la comptabilité)",
|
||||||
|
self::awaiting_signature->name => "En attente de signature",
|
||||||
|
self::awaiting_invoicing->name => "En attente de facturation",
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,43 +14,41 @@ enum TaskTypeEnum: int
|
||||||
case arbitrary = 4;
|
case arbitrary = 4;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optionnal labels definition.
|
* Optionnal labels definition
|
||||||
*
|
|
||||||
* @phpstan-ignore-next-line
|
|
||||||
*/
|
*/
|
||||||
private const LABELS = [
|
private const LABELS = [
|
||||||
self::web->name => "Web",
|
self::web->name => "Web",
|
||||||
self::seo->name => "SEO",
|
self::seo->name => "SEO",
|
||||||
self::package->name => "Forfait",
|
self::package->name => "Forfait",
|
||||||
self::arbitrary->name => "Libre",
|
self::arbitrary->name => "Libre",
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Custom added prices definition.
|
* Custom added prices definition
|
||||||
*/
|
*/
|
||||||
private const PRICES = [
|
private const PRICES = [
|
||||||
self::web->name => 600,
|
self::web->name => 600,
|
||||||
self::seo->name => 690,
|
self::seo->name => 690,
|
||||||
// * Linked to packages table
|
// * Linked to packages table
|
||||||
self::package->name => 0,
|
self::package->name => 0,
|
||||||
// * Arbitrary number
|
// * Arbitrary number
|
||||||
self::arbitrary->name => 0,
|
self::arbitrary->name => 0,
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get Price.
|
* Get Price
|
||||||
*
|
*
|
||||||
* @return integer
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function price(): int
|
public function price(): string
|
||||||
{
|
{
|
||||||
return self::PRICES[$this->name];
|
return self::PRICES[$this->name];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get enum prices.
|
* Get enum prices
|
||||||
*
|
*
|
||||||
* @return array<string, int>
|
* @return array<string>
|
||||||
*/
|
*/
|
||||||
public static function toPrices(): array
|
public static function toPrices(): array
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -12,12 +12,10 @@ enum MessageTypeEnum: int
|
||||||
case public = 2;
|
case public = 2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optionnal labels definition.
|
* Optionnal labels definition
|
||||||
*
|
|
||||||
* @phpstan-ignore-next-line
|
|
||||||
*/
|
*/
|
||||||
private const LABELS = [
|
private const LABELS = [
|
||||||
self::private->name => "Privé",
|
self::private->name => "Privé",
|
||||||
self::public->name => "Public",
|
self::public->name => "Public",
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ namespace App\Enums\Tickets;
|
||||||
|
|
||||||
use App\Traits\Enums\BaseEnum;
|
use App\Traits\Enums\BaseEnum;
|
||||||
|
|
||||||
enum TicketFileTypeEnum: string
|
enum TicketFileTypeEnum: int
|
||||||
{
|
{
|
||||||
use BaseEnum;
|
use BaseEnum;
|
||||||
|
|
||||||
|
|
@ -16,11 +16,10 @@ enum TicketFileTypeEnum: string
|
||||||
case docx = '.docx';
|
case docx = '.docx';
|
||||||
case xlsx = '.xlsx';
|
case xlsx = '.xlsx';
|
||||||
case csv = '.csv';
|
case csv = '.csv';
|
||||||
|
case svg = '.svg';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optionnal labels definition.
|
* Optionnal labels definition
|
||||||
*
|
|
||||||
* @phpstan-ignore-next-line
|
|
||||||
*/
|
*/
|
||||||
private const LABELS = [
|
private const LABELS = [
|
||||||
self::png->name => "Fichier png",
|
self::png->name => "Fichier png",
|
||||||
|
|
@ -31,10 +30,11 @@ enum TicketFileTypeEnum: string
|
||||||
self::docx->name => "Fichier docx",
|
self::docx->name => "Fichier docx",
|
||||||
self::xlsx->name => "Fichier xlsx",
|
self::xlsx->name => "Fichier xlsx",
|
||||||
self::csv->name => "Fichier csv",
|
self::csv->name => "Fichier csv",
|
||||||
|
self::svg->name => "Fichier svg",
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Custom added mimes type definition.
|
* Custom added mimes type definition
|
||||||
*/
|
*/
|
||||||
private const MIMETYPE = [
|
private const MIMETYPE = [
|
||||||
self::png->name => 'image/png',
|
self::png->name => 'image/png',
|
||||||
|
|
@ -45,10 +45,11 @@ enum TicketFileTypeEnum: string
|
||||||
self::docx->name => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
self::docx->name => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||||
self::xlsx->name => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
self::xlsx->name => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||||
self::csv->name => 'text/csv',
|
self::csv->name => 'text/csv',
|
||||||
|
self::svg->name => 'image/svg+xml',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get Class.
|
* Get Class
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
|
|
@ -58,7 +59,7 @@ enum TicketFileTypeEnum: string
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get enum classes.
|
* Get enum classes
|
||||||
*
|
*
|
||||||
* @return array<string>
|
* @return array<string>
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -17,41 +17,42 @@ enum TicketStatusEnum: int
|
||||||
case recetteValidated = 7;
|
case recetteValidated = 7;
|
||||||
case production = 8;
|
case production = 8;
|
||||||
case archived = 9;
|
case archived = 9;
|
||||||
|
case inDev = 10;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optionnal labels definition.
|
* Optionnal labels definition
|
||||||
*
|
|
||||||
* @phpstan-ignore-next-line
|
|
||||||
*/
|
*/
|
||||||
private const LABELS = [
|
private const LABELS = [
|
||||||
self::new->name => "Nouveau",
|
self::new->name => "Nouveau",
|
||||||
self::estimateTodo->name => "Étude chef(s) de projet",
|
self::estimateTodo->name => "Étude chef(s) de projet",
|
||||||
self::takenInAccount->name => "Pris en compte",
|
self::takenInAccount->name => "À planifier",
|
||||||
self::waiting->name => "En attente de réponse",
|
self::waiting->name => "En attente de réponse",
|
||||||
self::waitingValidation->name => "En attente de validation",
|
self::waitingValidation->name => "En attente de validation",
|
||||||
self::recette->name => "En recettage",
|
self::recette->name => "En recettage",
|
||||||
self::recetteValidated->name => "Recettage validé",
|
self::recetteValidated->name => "Recettage validé",
|
||||||
self::production->name => "En production",
|
self::production->name => "En production",
|
||||||
self::archived->name => "Archivé",
|
self::archived->name => "Archivé",
|
||||||
|
self::inDev->name => "En cours de développement",
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Custom added classes definition.
|
* Custom added classes definition
|
||||||
*/
|
*/
|
||||||
private const CLASSES = [
|
private const CLASSES = [
|
||||||
self::new->name => 'text-danger',
|
self::new->name => 'text-danger',
|
||||||
self::estimateTodo->name => 'text-info',
|
self::estimateTodo->name => 'text-info',
|
||||||
self::takenInAccount->name => 'text-info',
|
self::takenInAccount->name => 'text-info',
|
||||||
self::waiting->name => 'text-white bg-danger',
|
self::waiting->name => 'text-white bg-danger',
|
||||||
self::waitingValidation->name => 'text-warning bg-danger',
|
self::waitingValidation->name => 'text-warning bg-danger',
|
||||||
self::recette->name => 'text-primary',
|
self::recette->name => 'text-primary',
|
||||||
self::recetteValidated->name => 'text-success',
|
self::recetteValidated->name => 'text-success',
|
||||||
self::production->name => 'text-success',
|
self::production->name => 'text-success',
|
||||||
self::archived->name => 'text-secondary',
|
self::archived->name => 'text-secondary',
|
||||||
|
self::inDev->name => 'text-discovery',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get Class.
|
* Get Class
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
|
|
@ -61,7 +62,7 @@ enum TicketStatusEnum: int
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get enum classes.
|
* Get enum classes
|
||||||
*
|
*
|
||||||
* @return array<string>
|
* @return array<string>
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -14,31 +14,35 @@ enum TicketTypeEnum: int
|
||||||
case newsletter = 4;
|
case newsletter = 4;
|
||||||
case qrcode = 5;
|
case qrcode = 5;
|
||||||
case advice = 6;
|
case advice = 6;
|
||||||
|
case complaints = 7;
|
||||||
|
case mailing = 8;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optionnal labels definition.
|
* Optionnal labels definition
|
||||||
*
|
|
||||||
* @phpstan-ignore-next-line
|
|
||||||
*/
|
*/
|
||||||
private const LABELS = [
|
private const LABELS = [
|
||||||
self::bug->name => "Bug",
|
self::bug->name => "Bug",
|
||||||
self::evolution->name => "Évolution",
|
self::evolution->name => "Évolution",
|
||||||
self::br->name => "Demande BR",
|
self::br->name => "Demande BR",
|
||||||
self::newsletter->name => "Demande newsletter",
|
self::newsletter->name => "Demande newsletter",
|
||||||
self::qrcode->name => "Demande de QR Code",
|
self::qrcode->name => "Demande de QR Code",
|
||||||
self::advice->name => "Conseil - Accompagnement",
|
self::advice->name => "Conseil - Accompagnement",
|
||||||
|
self::complaints->name => "Réclamations consommateurs",
|
||||||
|
self::mailing->name => "Demande mail en masse",
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Custom added classes definition
|
* Custom added classes definition
|
||||||
*/
|
*/
|
||||||
private const CLASSES = [
|
private const CLASSES = [
|
||||||
self::bug->name => "bg-danger",
|
self::bug->name => "bg-danger",
|
||||||
self::evolution->name => "bg-success",
|
self::evolution->name => "bg-success",
|
||||||
self::br->name => "bg-primary",
|
self::br->name => "bg-primary",
|
||||||
self::newsletter->name => "bg-warning",
|
self::newsletter->name => "bg-warning",
|
||||||
self::qrcode->name => "bg-secondary",
|
self::qrcode->name => "bg-secondary",
|
||||||
self::advice->name => "bg-info",
|
self::advice->name => "bg-info",
|
||||||
|
self::complaints->name => "bg-dark",
|
||||||
|
self::mailing->name => "bg-discovery",
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Enums\Users;
|
|
||||||
|
|
||||||
use App\Traits\Enums\BaseEnum;
|
|
||||||
|
|
||||||
enum GitlabUsersEnum: int
|
|
||||||
{
|
|
||||||
use BaseEnum;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Each user is associated to his ID on gitlab.
|
|
||||||
*
|
|
||||||
* 24 is Nicolas Demangeat
|
|
||||||
*/
|
|
||||||
case default = 24;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Optionnal labels definition.
|
|
||||||
*
|
|
||||||
* @phpstan-ignore-next-line
|
|
||||||
*/
|
|
||||||
private const LABELS = [
|
|
||||||
self::default->name => "Default",
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
@ -13,13 +13,11 @@ enum RoleEnum: int
|
||||||
case client = 2;
|
case client = 2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optionnal labels definition.
|
* Optionnal labels definition
|
||||||
*
|
|
||||||
* @phpstan-ignore-next-line
|
|
||||||
*/
|
*/
|
||||||
private const LABELS = [
|
private const LABELS = [
|
||||||
self::developper->name => "Developpeur",
|
self::developper->name => "Developpeur",
|
||||||
self::admin->name => "Administrateur",
|
self::admin->name => "Administrateur",
|
||||||
self::client->name => "Client",
|
self::client->name => "Client",
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
30
app/Events/BrevoWebhookCallReceived.php
Normal file
30
app/Events/BrevoWebhookCallReceived.php
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Events;
|
||||||
|
|
||||||
|
use Domain\Models\ValueObjects\Email;
|
||||||
|
use Illuminate\Broadcasting\PrivateChannel;
|
||||||
|
use Illuminate\Foundation\Events\Dispatchable;
|
||||||
|
|
||||||
|
readonly class BrevoWebhookCallReceived
|
||||||
|
{
|
||||||
|
use Dispatchable;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
public Email $from,
|
||||||
|
public Email $to,
|
||||||
|
public string $htmlRawContent
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the channels the event should broadcast on.
|
||||||
|
*
|
||||||
|
* @return array<int, \Illuminate\Broadcasting\Channel>
|
||||||
|
*/
|
||||||
|
public function broadcastOn(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
new PrivateChannel('default'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
34
app/Events/TicketCreated.php
Normal file
34
app/Events/TicketCreated.php
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Events;
|
||||||
|
|
||||||
|
use App\Models\Site;
|
||||||
|
use App\Models\Ticket;
|
||||||
|
use Illuminate\Broadcasting\PrivateChannel;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Foundation\Events\Dispatchable;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
class TicketCreated implements ShouldQueue
|
||||||
|
{
|
||||||
|
use Dispatchable;
|
||||||
|
use SerializesModels;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
public readonly Site $siteReceivingTicket,
|
||||||
|
public readonly Ticket $ticket,
|
||||||
|
public readonly string $byUserName
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the channels the event should broadcast on.
|
||||||
|
*
|
||||||
|
* @return array<int, \Illuminate\Broadcasting\Channel>
|
||||||
|
*/
|
||||||
|
public function broadcastOn(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
new PrivateChannel('default'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -15,7 +15,7 @@ class TicketStatusChanged
|
||||||
use InteractsWithSockets;
|
use InteractsWithSockets;
|
||||||
use SerializesModels;
|
use SerializesModels;
|
||||||
|
|
||||||
/** @var \App\Models\Ticket */
|
/** @var \App\Models\Site */
|
||||||
public $ticket;
|
public $ticket;
|
||||||
|
|
||||||
/** @var \App\Models\User */
|
/** @var \App\Models\User */
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ class Handler extends ExceptionHandler
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function register(): void
|
public function register()
|
||||||
{
|
{
|
||||||
$this->reportable(function (\Throwable $e) {
|
$this->reportable(function (\Throwable $e) {
|
||||||
if (app()->bound('sentry')) {
|
if (app()->bound('sentry')) {
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ class ForgotPasswordController extends Controller
|
||||||
use SendsPasswordResetEmails;
|
use SendsPasswordResetEmails;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ForgotPasswordController.
|
* ForgotPasswordController
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -23,11 +23,11 @@ class ResetPasswordController extends Controller
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
protected function rules(): array
|
protected function rules()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'token' => 'required',
|
'token' => 'required',
|
||||||
'email' => 'required|email',
|
'email' => 'required|email',
|
||||||
'password' => [
|
'password' => [
|
||||||
'required', 'confirmed', Password::min(8)
|
'required', 'confirmed', Password::min(8)
|
||||||
->mixedCase()
|
->mixedCase()
|
||||||
|
|
|
||||||
58
app/Http/Controllers/Bo/BrevoWebhookController.php
Normal file
58
app/Http/Controllers/Bo/BrevoWebhookController.php
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Bo;
|
||||||
|
|
||||||
|
use App\Events\BrevoWebhookCallReceived;
|
||||||
|
use App\Http\Requests\Bo\BrevoWebhookRequest;
|
||||||
|
use Domain\Models\ValueObjects\Email;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
use Illuminate\Routing\Controller as BaseController;
|
||||||
|
use \Illuminate\Contracts\Events\Dispatcher;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Http\Response;
|
||||||
|
|
||||||
|
class BrevoWebhookController extends BaseController
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly LoggerInterface $logger,
|
||||||
|
private readonly Dispatcher $dispatcher
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function webhookCallReceived(BrevoWebhookRequest $request): JsonResponse
|
||||||
|
{
|
||||||
|
$fromEmail = $request->getFromAddress();
|
||||||
|
$toEmail = $request->getToAddress();
|
||||||
|
$formContent = $request->getRawHtmlBody();
|
||||||
|
|
||||||
|
if (!$this->isFromLdc($fromEmail)) {
|
||||||
|
$this->logger->warning(
|
||||||
|
'Received a brevo webhook call from a non ldc email.',
|
||||||
|
[
|
||||||
|
'from' => $fromEmail,
|
||||||
|
'to' => $toEmail,
|
||||||
|
'content' => base64_encode($formContent)
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
return response()->json(
|
||||||
|
['ok' => false],
|
||||||
|
Response::HTTP_BAD_REQUEST
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->dispatcher->dispatch(
|
||||||
|
new BrevoWebhookCallReceived(
|
||||||
|
from: $fromEmail,
|
||||||
|
to: $toEmail,
|
||||||
|
htmlRawContent: $formContent,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return response()->json(['ok' => true]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function isFromLdc(Email $email): bool
|
||||||
|
{
|
||||||
|
return substr(strrchr($email->value, "@"), 1) === 'ldc.fr';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -7,7 +7,6 @@ use App\Http\Requests\Bo\CreditAccounts\StoreCreditAccountRequest;
|
||||||
use App\Models\Brand;
|
use App\Models\Brand;
|
||||||
use App\Models\Credit\Account;
|
use App\Models\Credit\Account;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Auth;
|
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
|
|
@ -22,11 +21,13 @@ class AccountController extends Controller
|
||||||
public function index(Request $request): \Illuminate\Contracts\View\View
|
public function index(Request $request): \Illuminate\Contracts\View\View
|
||||||
{
|
{
|
||||||
/** @var \App\Models\User $user */
|
/** @var \App\Models\User $user */
|
||||||
$user = Auth::user();
|
$user = auth()->user();
|
||||||
|
|
||||||
$brandModels = (!$user->isAdmin())
|
if (!$user->isAdmin()) {
|
||||||
? $user->brands()->pluck('id')
|
$brandModels = $user->brands()->pluck('id');
|
||||||
: $request->brand ?? Brand::query()->pluck('id');
|
} else {
|
||||||
|
$brandModels = $request->brand ?? Brand::all()->pluck('id');
|
||||||
|
}
|
||||||
|
|
||||||
/** @var \Illuminate\Database\Eloquent\Builder $credit_accountModels */
|
/** @var \Illuminate\Database\Eloquent\Builder $credit_accountModels */
|
||||||
$credit_accountModels = Account::query()->whereIn('brand_id', $brandModels);
|
$credit_accountModels = Account::query()->whereIn('brand_id', $brandModels);
|
||||||
|
|
@ -61,14 +62,14 @@ class AccountController extends Controller
|
||||||
/**
|
/**
|
||||||
* Show the form for creating a new resource.
|
* Show the form for creating a new resource.
|
||||||
*
|
*
|
||||||
* @param \App\Models\Brand $brand
|
* @param \App\Models\Brand $brand
|
||||||
* @param \App\Models\Credit\Account $account
|
* @param \App\Models\Account $account
|
||||||
* @return \Illuminate\Contracts\View\View
|
* @return \Illuminate\Contracts\View\View
|
||||||
*/
|
*/
|
||||||
public function create(Brand $brand, Account $account): \Illuminate\Contracts\View\View
|
public function create(Brand $brand, Account $account): \Illuminate\Contracts\View\View
|
||||||
{
|
{
|
||||||
return view('bo.pages.credit_accounts.create', [
|
return view('bo.pages.credit_accounts.create', [
|
||||||
'brandModel' => $brand,
|
'brandModel' => $brand,
|
||||||
'credit_accountModel' => $account
|
'credit_accountModel' => $account
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
@ -84,7 +85,7 @@ class AccountController extends Controller
|
||||||
{
|
{
|
||||||
return DB::transaction(function () use ($brand, $request) {
|
return DB::transaction(function () use ($brand, $request) {
|
||||||
$credit_accountModel = new Account();
|
$credit_accountModel = new Account();
|
||||||
$credit_accountModel->brand_id = $brand->getKey();
|
$credit_accountModel->brand_id = $brand->id;
|
||||||
$credit_accountModel->fill($request->validated());
|
$credit_accountModel->fill($request->validated());
|
||||||
|
|
||||||
if ($credit_accountModel->saveOrFail()) {
|
if ($credit_accountModel->saveOrFail()) {
|
||||||
|
|
|
||||||
|
|
@ -58,14 +58,14 @@ class CreditLogController extends Controller
|
||||||
/**
|
/**
|
||||||
* Show the form for creating a new resource.
|
* Show the form for creating a new resource.
|
||||||
*
|
*
|
||||||
* @param \App\Models\Brand $brand
|
* @param \App\Models\Brand $brand
|
||||||
* @param \App\Models\Credit\Account $account
|
* @param \App\Models\Account $account
|
||||||
* @return \Illuminate\Contracts\View\View
|
* @return \Illuminate\Contracts\View\View
|
||||||
*/
|
*/
|
||||||
public function create(Brand $brand, Account $account): \Illuminate\Contracts\View\View
|
public function create(Brand $brand, Account $account): \Illuminate\Contracts\View\View
|
||||||
{
|
{
|
||||||
return view('bo.pages.credit_logs.create', [
|
return view('bo.pages.credit_logs.create', [
|
||||||
'brandModel' => $brand,
|
'brandModel' => $brand,
|
||||||
'credit_accountModel' => $account
|
'credit_accountModel' => $account
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
@ -74,7 +74,7 @@ class CreditLogController extends Controller
|
||||||
* Store a newly created resource in storage.
|
* Store a newly created resource in storage.
|
||||||
*
|
*
|
||||||
* @param \App\Models\Brand $brand
|
* @param \App\Models\Brand $brand
|
||||||
* @param \App\Models\Credit\Account $account
|
* @param \App\Models\Account $account
|
||||||
* @param \App\Http\Requests\Bo\CreditLogs\StoreCreditLogRequest $request
|
* @param \App\Http\Requests\Bo\CreditLogs\StoreCreditLogRequest $request
|
||||||
* @return \Illuminate\Http\RedirectResponse
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -25,12 +25,27 @@ class InvoiceController extends Controller
|
||||||
*/
|
*/
|
||||||
public function index(Request $request): \Illuminate\Contracts\View\View
|
public function index(Request $request): \Illuminate\Contracts\View\View
|
||||||
{
|
{
|
||||||
|
// If no sorting is requested, apply the default orderByDesc.
|
||||||
/** @var \Illuminate\Database\Eloquent\Builder $invoiceModels */
|
/** @var \Illuminate\Database\Eloquent\Builder $invoiceModels */
|
||||||
$invoiceModels = Invoice::query()->orderByDesc('created_at');
|
$invoiceModels = (!request()->query('sort_col') && !request()->query('sort_way'))
|
||||||
$status = intval($request->status);
|
? Invoice::query()->orderByDesc('created_at')
|
||||||
$invoiceModels = $invoiceModels->when($status, function ($query) use ($status) {
|
: Invoice::query();
|
||||||
$query->where('status', $status);
|
|
||||||
});
|
$status = intval($request->status);
|
||||||
|
|
||||||
|
switch ($status) {
|
||||||
|
case InvoiceStatusEnum::awaiting_signature->value:
|
||||||
|
$invoiceModels->whereNotNull('sent_client_date')->whereNull('signed_date');
|
||||||
|
break;
|
||||||
|
case InvoiceStatusEnum::awaiting_invoicing->value:
|
||||||
|
$invoiceModels->whereNotNull('sent_client_date')->whereNotNull('signed_date')->whereNull('sent_accounting_date');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if ($status !== 0) {
|
||||||
|
$invoiceModels->where('status', $status);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/** @var string $search Search field */
|
/** @var string $search Search field */
|
||||||
$search = $request->search;
|
$search = $request->search;
|
||||||
|
|
@ -75,7 +90,7 @@ class InvoiceController extends Controller
|
||||||
*/
|
*/
|
||||||
public function create(Invoice $invoice): \Illuminate\Contracts\View\View
|
public function create(Invoice $invoice): \Illuminate\Contracts\View\View
|
||||||
{
|
{
|
||||||
$packageModels = Package::get();
|
$packageModels = Package::where('published', true)->get();
|
||||||
$taskRowModel = Invoice::getTaskStructure();
|
$taskRowModel = Invoice::getTaskStructure();
|
||||||
$siteModels = Site::orderBy('name', 'ASC')->get();
|
$siteModels = Site::orderBy('name', 'ASC')->get();
|
||||||
$companyModels = Company::get();
|
$companyModels = Company::get();
|
||||||
|
|
@ -176,9 +191,8 @@ class InvoiceController extends Controller
|
||||||
* @param \App\Models\Invoice $invoice
|
* @param \App\Models\Invoice $invoice
|
||||||
* @return \Illuminate\Http\RedirectResponse|\Symfony\Component\HttpFoundation\Response
|
* @return \Illuminate\Http\RedirectResponse|\Symfony\Component\HttpFoundation\Response
|
||||||
*/
|
*/
|
||||||
public function download(
|
public function download(Invoice $invoice)
|
||||||
Invoice $invoice
|
{
|
||||||
): \Illuminate\Http\RedirectResponse|\Symfony\Component\HttpFoundation\Response {
|
|
||||||
if (Gate::allows('isAdmin')) {
|
if (Gate::allows('isAdmin')) {
|
||||||
return $invoice->generateInvoice()
|
return $invoice->generateInvoice()
|
||||||
->stream(Str::slug(trans('Devis :appname :date - ref :ref', [
|
->stream(Str::slug(trans('Devis :appname :date - ref :ref', [
|
||||||
|
|
@ -200,7 +214,7 @@ class InvoiceController extends Controller
|
||||||
* Get a paginate resource.
|
* Get a paginate resource.
|
||||||
*
|
*
|
||||||
* @param \Illuminate\Http\Request $request
|
* @param \Illuminate\Http\Request $request
|
||||||
* @return \Illuminate\Http\JsonResponse
|
* @return Illuminate\Http\JsonResponse
|
||||||
*/
|
*/
|
||||||
public function jsonPaginate(Request $request): \Illuminate\Http\JsonResponse
|
public function jsonPaginate(Request $request): \Illuminate\Http\JsonResponse
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,15 @@ class PackageController extends Controller
|
||||||
/** @var \Illuminate\Database\Eloquent\Builder $packageModels */
|
/** @var \Illuminate\Database\Eloquent\Builder $packageModels */
|
||||||
$packageModels = Package::query();
|
$packageModels = Package::query();
|
||||||
|
|
||||||
|
$status = $request->status;
|
||||||
|
if ($status === null) {
|
||||||
|
$packageModels->where('published', true);
|
||||||
|
} elseif ($status === '0') {
|
||||||
|
$packageModels->where('published', false);
|
||||||
|
} elseif ($status === '1') {
|
||||||
|
$packageModels->where('published', true);
|
||||||
|
}
|
||||||
|
|
||||||
/** @var string $search Search field */
|
/** @var string $search Search field */
|
||||||
$search = $request->search;
|
$search = $request->search;
|
||||||
if ($search) {
|
if ($search) {
|
||||||
|
|
@ -42,7 +51,7 @@ class PackageController extends Controller
|
||||||
/** Custom pagination */
|
/** Custom pagination */
|
||||||
$packageModels = $this->customPaginate($packageModels, $request->pagination);
|
$packageModels = $this->customPaginate($packageModels, $request->pagination);
|
||||||
|
|
||||||
return view('bo.pages.packages.index', compact('packageModels', 'search', 'searchFields'));
|
return view('bo.pages.packages.index', compact('packageModels', 'search', 'searchFields', 'status'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -153,4 +162,16 @@ class PackageController extends Controller
|
||||||
));
|
));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change model published.
|
||||||
|
*
|
||||||
|
* @param \App\Models\Package $package
|
||||||
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
|
*/
|
||||||
|
public function changePublished(Package $package)
|
||||||
|
{
|
||||||
|
$package->update(['published' => !$package->getOriginal('published')]);
|
||||||
|
return redirect()->back()->with('success', trans(__('crud.messages.publish_status_saved')));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,193 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers\Bo;
|
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
|
||||||
use App\Http\Requests\Bo\Projects\StoreProjectRequest;
|
|
||||||
use App\Http\Requests\Bo\Projects\UpdateProjectRequest;
|
|
||||||
use App\Lib\Helpers\ToolboxHelper;
|
|
||||||
use App\Models\Project;
|
|
||||||
use App\Models\Site;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Illuminate\Support\Facades\DB;
|
|
||||||
use Illuminate\Support\Str;
|
|
||||||
|
|
||||||
class ProjectController extends Controller
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Display a listing of the resource.
|
|
||||||
*
|
|
||||||
* @param \Illuminate\Http\Request $request
|
|
||||||
* @return \Illuminate\Contracts\View\View
|
|
||||||
*/
|
|
||||||
public function index(Request $request): \Illuminate\Contracts\View\View
|
|
||||||
{
|
|
||||||
/** @var \Illuminate\Database\Eloquent\Builder $projectModels */
|
|
||||||
$projectModels = Project::query();
|
|
||||||
|
|
||||||
/** @var string $search Search field */
|
|
||||||
$search = $request->search;
|
|
||||||
if ($search) {
|
|
||||||
$this->searchQuery(
|
|
||||||
$projectModels,
|
|
||||||
$search,
|
|
||||||
null,
|
|
||||||
'name',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
$searchFields = trans('Nom');
|
|
||||||
|
|
||||||
/** Sort columns with a query */
|
|
||||||
$this->sortQuery($projectModels);
|
|
||||||
|
|
||||||
/** Custom pagination */
|
|
||||||
$projectModels = $this->customPaginate($projectModels, $request->pagination);
|
|
||||||
|
|
||||||
return view('bo.pages.projects.index', compact('projectModels', 'search', 'searchFields'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Crud show view
|
|
||||||
*
|
|
||||||
* @param \App\Models\Project $project
|
|
||||||
* @return \Illuminate\Contracts\View\View
|
|
||||||
*/
|
|
||||||
public function show(Project $project): \Illuminate\Contracts\View\View
|
|
||||||
{
|
|
||||||
return view('bo.pages.projects.show', [
|
|
||||||
'projectModel' => $project
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the form for creating a new resource.
|
|
||||||
*
|
|
||||||
* @param \App\Models\Project $project
|
|
||||||
* @return \Illuminate\Contracts\View\View
|
|
||||||
*/
|
|
||||||
public function create(Project $project): \Illuminate\Contracts\View\View
|
|
||||||
{
|
|
||||||
$siteModels = Site::orderBy('name', 'ASC')->get();
|
|
||||||
|
|
||||||
return view('bo.pages.projects.create', [
|
|
||||||
'projectModel' => $project,
|
|
||||||
'siteModels' => $siteModels
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Store a newly created resource in storage.
|
|
||||||
*
|
|
||||||
* @param \App\Http\Requests\Bo\Projects\StoreProjectRequest $request
|
|
||||||
* @return \Illuminate\Http\RedirectResponse
|
|
||||||
*/
|
|
||||||
public function store(StoreProjectRequest $request): \Illuminate\Http\RedirectResponse
|
|
||||||
{
|
|
||||||
return DB::transaction(function () use ($request) {
|
|
||||||
$project = new Project();
|
|
||||||
$project->fill($request->validated());
|
|
||||||
|
|
||||||
if ($project->saveOrFail()) {
|
|
||||||
return redirect()
|
|
||||||
->route('bo.projects.edit', $project)
|
|
||||||
->with('success', trans(
|
|
||||||
'crud.messages.has_been_created',
|
|
||||||
['model' => Str::singular(trans('models.classes.projects'))]
|
|
||||||
));
|
|
||||||
}
|
|
||||||
return redirect()
|
|
||||||
->back()
|
|
||||||
->with('error', trans(
|
|
||||||
'crud.messages.cannot_be_created',
|
|
||||||
['model' => Str::singular(trans('models.classes.projects'))]
|
|
||||||
));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the form for editing the specified resource.
|
|
||||||
*
|
|
||||||
* @param \App\Models\Project $project
|
|
||||||
* @return \Illuminate\Contracts\View\View
|
|
||||||
*/
|
|
||||||
public function edit(Project $project): \Illuminate\Contracts\View\View
|
|
||||||
{
|
|
||||||
$siteModels = Site::orderBy('name', 'ASC')->get();
|
|
||||||
|
|
||||||
return view('bo.pages.projects.edit', [
|
|
||||||
'projectModel' => $project,
|
|
||||||
'siteModels' => $siteModels
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the specified resource in storage.
|
|
||||||
*
|
|
||||||
* @param \App\Http\Requests\Bo\Projects\UpdateProjectRequest $request
|
|
||||||
* @param \App\Models\Project $project
|
|
||||||
* @return \Illuminate\Http\RedirectResponse
|
|
||||||
*/
|
|
||||||
public function update(UpdateProjectRequest $request, Project $project): \Illuminate\Http\RedirectResponse
|
|
||||||
{
|
|
||||||
return DB::transaction(function () use ($request, $project) {
|
|
||||||
$project->fill($request->validated());
|
|
||||||
if ($project->saveOrFail()) {
|
|
||||||
return redirect()
|
|
||||||
->route('bo.projects.edit', $project)
|
|
||||||
->with('success', trans(
|
|
||||||
'crud.messages.has_been_updated',
|
|
||||||
['model' => Str::singular(trans('models.classes.projects'))]
|
|
||||||
));
|
|
||||||
} //end if
|
|
||||||
return redirect()
|
|
||||||
->back()
|
|
||||||
->with('error', trans(
|
|
||||||
'crud.messages.cannot_be_updated',
|
|
||||||
['model' => Str::singular(trans('models.classes.projects'))]
|
|
||||||
));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove the specified resource from storage.
|
|
||||||
*
|
|
||||||
* @param \App\Models\Project $project
|
|
||||||
* @return \Illuminate\Http\RedirectResponse
|
|
||||||
*/
|
|
||||||
public function destroy(Project $project): \Illuminate\Http\RedirectResponse
|
|
||||||
{
|
|
||||||
return DB::transaction(function () use ($project) {
|
|
||||||
if ($project->deleteOrFail()) {
|
|
||||||
return redirect()
|
|
||||||
->route('bo.projects.index')
|
|
||||||
->with('success', trans(
|
|
||||||
'crud.messages.has_been_deleted',
|
|
||||||
['model' => Str::singular(trans('models.classes.projects'))]
|
|
||||||
));
|
|
||||||
}
|
|
||||||
return redirect()
|
|
||||||
->back()
|
|
||||||
->with('error', trans(
|
|
||||||
':crud.messages.cannot_be_deleted',
|
|
||||||
['model' => Str::singular(trans('models.classes.projects'))]
|
|
||||||
));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a paginate resource.
|
|
||||||
*
|
|
||||||
* @param \Illuminate\Http\Request $request
|
|
||||||
* @return \Illuminate\Http\JsonResponse
|
|
||||||
*/
|
|
||||||
public function jsonPaginate(Request $request): \Illuminate\Http\JsonResponse
|
|
||||||
{
|
|
||||||
return DB::transaction(function () use ($request) {
|
|
||||||
$model = $request->targetModel;
|
|
||||||
$search = $request->search;
|
|
||||||
$models = $model::where("name", "LIKE", "%{$search}%")->orderBy("name", "ASC");
|
|
||||||
|
|
||||||
return ToolboxHelper::jsonPaginate($this->customPaginate($models, $request->pagination));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -28,11 +28,11 @@ class SiteController extends Controller
|
||||||
|
|
||||||
if ($user->isAdmin()) {
|
if ($user->isAdmin()) {
|
||||||
/** @var \Illuminate\Database\Eloquent\Builder $siteModels */
|
/** @var \Illuminate\Database\Eloquent\Builder $siteModels */
|
||||||
$siteModels = Site::query();
|
$siteModels = Site::query()->with(['invoices', 'tickets']);
|
||||||
} else {
|
} else {
|
||||||
/** @var \Illuminate\Database\Eloquent\Builder $siteModels */
|
/** @var \Illuminate\Database\Eloquent\Builder $siteModels */
|
||||||
$siteModels = Site::whereHas('users', function (\Illuminate\Database\Eloquent\Builder $query) use ($user) {
|
$siteModels = Site::whereHas('users', function (\Illuminate\Database\Eloquent\Builder $query) use ($user) {
|
||||||
$query->where('id', $user->id);
|
$query->where('id', $user->id)->with(['invoices', 'tickets']);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -189,7 +189,7 @@ class SiteController extends Controller
|
||||||
* Get a paginate resource.
|
* Get a paginate resource.
|
||||||
*
|
*
|
||||||
* @param \Illuminate\Http\Request $request
|
* @param \Illuminate\Http\Request $request
|
||||||
* @return \Illuminate\Http\JsonResponse
|
* @return Illuminate\Http\JsonResponse
|
||||||
*/
|
*/
|
||||||
public function jsonPaginate(Request $request): \Illuminate\Http\JsonResponse
|
public function jsonPaginate(Request $request): \Illuminate\Http\JsonResponse
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -2,45 +2,48 @@
|
||||||
|
|
||||||
namespace App\Http\Controllers\Bo;
|
namespace App\Http\Controllers\Bo;
|
||||||
|
|
||||||
use App\Enums\Tickets\TicketStatusEnum;
|
use App\Models\Site;
|
||||||
use App\Enums\Tickets\TicketTypeEnum;
|
use App\Models\User;
|
||||||
use App\Enums\Users\GitlabUsersEnum;
|
use App\Models\Ticket;
|
||||||
|
use App\Mail\NewTicket;
|
||||||
|
use App\Models\Message;
|
||||||
|
use Illuminate\Support\Arr;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use App\Jobs\UpdateIssueLabels;
|
||||||
|
use App\Lib\Helpers\ToolboxHelper;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
use App\Events\NotifySubscriptions;
|
use App\Events\NotifySubscriptions;
|
||||||
use App\Events\TicketStatusChanged;
|
use App\Events\TicketStatusChanged;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Http\Requests\Bo\AssignTicketToUserRequest;
|
use App\Http\Requests\Bo\LinkTicket;
|
||||||
use App\Http\Requests\Bo\ChangeTicketStatus;
|
use Illuminate\Support\Facades\Mail;
|
||||||
use App\Http\Requests\Bo\CreateMessage;
|
use App\Enums\Tickets\TicketTypeEnum;
|
||||||
use App\Http\Requests\Bo\SortTickets;
|
use App\Http\Requests\Bo\SortTickets;
|
||||||
use App\Http\Requests\Bo\StoreTicket;
|
use App\Http\Requests\Bo\StoreTicket;
|
||||||
use App\Http\Requests\Bo\UpdateChangeOrderRequest;
|
|
||||||
use App\Http\Requests\Bo\UpdateMessage;
|
|
||||||
use App\Http\Requests\Bo\UpdateTicket;
|
use App\Http\Requests\Bo\UpdateTicket;
|
||||||
use App\Http\Requests\Bo\LinkTicket;
|
|
||||||
use App\Lib\Helpers\FileStorageHelper;
|
use App\Lib\Helpers\FileStorageHelper;
|
||||||
use App\Lib\Helpers\ToolboxHelper;
|
use App\Enums\Tickets\TicketStatusEnum;
|
||||||
use App\Mail\NewTicket;
|
use App\Events\TicketCreated;
|
||||||
use App\Models\Message;
|
use App\Http\Requests\Bo\CreateMessage;
|
||||||
use App\Models\Site;
|
use App\Http\Requests\Bo\UpdateMessage;
|
||||||
use App\Models\Ticket;
|
use Illuminate\Support\Facades\Session;
|
||||||
use App\Models\User;
|
|
||||||
use GrahamCampbell\GitLab\Facades\GitLab;
|
use GrahamCampbell\GitLab\Facades\GitLab;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
use Illuminate\Http\Request;
|
use App\Http\Requests\Bo\ChangeTicketStatus;
|
||||||
use Illuminate\Support\Arr;
|
use App\Http\Requests\Bo\UpdateChangeOrderRequest;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use App\Http\Requests\Bo\AssignTicketToUserRequest;
|
||||||
use Illuminate\Support\Facades\DB;
|
use App\Http\Requests\Bo\UpdateTicketPriorityRequest;
|
||||||
use Illuminate\Support\Facades\Mail;
|
use Illuminate\Contracts\Events\Dispatcher;
|
||||||
use Illuminate\Support\Facades\Session;
|
|
||||||
use Illuminate\Support\Str;
|
|
||||||
|
|
||||||
class TicketController extends Controller
|
class TicketController extends Controller
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* TicketController
|
* TicketController
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct(
|
||||||
{
|
public readonly Dispatcher $dispatcher
|
||||||
|
) {
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
$this->authorizeResource(Ticket::class, 'ticket');
|
$this->authorizeResource(Ticket::class, 'ticket');
|
||||||
}
|
}
|
||||||
|
|
@ -63,7 +66,7 @@ class TicketController extends Controller
|
||||||
$q->where('name', 'LIKE', "%$request->s%");
|
$q->where('name', 'LIKE', "%$request->s%");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
/** @var \Illuminate\Pagination\LengthAwarePaginator $tickets */
|
/** @var \Illuminate/Pagination/LengthAwarePaginator $tickets */
|
||||||
$tickets = $tickets->paginate();
|
$tickets = $tickets->paginate();
|
||||||
return \response()->json($tickets->getCollection()->map(function (Ticket $ticket) {
|
return \response()->json($tickets->getCollection()->map(function (Ticket $ticket) {
|
||||||
return [
|
return [
|
||||||
|
|
@ -129,12 +132,10 @@ class TicketController extends Controller
|
||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
* @param Ticket $ticket
|
* @param Ticket $ticket
|
||||||
* @return \Illuminate\Http\JsonResponse|\Illuminate\Contracts\View\View
|
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
|
||||||
*/
|
*/
|
||||||
public function show(
|
public function show(Request $request, Ticket $ticket)
|
||||||
Request $request,
|
{
|
||||||
Ticket $ticket
|
|
||||||
): \Illuminate\Http\JsonResponse|\Illuminate\Contracts\View\View {
|
|
||||||
if ($request->ajax()) {
|
if ($request->ajax()) {
|
||||||
return \response()->json([
|
return \response()->json([
|
||||||
'label' => $ticket->formatName($ticket),
|
'label' => $ticket->formatName($ticket),
|
||||||
|
|
@ -165,9 +166,9 @@ class TicketController extends Controller
|
||||||
/**
|
/**
|
||||||
* Show create Form
|
* Show create Form
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Contracts\View\View
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*/
|
*/
|
||||||
public function create(): \Illuminate\Http\RedirectResponse|\Illuminate\Contracts\View\View
|
public function create()
|
||||||
{
|
{
|
||||||
/** @var \App\Models\User */
|
/** @var \App\Models\User */
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
|
|
@ -190,7 +191,7 @@ class TicketController extends Controller
|
||||||
* @param StoreTicket $request
|
* @param StoreTicket $request
|
||||||
* @return \Illuminate\Http\RedirectResponse
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*/
|
*/
|
||||||
public function store(StoreTicket $request): \Illuminate\Http\RedirectResponse
|
public function store(StoreTicket $request)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
return DB::transaction(function () use ($request) {
|
return DB::transaction(function () use ($request) {
|
||||||
|
|
@ -215,7 +216,7 @@ class TicketController extends Controller
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$ticket->user()->associate(auth()->user());
|
$ticket->user()->associate($user);
|
||||||
$ticket->site()->associate($site);
|
$ticket->site()->associate($site);
|
||||||
$ticket->saveOrFail();
|
$ticket->saveOrFail();
|
||||||
|
|
||||||
|
|
@ -225,11 +226,11 @@ class TicketController extends Controller
|
||||||
|
|
||||||
$user->subscriptions()->toggle($ticket->id);
|
$user->subscriptions()->toggle($ticket->id);
|
||||||
|
|
||||||
if (config('mail.MAIL_ADMIN')) {
|
$this->dispatcher->dispatch(new TicketCreated(
|
||||||
Mail::to(config('mail.MAIL_ADMIN'))->send(new NewTicket($ticket));
|
siteReceivingTicket: $site,
|
||||||
} else {
|
ticket: $ticket,
|
||||||
throw new \ErrorException('Missing MAIL_ADMIN in .env');
|
byUserName: $user->name
|
||||||
}
|
));
|
||||||
|
|
||||||
return redirect()->route('bo.ticket.show', $ticket)
|
return redirect()->route('bo.ticket.show', $ticket)
|
||||||
->with('success', trans('Ticket enregistré !'));
|
->with('success', trans('Ticket enregistré !'));
|
||||||
|
|
@ -243,13 +244,13 @@ class TicketController extends Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show update form.
|
* Show update form
|
||||||
*
|
*
|
||||||
* @param Ticket $ticket
|
* @param Ticket $ticket
|
||||||
* @return \Illuminate\Contracts\View\View
|
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
|
||||||
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
|
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
|
||||||
*/
|
*/
|
||||||
public function edit(Ticket $ticket): \Illuminate\Contracts\View\View
|
public function edit(Ticket $ticket)
|
||||||
{
|
{
|
||||||
/** @var \App\Models\User */
|
/** @var \App\Models\User */
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
|
|
@ -262,13 +263,13 @@ class TicketController extends Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update Model.
|
* Update Model
|
||||||
*
|
*
|
||||||
* @param UpdateTicket $request
|
* @param UpdateTicket $request
|
||||||
* @param Ticket $ticket
|
* @param Ticket $ticket
|
||||||
* @return \Illuminate\Http\RedirectResponse
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*/
|
*/
|
||||||
public function update(UpdateTicket $request, Ticket $ticket): \Illuminate\Http\RedirectResponse
|
public function update(UpdateTicket $request, Ticket $ticket)
|
||||||
{
|
{
|
||||||
$ticket->fill($request->validated());
|
$ticket->fill($request->validated());
|
||||||
|
|
||||||
|
|
@ -307,14 +308,18 @@ class TicketController extends Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change ticket Status.
|
* Change ticket Status
|
||||||
*
|
*
|
||||||
* @param ChangeTicketStatus $request
|
* @param ChangeTicketStatus $request
|
||||||
* @param Ticket $ticket
|
* @param Ticket $ticket
|
||||||
* @return \Illuminate\Http\RedirectResponse
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*/
|
*/
|
||||||
public function changeStatus(ChangeTicketStatus $request, Ticket $ticket): \Illuminate\Http\RedirectResponse
|
public function changeStatus(ChangeTicketStatus $request, Ticket $ticket)
|
||||||
{
|
{
|
||||||
|
if ($ticket->gitlab_issue) {
|
||||||
|
\dispatch(new UpdateIssueLabels($ticket, $request->status));
|
||||||
|
}
|
||||||
|
|
||||||
$ticket->fill($request->validated());
|
$ticket->fill($request->validated());
|
||||||
$ticket->saveOrFail();
|
$ticket->saveOrFail();
|
||||||
|
|
||||||
|
|
@ -323,33 +328,32 @@ class TicketController extends Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a new Message to the Ticket.
|
* Add a new Message to the Ticket
|
||||||
*
|
*
|
||||||
* @param CreateMessage $request
|
* @param CreateMessage $request
|
||||||
* @param Ticket $ticket
|
* @param Ticket $ticket
|
||||||
* @return \Illuminate\Http\RedirectResponse
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*/
|
*/
|
||||||
public function createMessage(CreateMessage $request, Ticket $ticket): \Illuminate\Http\RedirectResponse
|
public function createMessage(CreateMessage $request, Ticket $ticket)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
return DB::transaction(function () use ($request, $ticket) {
|
return DB::transaction(function () use ($request, $ticket) {
|
||||||
/** @var \App\Models\User $user */
|
|
||||||
$user = Auth::user();
|
|
||||||
|
|
||||||
/** @var \Illuminate\Http\UploadedFile|null */
|
/** @var \Illuminate\Http\UploadedFile|null */
|
||||||
$filesMessage = $request->file_messages;
|
$filesMessage = $request->file_messages;
|
||||||
$message = new Message($request->validated());
|
$message = new Message($request->validated());
|
||||||
$message->user()->associate($user);
|
$message->user()->associate(auth()->user());
|
||||||
$message->ticket()->associate($ticket);
|
$message->ticket()->associate($ticket);
|
||||||
|
|
||||||
|
/** @var \App\Models\User */
|
||||||
|
$user = auth()->user();
|
||||||
|
// Subscribe to ticket.
|
||||||
if ($request->subscribe) {
|
if ($request->subscribe) {
|
||||||
if (!$user->subscriptions()->find($ticket->id)) {
|
$user->subscriptions()->syncWithoutDetaching([$ticket->id]);
|
||||||
$user->subscriptions()->attach($ticket->id);
|
} else {
|
||||||
}
|
|
||||||
} elseif ($user->subscriptions()->find($ticket->id)) {
|
|
||||||
$user->subscriptions()->detach($ticket->id);
|
$user->subscriptions()->detach($ticket->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Store files if any.
|
||||||
if (isset($filesMessage) and $filesMessage) {
|
if (isset($filesMessage) and $filesMessage) {
|
||||||
foreach ($filesMessage as $key => $singleFile) {
|
foreach ($filesMessage as $key => $singleFile) {
|
||||||
if ($key === 0) {
|
if ($key === 0) {
|
||||||
|
|
@ -367,7 +371,7 @@ class TicketController extends Controller
|
||||||
|
|
||||||
return back()
|
return back()
|
||||||
->with('success', trans('Votre message à été ajouté'));
|
->with('success', trans('Votre message à été ajouté'));
|
||||||
});
|
}, 5);
|
||||||
} catch (\ErrorException $e) {
|
} catch (\ErrorException $e) {
|
||||||
report($e);
|
report($e);
|
||||||
Session::flash('error', trans('Une erreur est survenue'));
|
Session::flash('error', trans('Une erreur est survenue'));
|
||||||
|
|
@ -377,7 +381,7 @@ class TicketController extends Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update Message.
|
* Update Message
|
||||||
*
|
*
|
||||||
* @param UpdateMessage $request
|
* @param UpdateMessage $request
|
||||||
* @param Ticket $ticket
|
* @param Ticket $ticket
|
||||||
|
|
@ -385,11 +389,8 @@ class TicketController extends Controller
|
||||||
* @return \Illuminate\Http\RedirectResponse
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
|
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
|
||||||
*/
|
*/
|
||||||
public function updateMessage(
|
public function updateMessage(UpdateMessage $request, Ticket $ticket, Message $message)
|
||||||
UpdateMessage $request,
|
{
|
||||||
Ticket $ticket,
|
|
||||||
Message $message
|
|
||||||
): \Illuminate\Http\RedirectResponse {
|
|
||||||
$message->message = $request->message;
|
$message->message = $request->message;
|
||||||
$message->saveOrFail();
|
$message->saveOrFail();
|
||||||
|
|
||||||
|
|
@ -398,12 +399,12 @@ class TicketController extends Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change ticket status to archived.
|
* Change ticket status to archived
|
||||||
*
|
*
|
||||||
* @param Ticket $ticket
|
* @param Ticket $ticket
|
||||||
* @return \Illuminate\Http\RedirectResponse
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*/
|
*/
|
||||||
public function setToArchive(Ticket $ticket): \Illuminate\Http\RedirectResponse
|
public function setToArchive(Ticket $ticket)
|
||||||
{
|
{
|
||||||
$ticket->status = TicketStatusEnum::archived;
|
$ticket->status = TicketStatusEnum::archived;
|
||||||
$ticket->saveOrFail();
|
$ticket->saveOrFail();
|
||||||
|
|
@ -412,15 +413,15 @@ class TicketController extends Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subscribe to ticket.
|
* Subscribe to ticket
|
||||||
*
|
*
|
||||||
* @param Ticket $ticket
|
* @param Ticket $ticket
|
||||||
* @return \Illuminate\Http\RedirectResponse
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*/
|
*/
|
||||||
public function subscribe(Ticket $ticket): \Illuminate\Http\RedirectResponse
|
public function subscribe(Ticket $ticket)
|
||||||
{
|
{
|
||||||
/** @var \App\Models\User $user */
|
/** @var \App\Models\User */
|
||||||
$user = Auth::user();
|
$user = auth()->user();
|
||||||
$user->subscriptions()->toggle($ticket->id);
|
$user->subscriptions()->toggle($ticket->id);
|
||||||
if ($user->subscriptions()->where('ticket_id', $ticket->id)->exists()) {
|
if ($user->subscriptions()->where('ticket_id', $ticket->id)->exists()) {
|
||||||
return back()
|
return back()
|
||||||
|
|
@ -430,15 +431,15 @@ class TicketController extends Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reopen ticket.
|
* Reopen ticket
|
||||||
*
|
*
|
||||||
* @param Ticket $ticket
|
* @param Ticket $ticket
|
||||||
* @return \Illuminate\Http\RedirectResponse
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*/
|
*/
|
||||||
public function reopen(Ticket $ticket): \Illuminate\Http\RedirectResponse
|
public function reopen(Ticket $ticket)
|
||||||
{
|
{
|
||||||
$message = trans(':ticketName à réouvert le ticket n°:ticketNumber', [
|
$message = trans(':ticketName à réouvert le ticket n°:ticketNumber', [
|
||||||
'ticketName' => $ticket->user->name,
|
'ticketName' => $ticket->user->name,
|
||||||
'ticketNumber' => $ticket->id,
|
'ticketNumber' => $ticket->id,
|
||||||
]);
|
]);
|
||||||
/** @var \App\Enums\Tickets\TicketStatusEnum */
|
/** @var \App\Enums\Tickets\TicketStatusEnum */
|
||||||
|
|
@ -448,28 +449,27 @@ class TicketController extends Controller
|
||||||
event(new TicketStatusChanged($ticket, $oldStatus, null, $message, false, false));
|
event(new TicketStatusChanged($ticket, $oldStatus, null, $message, false, false));
|
||||||
event(new NotifySubscriptions($ticket, $message, collect([$ticket->user])));
|
event(new NotifySubscriptions($ticket, $message, collect([$ticket->user])));
|
||||||
|
|
||||||
/** @var \App\Models\User $user */
|
/** @var \App\Models\User */
|
||||||
$user = Auth::user();
|
$user = auth()->user();
|
||||||
$user->subscriptions()->toggle($ticket->id);
|
$user->subscriptions()->toggle($ticket->id);
|
||||||
|
|
||||||
return back()->with('warning', trans('Votre ticket à été réouvert.'));
|
return back()->with('warning', trans('Votre ticket à été réouvert.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assign ticket to user ticket.
|
* Assign ticket to user ticket
|
||||||
*
|
*
|
||||||
* @param AssignTicketToUserRequest $request
|
* @param AssignTicketToUserRequest $request
|
||||||
* @param Ticket $ticket
|
* @param Ticket $ticket
|
||||||
* @return \Illuminate\Http\RedirectResponse
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*/
|
*/
|
||||||
public function assignTo(AssignTicketToUserRequest $request, Ticket $ticket): \Illuminate\Http\RedirectResponse
|
public function assignTo(AssignTicketToUserRequest $request, Ticket $ticket)
|
||||||
{
|
{
|
||||||
/** @var \App\Models\User $user */
|
/** @var \App\Models\User */
|
||||||
$user = Auth::user();
|
$user = auth()->user();
|
||||||
|
|
||||||
/** @var \App\Models\User|null $assignedUser */
|
/** @var \App\Models\User|null */
|
||||||
$assignedUser = User::whereId($request->assign)->first();
|
if ($assignedUser = User::whereId($request->assign)->first()) {
|
||||||
if ($assignedUser) {
|
|
||||||
$message = trans(':admin a assigné le ticket n°:ticketNumber à :assignedAdmin', [
|
$message = trans(':admin a assigné le ticket n°:ticketNumber à :assignedAdmin', [
|
||||||
'admin' => $user->name,
|
'admin' => $user->name,
|
||||||
'ticketNumber' => $ticket->id,
|
'ticketNumber' => $ticket->id,
|
||||||
|
|
@ -495,6 +495,8 @@ class TicketController extends Controller
|
||||||
event(new TicketStatusChanged($ticket, $oldStatus, null, $message, true, false));
|
event(new TicketStatusChanged($ticket, $oldStatus, null, $message, true, false));
|
||||||
event(new NotifySubscriptions($ticket, $message, collect([$ticket->user])));
|
event(new NotifySubscriptions($ticket, $message, collect([$ticket->user])));
|
||||||
|
|
||||||
|
/** @var \App\Models\User */
|
||||||
|
$user = auth()->user();
|
||||||
$user->subscriptions()->toggle($ticket->id);
|
$user->subscriptions()->toggle($ticket->id);
|
||||||
|
|
||||||
if ($assignedUser) {
|
if ($assignedUser) {
|
||||||
|
|
@ -550,14 +552,14 @@ class TicketController extends Controller
|
||||||
// * PRIVATES
|
// * PRIVATES
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filter Tickets request constructor.
|
* Filter Tickets request constructor
|
||||||
*
|
*
|
||||||
* @param \Illuminate\Database\Eloquent\Builder $tickets
|
* @param Builder $tickets
|
||||||
* @param \Illuminate\Http\Request $request
|
* @param Request $request
|
||||||
* @return \Illuminate\Database\Eloquent\Builder
|
* @return Builder
|
||||||
* @phpcs:disable Generic.Metrics.CyclomaticComplexity.MaxExceeded
|
* @phpcs:disable Generic.Metrics.CyclomaticComplexity.TooHigh
|
||||||
*/
|
*/
|
||||||
private function filterTickets(Builder $tickets, Request $request): \Illuminate\Database\Eloquent\Builder
|
private function filterTickets(Builder $tickets, Request $request): Builder
|
||||||
{
|
{
|
||||||
//phpcs:enable
|
//phpcs:enable
|
||||||
if ($request->rst) {
|
if ($request->rst) {
|
||||||
|
|
@ -664,13 +666,13 @@ class TicketController extends Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search ticket sql request constructor.
|
* Search ticket sql request constructor
|
||||||
*
|
*
|
||||||
* @param \Illuminate\Database\Eloquent\Builder $tickets
|
* @param Builder $tickets
|
||||||
* @param \Illuminate\Http\Request $request
|
* @param Request $request
|
||||||
* @return \Illuminate\Database\Eloquent\Builder
|
* @return Builder
|
||||||
*/
|
*/
|
||||||
private function searchTicket(Builder $tickets, Request $request): \Illuminate\Database\Eloquent\Builder
|
private function searchTicket(Builder $tickets, Request $request): Builder
|
||||||
{
|
{
|
||||||
if ($request->exists('search')) {
|
if ($request->exists('search')) {
|
||||||
if (empty($request->search)) {
|
if (empty($request->search)) {
|
||||||
|
|
@ -686,27 +688,29 @@ class TicketController extends Controller
|
||||||
|
|
||||||
return $this->searchQuery($tickets, Session::get('tickets.search'), function ($q) {
|
return $this->searchQuery($tickets, Session::get('tickets.search'), function ($q) {
|
||||||
$words = explode(' ', Session::get('tickets.search'));
|
$words = explode(' ', Session::get('tickets.search'));
|
||||||
foreach ($words as $word) {
|
if (\is_array($words)) {
|
||||||
if (!strlen($word)) {
|
foreach ($words as $word) {
|
||||||
continue;
|
if (!strlen($word)) {
|
||||||
}
|
continue;
|
||||||
$s = collect(TicketStatusEnum::cases())->filter(function (TicketStatusEnum $t) use ($word) {
|
}
|
||||||
return Str::slug($t->label()) === Str::slug($word);
|
$s = collect(TicketStatusEnum::cases())->filter(function (TicketStatusEnum $t) use ($word) {
|
||||||
})->map(function (TicketStatusEnum $ticket) {
|
return Str::slug($t->label()) === Str::slug($word);
|
||||||
return $ticket->value;
|
})->map(function (TicketStatusEnum $ticket) {
|
||||||
});
|
return $ticket->value;
|
||||||
$t = collect(TicketTypeEnum::cases())->filter(function (TicketTypeEnum $s) use ($word) {
|
|
||||||
return Str::slug($s->label()) === Str::slug($word);
|
|
||||||
})->map(function (TicketTypeEnum $ticket) {
|
|
||||||
return $ticket->value;
|
|
||||||
});
|
|
||||||
$q->orWhere('id', $word)
|
|
||||||
->orWhereIn('status', $s)
|
|
||||||
->orWhereIn('type', $t)
|
|
||||||
->orWhereHas('user', function ($q) use ($word) {
|
|
||||||
$q->where('name', 'LIKE', "%$word%");
|
|
||||||
});
|
});
|
||||||
} //end foreach
|
$t = collect(TicketTypeEnum::cases())->filter(function (TicketTypeEnum $s) use ($word) {
|
||||||
|
return Str::slug($s->label()) === Str::slug($word);
|
||||||
|
})->map(function (TicketTypeEnum $ticket) {
|
||||||
|
return $ticket->value;
|
||||||
|
});
|
||||||
|
$q->orWhere('id', $word)
|
||||||
|
->orWhereIn('status', $s)
|
||||||
|
->orWhereIn('type', $t)
|
||||||
|
->orWhereHas('user', function ($q) use ($word) {
|
||||||
|
$q->where('name', 'LIKE', "%$word%");
|
||||||
|
});
|
||||||
|
} //end foreach
|
||||||
|
} //end if
|
||||||
}, 'text', 'title', 'file', 'file2', 'file3', 'file4', 'file5');
|
}, 'text', 'title', 'file', 'file2', 'file3', 'file4', 'file5');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -714,7 +718,7 @@ class TicketController extends Controller
|
||||||
* Get a paginate resource.
|
* Get a paginate resource.
|
||||||
*
|
*
|
||||||
* @param \Illuminate\Http\Request $request
|
* @param \Illuminate\Http\Request $request
|
||||||
* @return \Illuminate\Http\JsonResponse
|
* @return Illuminate\Http\JsonResponse
|
||||||
*/
|
*/
|
||||||
public function jsonPaginate(Request $request): \Illuminate\Http\JsonResponse
|
public function jsonPaginate(Request $request): \Illuminate\Http\JsonResponse
|
||||||
{
|
{
|
||||||
|
|
@ -745,22 +749,29 @@ class TicketController extends Controller
|
||||||
*
|
*
|
||||||
* @param \App\Models\Ticket $ticket
|
* @param \App\Models\Ticket $ticket
|
||||||
* @return \Illuminate\Http\RedirectResponse
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
* @phpcs:disable Generic.Metrics.CyclomaticComplexity.TooHigh
|
|
||||||
*/
|
*/
|
||||||
public function createGitlabIssue(Ticket $ticket): \Illuminate\Http\RedirectResponse
|
public function createGitlabIssue(Ticket $ticket)
|
||||||
{
|
{
|
||||||
//phpcs:enable
|
$userGitlabId = auth()->user()->gitlab_id;
|
||||||
$gitlabRepoId = $ticket->site->gitlab_project_id;
|
$gitlabRepoId = $ticket->site->gitlab_project_id;
|
||||||
$description = \sprintf("%s<br>", $ticket->text);
|
|
||||||
$cLabel = match ($ticket->type) {
|
if (GitLab::projects()->show($gitlabRepoId)['archived']) {
|
||||||
TicketTypeEnum::bug => 'c-bug',
|
return back()->with('error', \trans("Ce projet GitLab est archivé et ne peut pas être utilisé."));
|
||||||
TicketTypeEnum::evolution, TicketTypeEnum::newsletter => 'c-feature',
|
}
|
||||||
|
|
||||||
|
$description = \sprintf("%s<br>", $ticket->text);
|
||||||
|
$cLabel = match ($ticket->type) {
|
||||||
|
TicketTypeEnum::bug => 'c-bug,g-to-dispatch',
|
||||||
|
TicketTypeEnum::evolution,
|
||||||
|
TicketTypeEnum::mailing => 'c-feature',
|
||||||
|
TicketTypeEnum::newsletter => 'c-feature,g-to-estimate',
|
||||||
};
|
};
|
||||||
|
|
||||||
$assigneeId = match ($ticket->type) {
|
$assigneeId = match ($ticket->type) {
|
||||||
TicketTypeEnum::bug => GitlabUsersEnum::default->value,
|
TicketTypeEnum::bug => $userGitlabId,
|
||||||
TicketTypeEnum::evolution,
|
TicketTypeEnum::evolution,
|
||||||
TicketTypeEnum::newsletter => $ticket->site->projectManager?->gitlab_id ?? GitlabUsersEnum::default->value
|
TicketTypeEnum::mailing,
|
||||||
|
TicketTypeEnum::newsletter => $ticket->site->projectManager?->gitlab_id
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
@ -770,7 +781,8 @@ class TicketController extends Controller
|
||||||
$description .= $this->formatGitlabFiles($ticket, $uploadedFile, $key + 1);
|
$description .= $this->formatGitlabFiles($ticket, $uploadedFile, $key + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$issue = GitLab::issues()->create($gitlabRepoId, [
|
|
||||||
|
$data = [
|
||||||
'title' => sprintf(
|
'title' => sprintf(
|
||||||
'ts-%s : %s',
|
'ts-%s : %s',
|
||||||
$ticket->id,
|
$ticket->id,
|
||||||
|
|
@ -781,8 +793,13 @@ class TicketController extends Controller
|
||||||
'c-support',
|
'c-support',
|
||||||
$cLabel
|
$cLabel
|
||||||
]),
|
]),
|
||||||
'assignee_id' => $assigneeId,
|
];
|
||||||
]);
|
|
||||||
|
if ($assigneeId) {
|
||||||
|
$data['assignee_id'] = $assigneeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
$issue = GitLab::issues()->create($gitlabRepoId, $data);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
\report($e);
|
\report($e);
|
||||||
return back()->with('error', \trans("Une erreur est survenue"));
|
return back()->with('error', \trans("Une erreur est survenue"));
|
||||||
|
|
@ -801,16 +818,16 @@ class TicketController extends Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Format files for Gitlab issues.
|
* Format files for Gitlab issues
|
||||||
*
|
*
|
||||||
* @param \App\Models\Ticket $ticket
|
* @param \App\Models\Ticket $ticket
|
||||||
* @param array $uploadedFile
|
* @param array $uploadedFile
|
||||||
* @param integer $fileNb
|
* @param integer $fileNb
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
private function formatGitlabFiles(Ticket $ticket, array $uploadedFile, int $fileNb): string
|
private function formatGitlabFiles(Ticket $ticket, array $uploadedFile, int $fileNb)
|
||||||
{
|
{
|
||||||
if (Str::endsWith($ticket->file, ['jpg', 'png', 'jpeg', 'pptx', 'docx', 'xslx', 'csv'])) {
|
if (Str::endsWith($ticket->file, ['jpg', 'png', 'jpeg', 'pptx', 'docx', 'xslx', 'csv', 'svg'])) {
|
||||||
$file = \sprintf(
|
$file = \sprintf(
|
||||||
"",
|
"",
|
||||||
$fileNb,
|
$fileNb,
|
||||||
|
|
@ -839,8 +856,7 @@ class TicketController extends Controller
|
||||||
$paramNames = collect(request()->route()->parameterNames);
|
$paramNames = collect(request()->route()->parameterNames);
|
||||||
$className = Str::of($paramNames->get($paramNames->count() - 2))->lower()->studly();
|
$className = Str::of($paramNames->get($paramNames->count() - 2))->lower()->studly();
|
||||||
$className = "\\App\\Models\\{$className}";
|
$className = "\\App\\Models\\{$className}";
|
||||||
/** @var \App\Models\Ticket|null $model */
|
$model = Arr::get($params, $paramNames->count() - 2);
|
||||||
$model = Arr::get($params, $paramNames->count() - 2);
|
|
||||||
|
|
||||||
if (!class_exists($className)) {
|
if (!class_exists($className)) {
|
||||||
throw new \RuntimeException("The {$className} class doesn't exist.");
|
throw new \RuntimeException("The {$className} class doesn't exist.");
|
||||||
|
|
@ -854,7 +870,7 @@ class TicketController extends Controller
|
||||||
throw new \RuntimeException("The {$className} doesn't match second last binded param.");
|
throw new \RuntimeException("The {$className} doesn't match second last binded param.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @var \App\Models\Ticket|null */
|
/** @var \Illuminate\Database\Eloquent\Model|null */
|
||||||
$model = $className::query()->where($model->getRouteKeyName(), $model->getRouteKey())->first();
|
$model = $className::query()->where($model->getRouteKeyName(), $model->getRouteKey())->first();
|
||||||
|
|
||||||
if (!$model) {
|
if (!$model) {
|
||||||
|
|
@ -862,7 +878,7 @@ class TicketController extends Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
return DB::transaction(function () use ($request, $className, $model) {
|
return DB::transaction(function () use ($request, $className, $model) {
|
||||||
/** @var \Illuminate\Support\Collection<int, \App\Models\Ticket> $models */
|
/** @var \Illuminate\Support\Collection $models */
|
||||||
$models = $className::query()
|
$models = $className::query()
|
||||||
->orderBy('order', 'ASC')
|
->orderBy('order', 'ASC')
|
||||||
->where('site_id', $model->site_id)
|
->where('site_id', $model->site_id)
|
||||||
|
|
@ -884,4 +900,34 @@ class TicketController extends Controller
|
||||||
return redirect()->back()->with('success', trans('crud.messages.order_changed'));
|
return redirect()->back()->with('success', trans('crud.messages.order_changed'));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update ticket priority.
|
||||||
|
*
|
||||||
|
* @param UpdateTicketPriorityRequest $request
|
||||||
|
* @param Ticket $ticket
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function changePriority(UpdateTicketPriorityRequest $request, Ticket $ticket)
|
||||||
|
{
|
||||||
|
$newPriority = $request->validated('priority');
|
||||||
|
|
||||||
|
return DB::transaction(function () use ($ticket, $newPriority) {
|
||||||
|
// Update all tickets who will be moved with this priority update.
|
||||||
|
$request = Ticket::query()
|
||||||
|
->where('site_id', $ticket->site_id)
|
||||||
|
->whereNot('status', TicketStatusEnum::archived)
|
||||||
|
->whereNot('id', $ticket->id)
|
||||||
|
->whereBetween('order', [min($ticket->order, $newPriority), max($ticket->order, $newPriority)]);
|
||||||
|
$ticket->order < $newPriority ? $request->decrement('order', 1) : $request->increment('order', 1);
|
||||||
|
|
||||||
|
// Update the ticket.
|
||||||
|
$ticket->order = $newPriority;
|
||||||
|
if (!$ticket->saveOrFail()) {
|
||||||
|
return back()->with('error', trans('crud.messages.order_not_changed'));
|
||||||
|
};
|
||||||
|
|
||||||
|
return redirect()->back()->with('success', trans('crud.messages.order_changed'));
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ class TicketTypeController extends Controller
|
||||||
/**
|
/**
|
||||||
* Show the form for editing the specified resource.
|
* Show the form for editing the specified resource.
|
||||||
*
|
*
|
||||||
* @param \App\Models\Ticket\TicketType $ticketType
|
* @param App\Models\Ticket\TicketType $ticketType
|
||||||
* @return \Illuminate\Contracts\View\View
|
* @return \Illuminate\Contracts\View\View
|
||||||
* @ignore phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
|
* @ignore phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -2,15 +2,16 @@
|
||||||
|
|
||||||
namespace App\Http\Controllers\Bo;
|
namespace App\Http\Controllers\Bo;
|
||||||
|
|
||||||
use App\Http\Controllers\Bo\Auth\ForgotPasswordController;
|
use App\Models\Site;
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Http\Requests\Bo\Users\StoreUserRequest;
|
use App\Http\Requests\Bo\Users\StoreUserRequest;
|
||||||
use App\Http\Requests\Bo\Users\UpdateUserRequest;
|
use App\Http\Requests\Bo\Users\UpdateUserRequest;
|
||||||
use App\Models\Site;
|
use App\Http\Controllers\Bo\Auth\ForgotPasswordController;
|
||||||
use App\Models\User;
|
use App\Http\Requests\Bo\Users\FavouriteSiteRequest;
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Illuminate\Support\Facades\DB;
|
|
||||||
use Illuminate\Support\Str;
|
|
||||||
|
|
||||||
class UserController extends Controller
|
class UserController extends Controller
|
||||||
{
|
{
|
||||||
|
|
@ -72,8 +73,9 @@ class UserController extends Controller
|
||||||
public function store(StoreUserRequest $request): \Illuminate\Http\RedirectResponse
|
public function store(StoreUserRequest $request): \Illuminate\Http\RedirectResponse
|
||||||
{
|
{
|
||||||
return DB::transaction(function () use ($request) {
|
return DB::transaction(function () use ($request) {
|
||||||
$user = new User();
|
$user = User::query()->onlyTrashed()->where('email', $request->validated('email'))->first() ?? new User();
|
||||||
$user->fill($request->safe()->except('sites'));
|
$user->fill($request->safe()->except('sites'));
|
||||||
|
$user->deleted_at = null;
|
||||||
|
|
||||||
if ($user->saveOrFail()) {
|
if ($user->saveOrFail()) {
|
||||||
$user->sites()->attach(collect($request->validated('sites'))->pluck('id'));
|
$user->sites()->attach(collect($request->validated('sites'))->pluck('id'));
|
||||||
|
|
@ -166,17 +168,43 @@ class UserController extends Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Password reset form.
|
* Password reset form
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Contracts\View\View
|
* @return \Illuminate\Contracts\View\View
|
||||||
*/
|
*/
|
||||||
public function passwordReset(): \Illuminate\Contracts\View\View
|
public function settings(): \Illuminate\Contracts\View\View
|
||||||
{
|
{
|
||||||
return view('bo.pages.users.passwordReset');
|
return view('bo.pages.users.settings');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Password reset submit.
|
* Favourite site submit
|
||||||
|
*
|
||||||
|
* @param \App\Http\Requests\Bo\Users\FavouriteSiteRequest $request
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
|
*/
|
||||||
|
public function favouriteSiteSubmit(FavouriteSiteRequest $request): \Illuminate\Http\RedirectResponse
|
||||||
|
{
|
||||||
|
/** @var \App\Models\User */
|
||||||
|
$user = auth()->user();
|
||||||
|
|
||||||
|
try {
|
||||||
|
$user->favourite_site_id = $request->favourite_site_id;
|
||||||
|
$user->saveOrFail();
|
||||||
|
|
||||||
|
return redirect()->back()->with("success", trans('crud.messages.favourite_site_changed'));
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
\report($e);
|
||||||
|
return redirect()->back()->with('error', trans('crud.messages.favourite_site_not_changed'));
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
\report($e);
|
||||||
|
return redirect()->back()->with('error', trans('crud.messages.favourite_site_not_changed'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Password reset submit
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Http\RedirectResponse
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*/
|
*/
|
||||||
|
|
@ -187,4 +215,18 @@ class UserController extends Controller
|
||||||
$request = new Request(['email' => $user->email]);
|
$request = new Request(['email' => $user->email]);
|
||||||
return app(ForgotPasswordController::class)->sendResetLinkEmail($request);
|
return app(ForgotPasswordController::class)->sendResetLinkEmail($request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get february last day date of the year
|
||||||
|
*
|
||||||
|
* @param integer $year
|
||||||
|
* @return integer 28 or 29
|
||||||
|
*/
|
||||||
|
private function getLastDayFebruary(int $year): int
|
||||||
|
{
|
||||||
|
if ((is_int($year / 4) && !is_int($year / 100)) || is_int($year / 400)) {
|
||||||
|
return 29;
|
||||||
|
}
|
||||||
|
return 28;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ namespace App\Http\Controllers;
|
||||||
|
|
||||||
use App\Enums\Tickets\TicketStatusEnum;
|
use App\Enums\Tickets\TicketStatusEnum;
|
||||||
use App\Models\Ticket;
|
use App\Models\Ticket;
|
||||||
|
use Illuminate\Pagination\LengthAwarePaginator;
|
||||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
use Illuminate\Foundation\Bus\DispatchesJobs;
|
use Illuminate\Foundation\Bus\DispatchesJobs;
|
||||||
use Illuminate\Foundation\Validation\ValidatesRequests;
|
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||||
|
|
@ -88,7 +89,7 @@ class Controller extends BaseController
|
||||||
string $search,
|
string $search,
|
||||||
callable $searchQuery = null,
|
callable $searchQuery = null,
|
||||||
string ...$fields
|
string ...$fields
|
||||||
): \Illuminate\Database\Eloquent\Builder {
|
): Builder {
|
||||||
if (count($fields)) {
|
if (count($fields)) {
|
||||||
// Search using words.
|
// Search using words.
|
||||||
$words = explode(' ', $search);
|
$words = explode(' ', $search);
|
||||||
|
|
@ -198,7 +199,7 @@ class Controller extends BaseController
|
||||||
* @param array $ignore
|
* @param array $ignore
|
||||||
* @return \Illuminate\Database\Eloquent\Builder
|
* @return \Illuminate\Database\Eloquent\Builder
|
||||||
*/
|
*/
|
||||||
protected function sortQuery(Builder $query, array $ignore = []): \Illuminate\Database\Eloquent\Builder
|
protected function sortQuery(Builder $query, array $ignore = []): Builder
|
||||||
{
|
{
|
||||||
$rName = request()->route()->getName();
|
$rName = request()->route()->getName();
|
||||||
$table = $query->getModel()->getTable();
|
$table = $query->getModel()->getTable();
|
||||||
|
|
@ -215,12 +216,13 @@ class Controller extends BaseController
|
||||||
Session::remove("$rName.sort_col");
|
Session::remove("$rName.sort_col");
|
||||||
Session::remove("$rName.sort_way");
|
Session::remove("$rName.sort_way");
|
||||||
}
|
}
|
||||||
if (request()->sort_col and request()->sort_way and Schema::hasColumn($table, request()->sort_col)) {
|
if (
|
||||||
if (
|
request()->sort_col &&
|
||||||
!in_array(request()->sort_col, $ignore)
|
request()->sort_way &&
|
||||||
) {
|
Schema::hasColumn($table, request()->sort_col) &&
|
||||||
$query = $query->orderBy(\sprintf("$table.%s", request()->sort_col), request()->sort_way);
|
(!isset($ignore) || (isset($ignore) && !in_array(request()->sort_col, $ignore)))
|
||||||
}
|
) {
|
||||||
|
$query = $query->orderBy("$table." . request()->sort_col, request()->sort_way);
|
||||||
}
|
}
|
||||||
return $query;
|
return $query;
|
||||||
}
|
}
|
||||||
|
|
@ -232,7 +234,7 @@ class Controller extends BaseController
|
||||||
* @param integer|null $pagination
|
* @param integer|null $pagination
|
||||||
* @return \Illuminate\Pagination\LengthAwarePaginator
|
* @return \Illuminate\Pagination\LengthAwarePaginator
|
||||||
*/
|
*/
|
||||||
protected function customPaginate(Builder $query, $pagination): \Illuminate\Pagination\LengthAwarePaginator
|
protected function customPaginate(Builder $query, $pagination): LengthAwarePaginator
|
||||||
{
|
{
|
||||||
if ($pagination) {
|
if ($pagination) {
|
||||||
Cache::put('pagination', $pagination);
|
Cache::put('pagination', $pagination);
|
||||||
|
|
|
||||||
|
|
@ -54,17 +54,17 @@ class Kernel extends HttpKernel
|
||||||
* @var array<string, class-string|string>
|
* @var array<string, class-string|string>
|
||||||
*/
|
*/
|
||||||
protected $routeMiddleware = [
|
protected $routeMiddleware = [
|
||||||
'auth' => \App\Http\Middleware\Authenticate::class,
|
'auth' => \App\Http\Middleware\Authenticate::class,
|
||||||
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
|
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
|
||||||
'auth.session' => \Illuminate\Session\Middleware\AuthenticateSession::class,
|
'auth.session' => \Illuminate\Session\Middleware\AuthenticateSession::class,
|
||||||
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
|
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
|
||||||
'can' => \Illuminate\Auth\Middleware\Authorize::class,
|
'can' => \Illuminate\Auth\Middleware\Authorize::class,
|
||||||
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
|
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
|
||||||
'is-admin' => \App\Http\Middleware\IsAdmin::class,
|
'is-admin' => \App\Http\Middleware\IsAdmin::class,
|
||||||
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
|
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
|
||||||
'signed' => \App\Http\Middleware\ValidateSignature::class,
|
'signed' => \App\Http\Middleware\ValidateSignature::class,
|
||||||
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
|
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
|
||||||
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
|
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
|
||||||
'htmlsanitize' => \App\Http\Middleware\HtmlSanitizer::class,
|
'htmlsanitize' => \App\Http\Middleware\HtmlSanitizer::class,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,5 +34,7 @@ class Authenticate extends Middleware
|
||||||
return route('login');
|
return route('login');
|
||||||
}
|
}
|
||||||
abort(401);
|
abort(401);
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ namespace App\Http\Middleware;
|
||||||
|
|
||||||
use App\Lib\Helpers\ToolboxHelper;
|
use App\Lib\Helpers\ToolboxHelper;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
class HtmlSanitizer
|
class HtmlSanitizer
|
||||||
{
|
{
|
||||||
|
|
@ -15,11 +16,8 @@ class HtmlSanitizer
|
||||||
* @param string|array ...$params
|
* @param string|array ...$params
|
||||||
* @return \Symfony\Component\HttpFoundation\Response
|
* @return \Symfony\Component\HttpFoundation\Response
|
||||||
*/
|
*/
|
||||||
public function handle(
|
public function handle(Request $request, \Closure $next, string|array ...$params): Response
|
||||||
Request $request,
|
{
|
||||||
\Closure $next,
|
|
||||||
string|array ...$params
|
|
||||||
): \Symfony\Component\HttpFoundation\Response {
|
|
||||||
$inputs = $request->all();
|
$inputs = $request->all();
|
||||||
/** @var callable|null */
|
/** @var callable|null */
|
||||||
$cleanInput = null;
|
$cleanInput = null;
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ namespace App\Http\Middleware;
|
||||||
|
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
class RedirectIfAuthenticated
|
class RedirectIfAuthenticated
|
||||||
{
|
{
|
||||||
|
|
@ -17,7 +18,7 @@ class RedirectIfAuthenticated
|
||||||
* @throws \RuntimeException If guard is unhandled.
|
* @throws \RuntimeException If guard is unhandled.
|
||||||
* @phpcs:disable Squiz.Commenting.FunctionComment.IncorrectTypeHint
|
* @phpcs:disable Squiz.Commenting.FunctionComment.IncorrectTypeHint
|
||||||
*/
|
*/
|
||||||
public function handle(Request $request, \Closure $next, ...$guards): \Symfony\Component\HttpFoundation\Response
|
public function handle(Request $request, \Closure $next, ...$guards): Response
|
||||||
{
|
{
|
||||||
// phpcs:enable phpcs:disable
|
// phpcs:enable phpcs:disable
|
||||||
$guards = empty($guards) ? [null] : $guards;
|
$guards = empty($guards) ? [null] : $guards;
|
||||||
|
|
@ -27,7 +28,7 @@ class RedirectIfAuthenticated
|
||||||
switch ($guard) {
|
switch ($guard) {
|
||||||
case 'backend':
|
case 'backend':
|
||||||
if (!$request->routeIs('bo.*') && !$request->routeIs('login')) {
|
if (!$request->routeIs('bo.*') && !$request->routeIs('login')) {
|
||||||
continue;
|
continue 2;
|
||||||
}
|
}
|
||||||
return \redirect()->route('bo.dashboard');
|
return \redirect()->route('bo.dashboard');
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
use Illuminate\Support\Facades\View;
|
use Illuminate\Support\Facades\View;
|
||||||
use Illuminate\Support\Facades\Vite;
|
use Illuminate\Support\Facades\Vite;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
class SecureHeaders
|
class SecureHeaders
|
||||||
{
|
{
|
||||||
|
|
@ -30,7 +31,7 @@ class SecureHeaders
|
||||||
* @return \Symfony\Component\HttpFoundation\Response
|
* @return \Symfony\Component\HttpFoundation\Response
|
||||||
* @phpcs:disable Squiz.Commenting.FunctionComment.IncorrectTypeHint
|
* @phpcs:disable Squiz.Commenting.FunctionComment.IncorrectTypeHint
|
||||||
*/
|
*/
|
||||||
public function handle(Request $request, Closure $next): \Symfony\Component\HttpFoundation\Response
|
public function handle(Request $request, Closure $next): Response
|
||||||
{
|
{
|
||||||
// phpcs:enable
|
// phpcs:enable
|
||||||
View::share('nonce', $nonce = Vite::useCspNonce());
|
View::share('nonce', $nonce = Vite::useCspNonce());
|
||||||
|
|
@ -88,12 +89,12 @@ class SecureHeaders
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove unwanted headers.
|
* Remove unwanted headers
|
||||||
*
|
*
|
||||||
* @param array $headerList
|
* @param array $headerList
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
private function removeUnwantedHeaders(array $headerList): void
|
private function removeUnwantedHeaders(array $headerList)
|
||||||
{
|
{
|
||||||
foreach ($headerList as $header) {
|
foreach ($headerList as $header) {
|
||||||
header_remove($header);
|
header_remove($header);
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ class TrustHosts extends Middleware
|
||||||
*
|
*
|
||||||
* @return array<int, string|null>
|
* @return array<int, string|null>
|
||||||
*/
|
*/
|
||||||
public function hosts(): array
|
public function hosts()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
$this->allSubdomainsOfApplicationUrl(),
|
$this->allSubdomainsOfApplicationUrl(),
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ class VerifyCsrfToken extends Middleware
|
||||||
* @var array<int, string>
|
* @var array<int, string>
|
||||||
*/
|
*/
|
||||||
protected $except = [
|
protected $except = [
|
||||||
'/csp-report'
|
'/csp-report',
|
||||||
|
'/brevo-in'
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ namespace App\Http\Requests\Bo;
|
||||||
|
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Foundation\Http\FormRequest;
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
use Illuminate\Support\Facades\Auth;
|
|
||||||
|
|
||||||
class AssignTicketToUserRequest extends FormRequest
|
class AssignTicketToUserRequest extends FormRequest
|
||||||
{
|
{
|
||||||
|
|
@ -13,11 +12,11 @@ class AssignTicketToUserRequest extends FormRequest
|
||||||
*
|
*
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public function authorize(): bool
|
public function authorize()
|
||||||
{
|
{
|
||||||
/** @var \App\Models\User $user */
|
/** @var \App\Models\User */
|
||||||
$user = Auth::user();
|
$user = auth()->user();
|
||||||
return Auth::check() and $user->isAdmin();
|
return auth()->check() and $user->isAdmin();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -25,14 +24,15 @@ class AssignTicketToUserRequest extends FormRequest
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function rules(): array
|
public function rules()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'assign' => [
|
'assign' => [
|
||||||
'nullable', 'exists:users,id',
|
'nullable', 'exists:users,id',
|
||||||
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
|
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
|
||||||
function ($attribute, $value, $fail) {
|
function ($attribute, $value, $fail) {
|
||||||
if ($user = User::query()->whereId($value)->first() and !$user->isAdmin()) {
|
/** @var \App\Models\User $user */
|
||||||
|
if ($user = User::whereId($value)->first() and !$user->isAdmin()) {
|
||||||
$fail(trans('Cet utilisateur ne peut se voir assigner un ticket'));
|
$fail(trans('Cet utilisateur ne peut se voir assigner un ticket'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ class StoreBrandRequest extends FormRequest
|
||||||
*
|
*
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public function authorize(): bool
|
public function authorize()
|
||||||
{
|
{
|
||||||
return Gate::allows('isAdmin');
|
return Gate::allows('isAdmin');
|
||||||
}
|
}
|
||||||
|
|
@ -22,11 +22,11 @@ class StoreBrandRequest extends FormRequest
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function rules(): array
|
public function rules()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'name' => 'required|string|min:3|max:255',
|
'name' => 'required|string|min:3|max:255',
|
||||||
'sites' => 'nullable|array',
|
'sites' => 'nullable|array',
|
||||||
'sites.*.id' => 'required|exists:sites,id'
|
'sites.*.id' => 'required|exists:sites,id'
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
@ -39,8 +39,8 @@ class StoreBrandRequest extends FormRequest
|
||||||
public function attributes(): array
|
public function attributes(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'name' => trans('Nom de la marque'),
|
'name' => trans('Nom de la marque'),
|
||||||
'sites' => trans('Sites associés à la marque'),
|
'sites' => trans('Sites associés à la marque'),
|
||||||
'sites.*.id' => trans('Élément parmis les sites associés à la marque'),
|
'sites.*.id' => trans('Élément parmis les sites associés à la marque'),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
50
app/Http/Requests/Bo/BrevoWebhookRequest.php
Normal file
50
app/Http/Requests/Bo/BrevoWebhookRequest.php
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Bo;
|
||||||
|
|
||||||
|
use Domain\Models\ValueObjects\Email;
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
use Illuminate\Support\Facades\Config;
|
||||||
|
|
||||||
|
class BrevoWebhookRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*/
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFromAddress(): Email
|
||||||
|
{
|
||||||
|
return new Email($this->string('items.0.From.Address'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getToAddress(): Email
|
||||||
|
{
|
||||||
|
return new Email((string) $this->input('items.0.To.0.Address'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRawHtmlBody(): string
|
||||||
|
{
|
||||||
|
return $this->string('items.0.RawHtmlBody');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
$expectedFormAddress = Config::string('mail.brevo_webook.expected_from_address');
|
||||||
|
|
||||||
|
return [
|
||||||
|
'items' => ['required', 'array', 'min:1'],
|
||||||
|
'items.0.From.Address' => ['required', 'email:rfc,spoof'],
|
||||||
|
'items.0.To.*.Address' => ['required', 'email:rfc,spoof', "in:{$expectedFormAddress}"],
|
||||||
|
'items.0.RawHtmlBody' => ['required', 'string', 'min:10'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -12,7 +12,7 @@ class ChangeTicketStatus extends FormRequest
|
||||||
*
|
*
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public function authorize(): bool
|
public function authorize()
|
||||||
{
|
{
|
||||||
/** @var \App\Models\User */
|
/** @var \App\Models\User */
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
|
|
@ -24,7 +24,7 @@ class ChangeTicketStatus extends FormRequest
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function rules(): array
|
public function rules()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'status' => [
|
'status' => [
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ class StoreCompanyRequest extends FormRequest
|
||||||
*
|
*
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public function authorize(): bool
|
public function authorize()
|
||||||
{
|
{
|
||||||
return Gate::allows('isAdmin');
|
return Gate::allows('isAdmin');
|
||||||
}
|
}
|
||||||
|
|
@ -22,7 +22,7 @@ class StoreCompanyRequest extends FormRequest
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function rules(): array
|
public function rules()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'name' => 'required|string|min:3|max:255',
|
'name' => 'required|string|min:3|max:255',
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ namespace App\Http\Requests\Bo;
|
||||||
|
|
||||||
use App\Enums\MessageTypeEnum;
|
use App\Enums\MessageTypeEnum;
|
||||||
use Illuminate\Foundation\Http\FormRequest;
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
use Illuminate\Support\Facades\Auth;
|
|
||||||
use Illuminate\Validation\Rules\Enum;
|
use Illuminate\Validation\Rules\Enum;
|
||||||
|
|
||||||
class CreateMessage extends FormRequest
|
class CreateMessage extends FormRequest
|
||||||
|
|
@ -14,11 +13,10 @@ class CreateMessage extends FormRequest
|
||||||
*
|
*
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public function authorize(): bool
|
public function authorize()
|
||||||
{
|
{
|
||||||
/** @var \App\Models\User|null $user */
|
/** @var \App\Models\User|null */
|
||||||
$user = Auth::user();
|
if (!($user = auth()->user())) {
|
||||||
if (!($user)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
|
|
@ -27,7 +25,7 @@ class CreateMessage extends FormRequest
|
||||||
) {
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return Auth::check() and $user->sites and ($user->isAdmin() or $user->sites->contains(
|
return auth()->check() and $user->sites and ($user->isAdmin() or $user->sites->contains(
|
||||||
$this->route()->ticket->site_id
|
$this->route()->ticket->site_id
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
@ -37,8 +35,10 @@ class CreateMessage extends FormRequest
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
protected function prepareForValidation(): void
|
protected function prepareForValidation()
|
||||||
{
|
{
|
||||||
|
/** @var \App\Models\User */
|
||||||
|
$user = auth()->user();
|
||||||
$this->merge([
|
$this->merge([
|
||||||
'subscribe' => $this->subscribe ? true : false,
|
'subscribe' => $this->subscribe ? true : false,
|
||||||
'type' => $this->is_private ? MessageTypeEnum::private->value : MessageTypeEnum::public->value
|
'type' => $this->is_private ? MessageTypeEnum::private->value : MessageTypeEnum::public->value
|
||||||
|
|
@ -50,15 +50,28 @@ class CreateMessage extends FormRequest
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function rules(): array
|
public function rules()
|
||||||
{
|
{
|
||||||
/** @var \App\Models\User $user */
|
/** @var \App\Models\User */
|
||||||
$user = Auth::user();
|
$user = auth()->user();
|
||||||
return [
|
return [
|
||||||
'subscribe' => 'required|boolean',
|
'subscribe' => 'required|boolean',
|
||||||
'message' => 'required|min:' . ($user->isAdmin() ? '5' : '20'),
|
'message' => [
|
||||||
|
'required',
|
||||||
|
'min:' . ($user->isAdmin() ? '5' : '20'),
|
||||||
|
function ($attribute, $value, $fail) {
|
||||||
|
$forbidden = ['merci de', 'merci de'];
|
||||||
|
foreach ($forbidden as $word) {
|
||||||
|
if (stripos(strtolower($value), $word) !== false) {
|
||||||
|
$fail(
|
||||||
|
"Le champs 'Message' contient la chaine de caractère non autorisée suivante : $word"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
],
|
||||||
'file_messages' => 'sometimes|array',
|
'file_messages' => 'sometimes|array',
|
||||||
'file_messages.*' => 'mimes:pptx,docx,xlsx,csv,txt,jpeg,jpg,png,pdf|max:2048',
|
'file_messages.*' => 'mimes:pptx,docx,xlsx,csv,txt,jpeg,jpg,png,pdf,svg|max:2048',
|
||||||
'type' => ['required', new Enum(MessageTypeEnum::class)]
|
'type' => ['required', new Enum(MessageTypeEnum::class)]
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ class AnswerEstimateRequest extends FormRequest
|
||||||
*
|
*
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public function authorize(): bool
|
public function authorize()
|
||||||
{
|
{
|
||||||
if (!auth()->check()) {
|
if (!auth()->check()) {
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -26,7 +26,7 @@ class AnswerEstimateRequest extends FormRequest
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
protected function prepareForValidation(): void
|
protected function prepareForValidation()
|
||||||
{
|
{
|
||||||
$this->merge([
|
$this->merge([
|
||||||
'answer' => $this->status === 'accept'
|
'answer' => $this->status === 'accept'
|
||||||
|
|
@ -38,7 +38,7 @@ class AnswerEstimateRequest extends FormRequest
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function rules(): array
|
public function rules()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'status' => 'required|in:accept,refuse',
|
'status' => 'required|in:accept,refuse',
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ class CreateEstimateRequest extends FormRequest
|
||||||
*
|
*
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public function authorize(): bool
|
public function authorize()
|
||||||
{
|
{
|
||||||
if (!auth()->check()) {
|
if (!auth()->check()) {
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -27,12 +27,12 @@ class CreateEstimateRequest extends FormRequest
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function rules(): array
|
public function rules()
|
||||||
{
|
{
|
||||||
/** @var \App\Models\Ticket */
|
/** @var \App\Models\Ticket */
|
||||||
$ticket = $this->ticket;
|
$ticket = $this->ticket;
|
||||||
return [
|
return [
|
||||||
'amount' => [
|
'amount' => [
|
||||||
'required',
|
'required',
|
||||||
'numeric',
|
'numeric',
|
||||||
'gt:0',
|
'gt:0',
|
||||||
|
|
@ -64,7 +64,7 @@ class CreateEstimateRequest extends FormRequest
|
||||||
public function attributes(): array
|
public function attributes(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'amount' => 'Montant',
|
'amount' => 'Montant',
|
||||||
'credit_account_id' => 'Compte à débiter'
|
'credit_account_id' => 'Compte à débiter'
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ class StoreCreditAccountRequest extends FormRequest
|
||||||
*
|
*
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public function authorize(): bool
|
public function authorize()
|
||||||
{
|
{
|
||||||
return Gate::allows('isAdmin');
|
return Gate::allows('isAdmin');
|
||||||
}
|
}
|
||||||
|
|
@ -24,11 +24,11 @@ class StoreCreditAccountRequest extends FormRequest
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function rules(): array
|
public function rules()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'label' => 'required|string|min:3|max:255',
|
'label' => 'required|string|min:3|max:255',
|
||||||
'type' => [
|
'type' => [
|
||||||
'required',
|
'required',
|
||||||
Rule::in(collect(AccountTypeEnum::cases())->pluck('value')->all()),
|
Rule::in(collect(AccountTypeEnum::cases())->pluck('value')->all()),
|
||||||
],
|
],
|
||||||
|
|
@ -44,8 +44,8 @@ class StoreCreditAccountRequest extends FormRequest
|
||||||
public function attributes(): array
|
public function attributes(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'label' => trans('Label du compte'),
|
'label' => trans('Label du compte'),
|
||||||
'type' => trans('Type du compte'),
|
'type' => trans('Type du compte'),
|
||||||
'balance' => trans('Solde du compte'),
|
'balance' => trans('Solde du compte'),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ class StoreCreditLogRequest extends FormRequest
|
||||||
*
|
*
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public function authorize(): bool
|
public function authorize()
|
||||||
{
|
{
|
||||||
return Gate::allows('isAdmin');
|
return Gate::allows('isAdmin');
|
||||||
}
|
}
|
||||||
|
|
@ -22,7 +22,7 @@ class StoreCreditLogRequest extends FormRequest
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function rules(): array
|
public function rules()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'amount' => [
|
'amount' => [
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ class StoreInformationRequest extends FormRequest
|
||||||
*
|
*
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public function authorize(): bool
|
public function authorize()
|
||||||
{
|
{
|
||||||
return Gate::allows('isAdmin');
|
return Gate::allows('isAdmin');
|
||||||
}
|
}
|
||||||
|
|
@ -24,12 +24,12 @@ class StoreInformationRequest extends FormRequest
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function rules(): array
|
public function rules()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'title' => 'required|string|min:3|max:255',
|
'title' => 'required|string|min:3|max:255',
|
||||||
'message' => 'required|string|min:3|max:255',
|
'message' => 'required|string|min:3|max:255',
|
||||||
'type' => [
|
'type' => [
|
||||||
'required',
|
'required',
|
||||||
Rule::in(collect(InfoColorsEnum::cases())->pluck('value')->all()),
|
Rule::in(collect(InfoColorsEnum::cases())->pluck('value')->all()),
|
||||||
],
|
],
|
||||||
|
|
@ -44,9 +44,9 @@ class StoreInformationRequest extends FormRequest
|
||||||
public function attributes(): array
|
public function attributes(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'title' => trans('Titre de l\'information'),
|
'title' => trans('Titre de l\'information'),
|
||||||
'message' => trans('Message de l\'information'),
|
'message' => trans('Message de l\'information'),
|
||||||
'type' => trans('Type d\'information'),
|
'type' => trans('Type d\'information'),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ class StoreInvoiceRequest extends FormRequest
|
||||||
*
|
*
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public function authorize(): bool
|
public function authorize()
|
||||||
{
|
{
|
||||||
return Gate::allows('isAdmin');
|
return Gate::allows('isAdmin');
|
||||||
}
|
}
|
||||||
|
|
@ -25,7 +25,7 @@ class StoreInvoiceRequest extends FormRequest
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
protected function prepareForValidation(): void
|
protected function prepareForValidation()
|
||||||
{
|
{
|
||||||
$this->merge([
|
$this->merge([
|
||||||
'tasks' => request()->tasks ? \collect(json_decode(request()->tasks))
|
'tasks' => request()->tasks ? \collect(json_decode(request()->tasks))
|
||||||
|
|
@ -41,7 +41,7 @@ class StoreInvoiceRequest extends FormRequest
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function rules(): array
|
public function rules()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'firstname' => 'required|string|min:3|max:255',
|
'firstname' => 'required|string|min:3|max:255',
|
||||||
|
|
@ -73,25 +73,25 @@ class StoreInvoiceRequest extends FormRequest
|
||||||
public function attributes(): array
|
public function attributes(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'firstname' => trans('Prénom de la personne associée'),
|
'firstname' => trans('Prénom de la personne associée'),
|
||||||
'lastname' => trans('Nom de la personne associée'),
|
'lastname' => trans('Nom de la personne associée'),
|
||||||
'object' => trans('Objet du devis'),
|
'object' => trans('Objet du devis'),
|
||||||
'tasks' => trans('Tâches du devis'),
|
'tasks' => trans('Tâches du devis'),
|
||||||
'tasks.*' => trans('Tâches du devis'),
|
'tasks.*' => trans('Tâches du devis'),
|
||||||
'tasks.*.days' => trans('Nombre de jours dédiés à la tâche'),
|
'tasks.*.days' => trans('Nombre de jours dédiés à la tâche'),
|
||||||
'tasks.*.amount' => trans('Montant dédié à la tâche'),
|
'tasks.*.amount' => trans('Montant dédié à la tâche'),
|
||||||
'tasks.*.desc' => trans('Description dédié à la tâche'),
|
'tasks.*.desc' => trans('Description dédié à la tâche'),
|
||||||
'tasks.*.type' => trans('Type de tâche'),
|
'tasks.*.type' => trans('Type de tâche'),
|
||||||
'tasks.*.package' => trans('Forfait dédié à la tâche'),
|
'tasks.*.package' => trans('Forfait dédié à la tâche'),
|
||||||
'comment' => trans('Commentaire du devis'),
|
'comment' => trans('Commentaire du devis'),
|
||||||
'show_days' => trans('Visibilité des jours'),
|
'show_days' => trans('Visibilité des jours'),
|
||||||
'site_id' => trans('Site associé'),
|
'site_id' => trans('Site associé'),
|
||||||
'company_id' => trans('Companie associé'),
|
'company_id' => trans('Companie associé'),
|
||||||
'invoiced_to_id' => trans('Entité à facturer'),
|
'invoiced_to_id' => trans('Entité à facturer'),
|
||||||
'signed_date' => trans('Date de signature du Devis'),
|
'signed_date' => trans('Date de signature du Devis'),
|
||||||
'sent_client_date' => trans('Date d\'envoi du Devis au client'),
|
'sent_client_date' => trans('Date d\'envoi du Devis au client'),
|
||||||
'sent_accounting_date' => trans('Date d\'envoi du Devis à la comptabilité'),
|
'sent_accounting_date' => trans('Date d\'envoi du Devis à la comptabilité'),
|
||||||
'status' => trans('État du devis'),
|
'status' => trans('État du devis'),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ class UpdateInvoiceRequest extends StoreInvoiceRequest
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function rules(): array
|
public function rules()
|
||||||
{
|
{
|
||||||
$rules = [];
|
$rules = [];
|
||||||
$model = $this->route('invoice');
|
$model = $this->route('invoice');
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ class StoreLabelRequest extends FormRequest
|
||||||
*
|
*
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public function authorize(): bool
|
public function authorize()
|
||||||
{
|
{
|
||||||
return Gate::allows('isAdmin');
|
return Gate::allows('isAdmin');
|
||||||
}
|
}
|
||||||
|
|
@ -23,10 +23,10 @@ class StoreLabelRequest extends FormRequest
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function rules(): array
|
public function rules()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'name' => 'required|string|min:2|max:255|unique:labels,name',
|
'name' => 'required|string|min:2|max:255|unique:labels,name',
|
||||||
'color' => [
|
'color' => [
|
||||||
'required',
|
'required',
|
||||||
new Hex(),
|
new Hex(),
|
||||||
|
|
@ -42,7 +42,7 @@ class StoreLabelRequest extends FormRequest
|
||||||
public function attributes(): array
|
public function attributes(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'name' => trans('validation.attributes.name'),
|
'name' => trans('validation.attributes.name'),
|
||||||
'color' => trans('validation.attributes.color'),
|
'color' => trans('validation.attributes.color'),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ class UpdateLabelRequest extends StoreLabelRequest
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function rules(): array
|
public function rules()
|
||||||
{
|
{
|
||||||
return array_merge(parent::rules(), [
|
return array_merge(parent::rules(), [
|
||||||
'name' => 'required|string|min:2|max:255|unique:labels,name,' . $this->route('label')->id . ',id',
|
'name' => 'required|string|min:2|max:255|unique:labels,name,' . $this->route('label')->id . ',id',
|
||||||
|
|
|
||||||
|
|
@ -12,21 +12,34 @@ class StorePackageRequest extends FormRequest
|
||||||
*
|
*
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public function authorize(): bool
|
public function authorize()
|
||||||
{
|
{
|
||||||
return Gate::allows('isAdmin');
|
return Gate::allows('isAdmin');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare the data for validation.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function prepareForValidation(): void
|
||||||
|
{
|
||||||
|
$this->merge([
|
||||||
|
'published' => $this->boolean('published'),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the validation rules that apply to the request.
|
* Get the validation rules that apply to the request.
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function rules(): array
|
public function rules()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'name' => 'required|string|min:3|max:255',
|
'name' => 'required|string|min:3|max:255',
|
||||||
'amount' => 'required|numeric|min:0|regex:/^\d+(\.\d{1,2})?$/',
|
'amount' => 'required|numeric|min:0|regex:/^\d+(\.\d{1,2})?$/',
|
||||||
|
'published' => 'required|boolean',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -38,8 +51,9 @@ class StorePackageRequest extends FormRequest
|
||||||
public function attributes(): array
|
public function attributes(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'name' => trans('Nom'),
|
'name' => trans('Nom'),
|
||||||
'amount' => trans('Montant (par jour)'),
|
'amount' => trans('Montant (par jour)'),
|
||||||
|
'published' => trans('Publication')
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Requests\Bo\Projects;
|
|
||||||
|
|
||||||
use Illuminate\Foundation\Http\FormRequest;
|
|
||||||
use Illuminate\Support\Facades\Gate;
|
|
||||||
|
|
||||||
class StoreProjectRequest extends FormRequest
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Determine if the user is authorized to make this request.
|
|
||||||
*
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
public function authorize(): bool
|
|
||||||
{
|
|
||||||
return Gate::allows('isAdmin');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the validation rules that apply to the request.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function rules(): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'name' => 'required|string|min:3|max:255|unique:projects,name',
|
|
||||||
'site_id' => 'required|exists:sites,id',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Requests\Bo\Projects;
|
|
||||||
|
|
||||||
class UpdateProjectRequest extends StoreProjectRequest
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Get the validation rules that apply to the request.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function rules(): array
|
|
||||||
{
|
|
||||||
return array_merge(parent::rules(), [
|
|
||||||
'name' => 'required|string|min:3|max:255|unique:projects,name,' . $this->route('project')->id . ',id',
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -12,7 +12,7 @@ class StoreSiteRequest extends FormRequest
|
||||||
*
|
*
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public function authorize(): bool
|
public function authorize()
|
||||||
{
|
{
|
||||||
return Gate::allows('isAdmin');
|
return Gate::allows('isAdmin');
|
||||||
}
|
}
|
||||||
|
|
@ -22,16 +22,16 @@ class StoreSiteRequest extends FormRequest
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function rules(): array
|
public function rules()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'name' => 'required|string|min:3|max:255',
|
'name' => 'required|string|min:3|max:255',
|
||||||
'users' => 'nullable|array',
|
'users' => 'nullable|array',
|
||||||
'users.*.id' => 'required|exists:users,id',
|
'users.*.id' => 'required|exists:users,id',
|
||||||
'gitlab_project_id' => 'nullable|unique:sites,gitlab_project_id',
|
'gitlab_project_id' => 'nullable',
|
||||||
'project_manager_id' => 'nullable|exists:users,id',
|
'project_manager_id' => 'nullable|exists:users,id',
|
||||||
'url_re7' => 'nullable|url',
|
'url_re7' => 'nullable|url',
|
||||||
'url_prod' => 'nullable|url'
|
'url_prod' => 'nullable|url'
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -43,13 +43,13 @@ class StoreSiteRequest extends FormRequest
|
||||||
public function attributes(): array
|
public function attributes(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'name' => trans('Nom du site'),
|
'name' => trans('Nom du site'),
|
||||||
'users' => trans('Utilisateurs associés au site'),
|
'users' => trans('Utilisateurs associés au site'),
|
||||||
'users.*.id' => trans('Élément parmis les Utilisateurs associés au site'),
|
'users.*.id' => trans('Élément parmis les Utilisateurs associés au site'),
|
||||||
'gitlab_project_id' => trans('ID du dépôt Gitlab'),
|
'gitlab_project_id' => trans('ID du dépôt Gitlab'),
|
||||||
'project_manager_id' => trans('Chef de projet'),
|
'project_manager_id' => trans('Chef de projet'),
|
||||||
'url_re7' => trans('Url de RECETTE'),
|
'url_re7' => trans('Url de RECETTE'),
|
||||||
'url_prod' => trans('Url de prod')
|
'url_prod' => trans('Url de prod')
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,15 +4,4 @@ namespace App\Http\Requests\Bo\Sites;
|
||||||
|
|
||||||
class UpdateSiteRequest extends StoreSiteRequest
|
class UpdateSiteRequest extends StoreSiteRequest
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Get the validation rules that apply to the request.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function rules(): array
|
|
||||||
{
|
|
||||||
return array_merge(parent::rules(), [
|
|
||||||
'gitlab_project_id' => 'nullable|unique:sites,gitlab_project_id,' . $this->route('site')->id . ',id',
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ class SortTickets extends FormRequest
|
||||||
*
|
*
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public function authorize(): bool
|
public function authorize()
|
||||||
{
|
{
|
||||||
return auth()->check();
|
return auth()->check();
|
||||||
}
|
}
|
||||||
|
|
@ -22,12 +22,12 @@ class SortTickets extends FormRequest
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function rules(): array
|
public function rules()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'search' => 'nullable|string',
|
'search' => 'nullable|string',
|
||||||
'sort_way' => 'sometimes|in:asc,desc',
|
'sort_way' => 'sometimes|in:asc,desc',
|
||||||
'status' => [
|
'status' => [
|
||||||
'sometimes',
|
'sometimes',
|
||||||
// @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
|
// @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
|
||||||
function ($attribute, $value, $fail) {
|
function ($attribute, $value, $fail) {
|
||||||
|
|
@ -38,7 +38,7 @@ class SortTickets extends FormRequest
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
'pr' => 'sometimes|int|exists:sites,id'
|
'pr' => 'sometimes|int|exists:sites,id'
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ class StoreTicket extends FormRequest
|
||||||
*
|
*
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public function authorize(): bool
|
public function authorize()
|
||||||
{
|
{
|
||||||
return auth()->check();
|
return auth()->check();
|
||||||
}
|
}
|
||||||
|
|
@ -24,7 +24,7 @@ class StoreTicket extends FormRequest
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
protected function prepareForValidation(): void
|
protected function prepareForValidation()
|
||||||
{
|
{
|
||||||
/** @var \App\Models\User|null */
|
/** @var \App\Models\User|null */
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
|
|
@ -97,10 +97,24 @@ class StoreTicket extends FormRequest
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
'date_mep' => 'nullable|date',
|
'date_mep' => 'nullable|date',
|
||||||
'text' => 'required|string|min:40',
|
'text' => [
|
||||||
|
'required',
|
||||||
|
'string',
|
||||||
|
'min:40',
|
||||||
|
function ($attribute, $value, $fail) {
|
||||||
|
$forbidden = ['merci de', 'merci de'];
|
||||||
|
foreach ($forbidden as $word) {
|
||||||
|
if (stripos(strtolower($value), $word) !== false) {
|
||||||
|
$fail(
|
||||||
|
"Le champs 'Description du ticket' contient la chaine de caractère non autorisée suivante : $word"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
],
|
||||||
'title' => 'required|string|between:3,255',
|
'title' => 'required|string|between:3,255',
|
||||||
'file_tickets' => 'sometimes|array',
|
'file_tickets' => 'sometimes|array',
|
||||||
'file_tickets.*' => 'mimes:pptx,docx,xlsx,csv,txt,jpeg,jpg,png,pdf|max:2048',
|
'file_tickets.*' => 'mimes:pptx,docx,xlsx,csv,txt,jpeg,jpg,png,pdf,svg|max:2048',
|
||||||
'is_internal' => 'required|boolean',
|
'is_internal' => 'required|boolean',
|
||||||
'labels' => 'sometimes|array',
|
'labels' => 'sometimes|array',
|
||||||
'labels.*' => [
|
'labels.*' => [
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ class UpdateTicketTypeRequest extends FormRequest
|
||||||
public function attributes(): array
|
public function attributes(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'type' => trans('Type'),
|
'type' => trans('Type'),
|
||||||
'template' => trans('Template'),
|
'template' => trans('Template'),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,6 @@
|
||||||
|
|
||||||
namespace App\Http\Requests\Bo;
|
namespace App\Http\Requests\Bo;
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
|
||||||
|
|
||||||
class UpdateTicket extends StoreTicket
|
class UpdateTicket extends StoreTicket
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
|
@ -13,12 +11,11 @@ class UpdateTicket extends StoreTicket
|
||||||
*/
|
*/
|
||||||
public function authorize(): bool
|
public function authorize(): bool
|
||||||
{
|
{
|
||||||
/** @var \App\Models\User|null $user */
|
/** @var \App\Models\User|null */
|
||||||
$user = Auth::user();
|
if (!($user = auth()->user())) {
|
||||||
if (!($user)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return Auth::check() and ($user->isAdmin() or
|
return auth()->check() and ($user->isAdmin() or
|
||||||
optional(request()->route()->ticket)->created_by === $user->id
|
optional(request()->route()->ticket)->created_by === $user->id
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
57
app/Http/Requests/Bo/UpdateTicketPriorityRequest.php
Normal file
57
app/Http/Requests/Bo/UpdateTicketPriorityRequest.php
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Bo;
|
||||||
|
|
||||||
|
use App\Models\Ticket;
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class UpdateTicketPriorityRequest extends FormRequest
|
||||||
|
{
|
||||||
|
private \App\Models\Ticket $ticket;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return auth()->check();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare the data for validation.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function prepareForValidation(): void
|
||||||
|
{
|
||||||
|
$this->ticket = $this->route('ticket');
|
||||||
|
$max = Ticket::query()->where('site_id', $this->ticket->site_id)->max('order');
|
||||||
|
|
||||||
|
$this->merge([
|
||||||
|
'priority' => min($this->integer('priority'), $max)
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'priority' => [
|
||||||
|
'required',
|
||||||
|
'integer',
|
||||||
|
'min:1',
|
||||||
|
function ($attribute, $value, $fail) {
|
||||||
|
if ($this->ticket && intval($value) === $this->ticket->order) {
|
||||||
|
$fail("La valeur de {$attribute} doit être différente de la valeur actuelle.");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
39
app/Http/Requests/Bo/Users/FavouriteSiteRequest.php
Normal file
39
app/Http/Requests/Bo/Users/FavouriteSiteRequest.php
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Bo\Users;
|
||||||
|
|
||||||
|
use Illuminate\Validation\Rule;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class FavouriteSiteRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return Auth::check();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
/** @var \App\Models\User|null $user */
|
||||||
|
$user = Auth::user();
|
||||||
|
|
||||||
|
return [
|
||||||
|
'favourite_site_id' => [
|
||||||
|
'nullable',
|
||||||
|
'exists:sites,id',
|
||||||
|
Rule::in($user->sites->pluck('id')),
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -14,28 +14,44 @@ class StoreUserRequest extends FormRequest
|
||||||
*
|
*
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public function authorize(): bool
|
public function authorize()
|
||||||
{
|
{
|
||||||
return Gate::allows('isAdmin');
|
return Gate::allows('isAdmin');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare the data for validation.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function prepareForValidation(): void
|
||||||
|
{
|
||||||
|
$this->merge([
|
||||||
|
'gitlab_id' => \boolval($this->input('gitlab_id')) ? $this->input('gitlab_id') : null
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the validation rules that apply to the request.
|
* Get the validation rules that apply to the request.
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function rules(): array
|
public function rules()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'name' => 'required|string|min:3|max:255',
|
'name' => 'required|string|min:3|max:255',
|
||||||
'email' => 'email|required|unique:users,email',
|
'email' => [
|
||||||
'role' => [
|
'email',
|
||||||
|
'required',
|
||||||
|
Rule::unique('users', 'email')->whereNull('deleted_at')
|
||||||
|
],
|
||||||
|
'role' => [
|
||||||
'required',
|
'required',
|
||||||
Rule::in(collect(RoleEnum::cases())->pluck('value')->all()),
|
Rule::in(collect(RoleEnum::cases())->pluck('value')->all()),
|
||||||
],
|
],
|
||||||
'sites' => 'nullable|array',
|
'sites' => 'nullable|array',
|
||||||
'sites.*.id' => 'required|exists:sites,id',
|
'sites.*.id' => 'required|exists:sites,id',
|
||||||
'gitlab_id' => 'nullable|integer|unique:users,gitlab_id'
|
'gitlab_id' => 'nullable|integer|unique:users,gitlab_id'
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -47,12 +63,12 @@ class StoreUserRequest extends FormRequest
|
||||||
public function attributes(): array
|
public function attributes(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'name' => trans('Nom de l\'utilisateur'),
|
'name' => trans('Nom de l\'utilisateur'),
|
||||||
'email' => trans('Email de l\'utilisateur'),
|
'email' => trans('Email de l\'utilisateur'),
|
||||||
'role' => trans('Rôle de l\'utilisateur'),
|
'role' => trans('Rôle de l\'utilisateur'),
|
||||||
'sites' => trans('Sites associés à l\'utilisateur'),
|
'sites' => trans('Sites associés à l\'utilisateur'),
|
||||||
'sites.*.id' => trans('Élément parmis les sites associés à l\'utilisateur'),
|
'sites.*.id' => trans('Élément parmis les sites associés à l\'utilisateur'),
|
||||||
'gitlab_id' => trans("ID de l'utilisateur Gitlab")
|
'gitlab_id' => trans("ID de l'utilisateur Gitlab")
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,10 +9,11 @@ class UpdateUserRequest extends StoreUserRequest
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function rules(): array
|
public function rules()
|
||||||
{
|
{
|
||||||
return array_merge(parent::rules(), [
|
return array_merge(parent::rules(), [
|
||||||
'email' => 'email|required|unique:users,email,' . $this->route('user')->id . ',id',
|
'email' => 'email|required|unique:users,email,' . $this->route('user')->id . ',id',
|
||||||
|
'gitlab_id' => 'nullable|integer|unique:users,gitlab_id,' . $this->route('user')->id . ',id'
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,17 +12,17 @@ class UserLabeledResource extends ResourceCollection
|
||||||
* Transform the resource collection into an array.
|
* Transform the resource collection into an array.
|
||||||
*
|
*
|
||||||
* @param \Illuminate\Http\Request $request
|
* @param \Illuminate\Http\Request $request
|
||||||
* @return \Illuminate\Support\Collection
|
* @return array
|
||||||
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
|
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
|
||||||
*/
|
*/
|
||||||
public function toArray(Request $request): \Illuminate\Support\Collection
|
public function toArray(Request $request)
|
||||||
{
|
{
|
||||||
// phpcs:enable
|
// phpcs:enable
|
||||||
return $this->collection->mapWithKeys(function (User $user, $key) {
|
return $this->collection->mapWithKeys(function (User $user, $key) {
|
||||||
return [
|
return [
|
||||||
$key => [
|
$key => [
|
||||||
'label' => sprintf('%d %s', $user->id, $user->name),
|
'label' => sprintf('%d %s', $user->id, $user->name),
|
||||||
'key' => $user->id
|
'key' => $user->id
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,11 @@ interface SpsConfigInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* URL method
|
* URL method
|
||||||
* Website (SP) url ex: https://le-gaulois-pro.s-web.test
|
* Website (SP) url ex: https://le-gaulois-pro.s-web.test
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function url(): string;
|
public function url(): string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* acsBase64 method
|
* acsBase64 method
|
||||||
* Return destination url base64 encoded
|
* Return destination url base64 encoded
|
||||||
|
|
@ -19,7 +18,6 @@ interface SpsConfigInterface
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function acsBase64(): string;
|
public function acsBase64(): string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* destination method
|
* destination method
|
||||||
* Return acs url concatenated with url
|
* Return acs url concatenated with url
|
||||||
|
|
@ -27,7 +25,6 @@ interface SpsConfigInterface
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function destination(): string;
|
public function destination(): string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* logout method
|
* logout method
|
||||||
* Return sls url concatenated with url
|
* Return sls url concatenated with url
|
||||||
|
|
@ -35,7 +32,6 @@ interface SpsConfigInterface
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function logout(): string;
|
public function logout(): string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* certificate method
|
* certificate method
|
||||||
* Return certificate (.pem) file from kebab case of Enum name
|
* Return certificate (.pem) file from kebab case of Enum name
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ class AutoCloseOldTickets
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function handle(): void
|
public function handle()
|
||||||
{
|
{
|
||||||
$limitDays = 15;
|
$limitDays = 15;
|
||||||
$message = 'En l\'absence d\'activitée depuis 15 jours ce ticket est automatiquement clos et archivé.';
|
$message = 'En l\'absence d\'activitée depuis 15 jours ce ticket est automatiquement clos et archivé.';
|
||||||
|
|
|
||||||
117
app/Jobs/ExportTicketsState.php
Normal file
117
app/Jobs/ExportTicketsState.php
Normal file
|
|
@ -0,0 +1,117 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Jobs;
|
||||||
|
|
||||||
|
use App\Enums\Tickets\TicketStatusEnum;
|
||||||
|
use App\Models\Site;
|
||||||
|
use App\Models\Ticket;
|
||||||
|
use App\Notifications\ExportTicketsStateNotification;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Foundation\Queue\Queueable;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
use Illuminate\Support\Facades\Notification;
|
||||||
|
|
||||||
|
class ExportTicketsState implements ShouldQueue
|
||||||
|
{
|
||||||
|
use Queueable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CSV File headers
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $header = [
|
||||||
|
"Priorité service",
|
||||||
|
"Site",
|
||||||
|
"Numéro de ticket",
|
||||||
|
"Priorité",
|
||||||
|
"Date de MEP souhaitée",
|
||||||
|
"Type de ticket",
|
||||||
|
"Titre du ticket",
|
||||||
|
"Statut du ticket",
|
||||||
|
"Chef de projet",
|
||||||
|
"Utilisateur assigné",
|
||||||
|
"Date de dernière activité",
|
||||||
|
"Date de création",
|
||||||
|
"Lien vers le ticket",
|
||||||
|
"Lien vers l'issue GitLab"
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the job.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function handle(): void
|
||||||
|
{
|
||||||
|
// L'ordre commence à 0 et reprendra à 1 pour chaque site.
|
||||||
|
$order = 0;
|
||||||
|
// Dernier site traité.
|
||||||
|
$lastSiteId = null;
|
||||||
|
// Insertion de la ligne d'en-têtes.
|
||||||
|
$csvlines[] = $this->header;
|
||||||
|
|
||||||
|
// Récupération des tickets.
|
||||||
|
Ticket::query()
|
||||||
|
->whereNotIn(
|
||||||
|
'status',
|
||||||
|
[TicketStatusEnum::archived, TicketStatusEnum::production]
|
||||||
|
)
|
||||||
|
->orderBy(Site::select('name')
|
||||||
|
->whereColumn('sites.id', 'tickets.site_id'))
|
||||||
|
->orderBy('order')->get()->each(function (Ticket $ticket) use (&$csvlines, &$lastSiteId, &$order) {
|
||||||
|
$csvlines[] = [
|
||||||
|
"",
|
||||||
|
$ticket->site->name,
|
||||||
|
$ticket->id,
|
||||||
|
$lastSiteId === $ticket->site_id ? $order + 1 : 1,
|
||||||
|
$ticket->date_mep?->format('d-m-Y') ?? 'No MEP Date',
|
||||||
|
$ticket->type->label(),
|
||||||
|
$ticket->title,
|
||||||
|
$ticket->status->label(),
|
||||||
|
$ticket->projectManager->name ?? 'No PM',
|
||||||
|
$ticket->assignedUser()->name ?? 'No Assigned User',
|
||||||
|
Carbon::create($ticket->getRawOriginal('last_activity'))->format('d-m-Y H:i:s'),
|
||||||
|
$ticket->created_at->format('d-m-Y H:i:s'),
|
||||||
|
route('bo.ticket.show', $ticket->id),
|
||||||
|
$ticket->gitlab_issue ?? 'No GitLab Issue'
|
||||||
|
];
|
||||||
|
|
||||||
|
$order = $lastSiteId === $ticket->site_id ? $order + 1 : 1;
|
||||||
|
$lastSiteId = $ticket->site_id;
|
||||||
|
});
|
||||||
|
|
||||||
|
Notification::route('mail', config('mail.MAIL_ADMIN'))
|
||||||
|
->notify(new ExportTicketsStateNotification($this->array2csv($csvlines, ";")));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* converts an array to a csv stream
|
||||||
|
*
|
||||||
|
* @param array $data
|
||||||
|
* @param string $delimiter
|
||||||
|
* @param string $enclosure
|
||||||
|
* @param string $escape_char
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function array2csv(
|
||||||
|
array $data,
|
||||||
|
string $delimiter = ',',
|
||||||
|
string $enclosure = '"',
|
||||||
|
string $escape_char = "\\"
|
||||||
|
) {
|
||||||
|
$f = fopen('php://memory', 'r+');
|
||||||
|
|
||||||
|
// UTF-8 BOM.
|
||||||
|
$BOM = "\xEF\xBB\xBF";
|
||||||
|
fwrite($f, $BOM);
|
||||||
|
|
||||||
|
foreach ($data as $item) {
|
||||||
|
fputcsv($f, $item, $delimiter, $enclosure, $escape_char);
|
||||||
|
}
|
||||||
|
rewind($f);
|
||||||
|
return stream_get_contents($f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -39,7 +39,7 @@ class SendTicketMentionMail implements ShouldQueue
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function handle(): void
|
public function handle()
|
||||||
{
|
{
|
||||||
Mail::to($this->user->email)->send($this->mail);
|
Mail::to($this->user->email)->send($this->mail);
|
||||||
Log::debug(sprintf('Mention mail sent to %s', $this->user->email));
|
Log::debug(sprintf('Mention mail sent to %s', $this->user->email));
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ class SendUserCreatedEmail implements ShouldQueue
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function handle(): void
|
public function handle()
|
||||||
{
|
{
|
||||||
Mail::to(['email' => $this->user->email])
|
Mail::to(['email' => $this->user->email])
|
||||||
->send(new UserCreatedMail($this->user));
|
->send(new UserCreatedMail($this->user));
|
||||||
|
|
|
||||||
85
app/Jobs/UpdateIssueLabels.php
Normal file
85
app/Jobs/UpdateIssueLabels.php
Normal file
|
|
@ -0,0 +1,85 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Jobs;
|
||||||
|
|
||||||
|
use App\Models\Ticket;
|
||||||
|
use App\Enums\Tickets\TicketStatusEnum;
|
||||||
|
use Illuminate\Foundation\Queue\Queueable;
|
||||||
|
use App\Traits\Controllers\HasGitlabIssue;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use App\Http\Requests\Bo\ChangeTicketStatus;
|
||||||
|
|
||||||
|
class UpdateIssueLabels implements ShouldQueue
|
||||||
|
{
|
||||||
|
use Queueable;
|
||||||
|
use HasGitlabIssue;
|
||||||
|
|
||||||
|
/** @var Ticket */
|
||||||
|
protected $ticket;
|
||||||
|
|
||||||
|
/** @var requestStatus */
|
||||||
|
protected $requestStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new job instance.
|
||||||
|
*
|
||||||
|
* @param \App\Models\Ticket $ticket
|
||||||
|
* @param string $request
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct(Ticket $ticket, string $requestStatus)
|
||||||
|
{
|
||||||
|
$this->ticket = $ticket;
|
||||||
|
$this->requestStatus = $requestStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the job.
|
||||||
|
*/
|
||||||
|
public function handle(): void
|
||||||
|
{
|
||||||
|
$oldStatus = $this->ticket->status;
|
||||||
|
$requestStatus = (int) $this->requestStatus;
|
||||||
|
$gitlabIssue = $this->getGitlabIssue($this->ticket->site->gitlab_project_id, $this->ticket->gitlab_issue);
|
||||||
|
|
||||||
|
$issueLabels = $gitlabIssue['labels'];
|
||||||
|
|
||||||
|
if ($oldStatus === TicketStatusEnum::waiting && $requestStatus !== TicketStatusEnum::waiting->value) {
|
||||||
|
$issueLabels = array_values(array_diff($issueLabels, ['g-wait']));
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($requestStatus) {
|
||||||
|
case TicketStatusEnum::takenInAccount->value:
|
||||||
|
$newLabels = ['g-to-dispatch'];
|
||||||
|
$updatedLabels = array_unique(array_merge($issueLabels, $newLabels));
|
||||||
|
|
||||||
|
$updatedIssue = $this->updateGitlabIssueLabels($gitlabIssue['project_id'], $gitlabIssue['iid'], $updatedLabels);
|
||||||
|
break;
|
||||||
|
case TicketStatusEnum::waiting->value:
|
||||||
|
$newLabels = ['g-wait'];
|
||||||
|
$updatedLabels = array_unique(array_merge($issueLabels, $newLabels));
|
||||||
|
|
||||||
|
$updatedIssue = $this->updateGitlabIssueLabels($gitlabIssue['project_id'], $gitlabIssue['iid'], $updatedLabels);
|
||||||
|
break;
|
||||||
|
case TicketStatusEnum::waitingValidation->value:
|
||||||
|
$removeLabels = ['g-to-estimate'];
|
||||||
|
$updatedLabels = array_diff($issueLabels, $removeLabels);
|
||||||
|
|
||||||
|
$updatedIssue = $this->updateGitlabIssueLabels($gitlabIssue['project_id'], $gitlabIssue['iid'], $updatedLabels);
|
||||||
|
break;
|
||||||
|
case TicketStatusEnum::recetteValidated->value:
|
||||||
|
$newLabels = ['g-re7-ok', 'to-prod'];
|
||||||
|
$updatedLabels = array_unique(array_merge($issueLabels, $newLabels));
|
||||||
|
|
||||||
|
$updatedIssue = $this->updateGitlabIssueLabels($gitlabIssue['project_id'], $gitlabIssue['iid'], $updatedLabels);
|
||||||
|
break;
|
||||||
|
case TicketStatusEnum::archived->value:
|
||||||
|
$updatedIssue = $this->closeGitlabIssue($gitlabIssue['project_id'], $gitlabIssue['iid'], $issueLabels);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$updatedIssue = $this->updateGitlabIssueLabels($gitlabIssue['project_id'], $gitlabIssue['iid'], $issueLabels);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -15,7 +15,7 @@ class WarnBeforeAutoCloseTicket
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function handle(): void
|
public function handle()
|
||||||
{
|
{
|
||||||
$warningDays = 7;
|
$warningDays = 7;
|
||||||
// phpcs:ignore Generic.Files.LineLength.TooLong
|
// phpcs:ignore Generic.Files.LineLength.TooLong
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ class CollectionHelper
|
||||||
* @param integer $pageSize
|
* @param integer $pageSize
|
||||||
* @return \Illuminate\Pagination\LengthAwarePaginator
|
* @return \Illuminate\Pagination\LengthAwarePaginator
|
||||||
*/
|
*/
|
||||||
public static function paginate(Collection $results, int $pageSize): \Illuminate\Pagination\LengthAwarePaginator
|
public static function paginate(Collection $results, int $pageSize): LengthAwarePaginator
|
||||||
{
|
{
|
||||||
$page = Paginator::resolveCurrentPage('page');
|
$page = Paginator::resolveCurrentPage('page');
|
||||||
|
|
||||||
|
|
@ -31,11 +31,8 @@ class CollectionHelper
|
||||||
* @param integer $page
|
* @param integer $page
|
||||||
* @return \Illuminate\Pagination\LengthAwarePaginator
|
* @return \Illuminate\Pagination\LengthAwarePaginator
|
||||||
*/
|
*/
|
||||||
public static function paginateManually(
|
public static function paginateManually(Collection $results, int $pageSize, int $page = 1): LengthAwarePaginator
|
||||||
Collection $results,
|
{
|
||||||
int $pageSize,
|
|
||||||
int $page = 1
|
|
||||||
): \Illuminate\Pagination\LengthAwarePaginator {
|
|
||||||
$total = $results->count();
|
$total = $results->count();
|
||||||
|
|
||||||
return self::paginator($results->forPage($page, $pageSize), $total, $pageSize, $page, [
|
return self::paginator($results->forPage($page, $pageSize), $total, $pageSize, $page, [
|
||||||
|
|
@ -54,19 +51,14 @@ class CollectionHelper
|
||||||
* @param array $options
|
* @param array $options
|
||||||
* @return \Illuminate\Pagination\LengthAwarePaginator
|
* @return \Illuminate\Pagination\LengthAwarePaginator
|
||||||
*/
|
*/
|
||||||
protected static function paginator(
|
protected static function paginator(Collection $items, int $total, int $perPage, int $currentPage, array $options)
|
||||||
Collection $items,
|
{
|
||||||
int $total,
|
|
||||||
int $perPage,
|
|
||||||
int $currentPage,
|
|
||||||
array $options
|
|
||||||
): \Illuminate\Pagination\LengthAwarePaginator {
|
|
||||||
return Container::getInstance()->makeWith(LengthAwarePaginator::class, [
|
return Container::getInstance()->makeWith(LengthAwarePaginator::class, [
|
||||||
'items' => $items,
|
'items' => $items,
|
||||||
'total' => $total,
|
'total' => $total,
|
||||||
'perPage' => $perPage,
|
'perPage' => $perPage,
|
||||||
'currentPage' => $currentPage,
|
'currentPage' => $currentPage,
|
||||||
'options' => $options
|
'options' => $options
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ namespace App\Lib\Helpers;
|
||||||
class ExceptionsHelper
|
class ExceptionsHelper
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Handle sentry event.
|
* Handle sentry event
|
||||||
*
|
*
|
||||||
* @param \Sentry\Event $event
|
* @param \Sentry\Event $event
|
||||||
* @return null|\Sentry\Event
|
* @return null|\Sentry\Event
|
||||||
|
|
@ -26,7 +26,7 @@ class ExceptionsHelper
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Anonimize Sentry Exception bag.
|
* Anonimize Sentry Exception bag
|
||||||
*
|
*
|
||||||
* @param \Sentry\ExceptionDataBag $exceptionDataBag
|
* @param \Sentry\ExceptionDataBag $exceptionDataBag
|
||||||
* @return \Sentry\ExceptionDataBag
|
* @return \Sentry\ExceptionDataBag
|
||||||
|
|
@ -42,7 +42,7 @@ class ExceptionsHelper
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Anonymise sentry stacktrace.
|
* Anonymise sentry stacktrace
|
||||||
*
|
*
|
||||||
* @param \Sentry\Stacktrace $stackTrace
|
* @param \Sentry\Stacktrace $stackTrace
|
||||||
* @return \Sentry\Stacktrace
|
* @return \Sentry\Stacktrace
|
||||||
|
|
@ -70,7 +70,7 @@ class ExceptionsHelper
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get anonymized sentry params.
|
* Get anonymized sentry params
|
||||||
*
|
*
|
||||||
* @param mixed[] $params
|
* @param mixed[] $params
|
||||||
* @return string[]
|
* @return string[]
|
||||||
|
|
@ -105,7 +105,7 @@ class ExceptionsHelper
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Anonymize at least Sql queries.
|
* Anonymize at least Sql queries
|
||||||
*
|
*
|
||||||
* @param string $message
|
* @param string $message
|
||||||
* @return string
|
* @return string
|
||||||
|
|
@ -120,7 +120,7 @@ class ExceptionsHelper
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Anonymize stack trace.
|
* Anonymize stack trace
|
||||||
*
|
*
|
||||||
* @param \Throwable $e
|
* @param \Throwable $e
|
||||||
* @return string
|
* @return string
|
||||||
|
|
@ -159,7 +159,7 @@ class ExceptionsHelper
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle Args.
|
* Handle Args
|
||||||
*
|
*
|
||||||
* @param array $stack
|
* @param array $stack
|
||||||
* @return string
|
* @return string
|
||||||
|
|
|
||||||
|
|
@ -175,7 +175,7 @@ class FileStorageHelper
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove all old files from string attribute html that are stored in public that
|
* Remove all old files from string attribute html that are stored in public that
|
||||||
* are nove present anymore on new html string.
|
* are nove present anymore on new html string
|
||||||
*
|
*
|
||||||
* @param string $newHtmlString The html string with alreadyParsed files using storeModelFilesFromHtml.
|
* @param string $newHtmlString The html string with alreadyParsed files using storeModelFilesFromHtml.
|
||||||
* @param string $oldHtmlString The old html string with alreadyParsed files using storeModelFilesFromHtml.
|
* @param string $oldHtmlString The old html string with alreadyParsed files using storeModelFilesFromHtml.
|
||||||
|
|
@ -188,7 +188,7 @@ class FileStorageHelper
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove all old files that are stored in public that
|
* Remove all old files that are stored in public that
|
||||||
* are not present anymore on new array files.
|
* are not present anymore on new array files
|
||||||
*
|
*
|
||||||
* @param string[] $oldFiles The old array files.
|
* @param string[] $oldFiles The old array files.
|
||||||
* @param string[] $newFiles The new array files.
|
* @param string[] $newFiles The new array files.
|
||||||
|
|
@ -208,7 +208,7 @@ class FileStorageHelper
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove all files from string attribute html that are stored in public.
|
* Remove all files from string attribute html that are stored in public
|
||||||
*
|
*
|
||||||
* @param string $htmlString The html string with alreadyParsed files using storeModelFilesFromHtml.
|
* @param string $htmlString The html string with alreadyParsed files using storeModelFilesFromHtml.
|
||||||
* @return void
|
* @return void
|
||||||
|
|
@ -225,7 +225,7 @@ class FileStorageHelper
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find all occurence of files in html.
|
* Find all occurence of files in html
|
||||||
*
|
*
|
||||||
* @param string $html
|
* @param string $html
|
||||||
* @return array
|
* @return array
|
||||||
|
|
@ -241,7 +241,7 @@ class FileStorageHelper
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filter array to get only uploaded files that exists
|
* Filter array to get only uploaded files that exists
|
||||||
* on disk 'public' (using helper storage strategy).
|
* on disk 'public' (using helper storage strategy)
|
||||||
*
|
*
|
||||||
* @param array $urls
|
* @param array $urls
|
||||||
* @return array
|
* @return array
|
||||||
|
|
@ -261,7 +261,8 @@ class FileStorageHelper
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filter array to get only uploaded files that exists on disk 'uploads'.
|
* Filter array to get only uploaded files that exists
|
||||||
|
* on disk 'uploads'
|
||||||
*
|
*
|
||||||
* @param array $urls
|
* @param array $urls
|
||||||
* @return array
|
* @return array
|
||||||
|
|
@ -283,7 +284,8 @@ class FileStorageHelper
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare storage path and return the file full path.
|
* Prepare storage path and return
|
||||||
|
* the file full path
|
||||||
*
|
*
|
||||||
* @param string $tableName Model table name.
|
* @param string $tableName Model table name.
|
||||||
* @param string $filename The basename for the file.
|
* @param string $filename The basename for the file.
|
||||||
|
|
@ -314,7 +316,7 @@ class FileStorageHelper
|
||||||
/**
|
/**
|
||||||
* Create sub folders to store files using pattern
|
* Create sub folders to store files using pattern
|
||||||
* storage/modelfiles/posts/10/04/19/5f
|
* storage/modelfiles/posts/10/04/19/5f
|
||||||
* year/month/day/md5 first 2 letters.
|
* year/month/day/md5 first 2 letters
|
||||||
*
|
*
|
||||||
* @param string $storage_dir
|
* @param string $storage_dir
|
||||||
* @param string $table
|
* @param string $table
|
||||||
|
|
@ -340,7 +342,7 @@ class FileStorageHelper
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get unique filename if the path is already occupied.
|
* Get unique filename if the path is already occupied
|
||||||
*
|
*
|
||||||
* @param string $folderPath
|
* @param string $folderPath
|
||||||
* @param string $filename
|
* @param string $filename
|
||||||
|
|
@ -363,7 +365,7 @@ class FileStorageHelper
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Slugify the filename.
|
* Slugify the filename
|
||||||
*
|
*
|
||||||
* @param string $filename
|
* @param string $filename
|
||||||
* @return string
|
* @return string
|
||||||
|
|
@ -374,7 +376,7 @@ class FileStorageHelper
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sanitize File name for uploaded files.
|
* Sanitize File name for uploaded files
|
||||||
*
|
*
|
||||||
* @param string $filename The original uploaded client file name.
|
* @param string $filename The original uploaded client file name.
|
||||||
* @param boolean $beautify Beautify the filename.
|
* @param boolean $beautify Beautify the filename.
|
||||||
|
|
@ -400,7 +402,7 @@ class FileStorageHelper
|
||||||
$filename = Str::of($filename)->ltrim('.-');
|
$filename = Str::of($filename)->ltrim('.-');
|
||||||
// * Optional beautification
|
// * Optional beautification
|
||||||
if ($beautify) {
|
if ($beautify) {
|
||||||
$filename = self::beautifyFilename($filename);
|
$filename = static::beautifyFilename($filename);
|
||||||
}
|
}
|
||||||
// * Maximize filename length to 255 bytes http://serverfault.com/a/9548/44086
|
// * Maximize filename length to 255 bytes http://serverfault.com/a/9548/44086
|
||||||
/** @var string */
|
/** @var string */
|
||||||
|
|
@ -419,7 +421,7 @@ class FileStorageHelper
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Beautify a filename.
|
* Beautify a filename
|
||||||
*
|
*
|
||||||
* @param string $filename
|
* @param string $filename
|
||||||
* @return string
|
* @return string
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
namespace App\Lib\Helpers;
|
namespace App\Lib\Helpers;
|
||||||
|
|
||||||
|
use Illuminate\Contracts\Database\Eloquent\Builder;
|
||||||
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\File;
|
use Illuminate\Support\Facades\File;
|
||||||
|
|
@ -57,7 +57,7 @@ class ToolboxHelper
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check uri points to image file.
|
* Check uri points to image file
|
||||||
*
|
*
|
||||||
* @param string $url
|
* @param string $url
|
||||||
* @return boolean
|
* @return boolean
|
||||||
|
|
@ -69,7 +69,7 @@ class ToolboxHelper
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check uri points to pdf file.
|
* Check uri points to pdf file
|
||||||
*
|
*
|
||||||
* @param string $url
|
* @param string $url
|
||||||
* @return boolean
|
* @return boolean
|
||||||
|
|
@ -85,7 +85,7 @@ class ToolboxHelper
|
||||||
* Only embed allowed are for MP4 self hosted videos right now
|
* Only embed allowed are for MP4 self hosted videos right now
|
||||||
*
|
*
|
||||||
* https is force by ckeditor MediaElements which natively supports
|
* https is force by ckeditor MediaElements which natively supports
|
||||||
* only cloud hosted medias (youtube, spotify etc..).
|
* only cloud hosted medias (youtube, spotify etc..)
|
||||||
*
|
*
|
||||||
* @param string $input
|
* @param string $input
|
||||||
* @return string
|
* @return string
|
||||||
|
|
@ -97,7 +97,7 @@ class ToolboxHelper
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assert That no Back Office url is present on txt.
|
* Assert That no Back Office url is present on txt
|
||||||
*
|
*
|
||||||
* @param string $field
|
* @param string $field
|
||||||
* @param string $text
|
* @param string $text
|
||||||
|
|
@ -140,7 +140,7 @@ class ToolboxHelper
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assert That only external url is present on txt.
|
* Assert That only external url is present on txt
|
||||||
*
|
*
|
||||||
* @param string $field
|
* @param string $field
|
||||||
* @param string $text
|
* @param string $text
|
||||||
|
|
@ -184,7 +184,7 @@ class ToolboxHelper
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assert Is Unique.
|
* Assert Is Unique
|
||||||
*
|
*
|
||||||
* @param \Illuminate\Database\Eloquent\Model $model
|
* @param \Illuminate\Database\Eloquent\Model $model
|
||||||
* @param array<string> $columns
|
* @param array<string> $columns
|
||||||
|
|
@ -235,7 +235,7 @@ class ToolboxHelper
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mutltibyte string replace.
|
* Mutltibyte string replace
|
||||||
*
|
*
|
||||||
* @param array|string $search
|
* @param array|string $search
|
||||||
* @param array|string $replace
|
* @param array|string $replace
|
||||||
|
|
@ -279,7 +279,7 @@ class ToolboxHelper
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asserts that the field is unique.
|
* Asserts that the field is unique
|
||||||
*
|
*
|
||||||
* @param string $table
|
* @param string $table
|
||||||
* @param string $field
|
* @param string $field
|
||||||
|
|
@ -295,7 +295,7 @@ class ToolboxHelper
|
||||||
string|int|float|bool|null|array $value,
|
string|int|float|bool|null|array $value,
|
||||||
?int $id = null,
|
?int $id = null,
|
||||||
?callable $query = null
|
?callable $query = null
|
||||||
): void {
|
) {
|
||||||
if (!$query) {
|
if (!$query) {
|
||||||
Validator::make([$field => $value], [
|
Validator::make([$field => $value], [
|
||||||
self::mbReplace('.', '\.', $field) => Rule::unique($table, $field)->ignore($id),
|
self::mbReplace('.', '\.', $field) => Rule::unique($table, $field)->ignore($id),
|
||||||
|
|
@ -316,7 +316,7 @@ class ToolboxHelper
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get original polyfill with autotranslate behavior.
|
* Get original polyfill with autotranslate behavior
|
||||||
*
|
*
|
||||||
* @param \Illuminate\Database\Eloquent\Model $model
|
* @param \Illuminate\Database\Eloquent\Model $model
|
||||||
* @param string $attribute
|
* @param string $attribute
|
||||||
|
|
@ -335,20 +335,20 @@ class ToolboxHelper
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dynamic model query.
|
* Dynamic model query
|
||||||
*
|
*
|
||||||
* @param string $defaultLocale
|
* @param string $defaultLocale
|
||||||
* @param \Illuminate\Database\Eloquent\Builder $q
|
* @param \Illuminate\Contracts\Database\Eloquent\Builder $q
|
||||||
* @param string $column
|
* @param string $column
|
||||||
* @param string $value
|
* @param string $value
|
||||||
* @return \Illuminate\Database\Eloquent\Builder
|
* @return \Illuminate\Contracts\Database\Eloquent\Builder
|
||||||
*/
|
*/
|
||||||
public static function queryColumnWithLocales(
|
public static function queryColumnWithLocales(
|
||||||
string $defaultLocale,
|
string $defaultLocale,
|
||||||
Builder $q,
|
Builder $q,
|
||||||
string $column,
|
string $column,
|
||||||
string $value
|
string $value
|
||||||
): \Illuminate\Contracts\Database\Eloquent\Builder {
|
): Builder {
|
||||||
$currentLocale = app()->currentLocale();
|
$currentLocale = app()->currentLocale();
|
||||||
$locales = collect(config('app.locales'))
|
$locales = collect(config('app.locales'))
|
||||||
->mapWithKeys(fn(string $locale) => [$locale => $locale]);
|
->mapWithKeys(fn(string $locale) => [$locale => $locale]);
|
||||||
|
|
@ -376,7 +376,7 @@ class ToolboxHelper
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates an array from a dot separated string.
|
* Generates an array from a dot separated string
|
||||||
*
|
*
|
||||||
* @param string $path
|
* @param string $path
|
||||||
* @param mixed $value
|
* @param mixed $value
|
||||||
|
|
@ -395,7 +395,7 @@ class ToolboxHelper
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert deeply an object to array.
|
* Convert deeply an object to array
|
||||||
*
|
*
|
||||||
* @param array|object $input
|
* @param array|object $input
|
||||||
* @return array
|
* @return array
|
||||||
|
|
@ -418,7 +418,7 @@ class ToolboxHelper
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert deeply an array to object.
|
* Convert deeply an array to object
|
||||||
*
|
*
|
||||||
* @param array|object $input
|
* @param array|object $input
|
||||||
* @return object
|
* @return object
|
||||||
|
|
@ -441,15 +441,15 @@ class ToolboxHelper
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate picture.
|
* Validate picture
|
||||||
*
|
*
|
||||||
* @param string $attribute
|
* @param string $attribute
|
||||||
* @param string|null $value
|
* @param string|null $value
|
||||||
* @param callable $fail
|
* @param callback $fail
|
||||||
* @param object $sizes
|
* @param object $sizes
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public static function validatePicture(string $attribute, string|null $value, callable $fail, object $sizes): void
|
public static function validatePicture(string $attribute, string|null $value, callable $fail, object $sizes)
|
||||||
{
|
{
|
||||||
if (!($useStorage = Storage::exists($value)) and !File::exists($value)) {
|
if (!($useStorage = Storage::exists($value)) and !File::exists($value)) {
|
||||||
$fail(trans(':attribute n\'existe pas dans le système de fichier', [
|
$fail(trans(':attribute n\'existe pas dans le système de fichier', [
|
||||||
|
|
@ -502,7 +502,7 @@ class ToolboxHelper
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the file full path.
|
* Get the file full path
|
||||||
*
|
*
|
||||||
* @param string $value
|
* @param string $value
|
||||||
* @param boolean $useStorage
|
* @param boolean $useStorage
|
||||||
|
|
@ -516,13 +516,13 @@ class ToolboxHelper
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the file mimetype.
|
* Get the file mimetype
|
||||||
*
|
*
|
||||||
* @param string $value
|
* @param string $value
|
||||||
* @param boolean $useStorage
|
* @param boolean $useStorage
|
||||||
* @return string|false
|
* @return string|false
|
||||||
*/
|
*/
|
||||||
private static function getUploadedFileMimeType(string $value, bool $useStorage): string|false
|
private static function getUploadedFileMimeType(string $value, bool $useStorage)
|
||||||
{
|
{
|
||||||
return !$useStorage ? File::mimeType($value) : Storage::mimeType($value);
|
return !$useStorage ? File::mimeType($value) : Storage::mimeType($value);
|
||||||
}
|
}
|
||||||
|
|
@ -559,6 +559,6 @@ class ToolboxHelper
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
return \response()->json($models);
|
return \response()->json($models ?? 500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ class AddStatusMessages
|
||||||
* @return void
|
* @return void
|
||||||
* @phpcs:disable Generic.Metrics.CyclomaticComplexity
|
* @phpcs:disable Generic.Metrics.CyclomaticComplexity
|
||||||
*/
|
*/
|
||||||
public function handle(TicketStatusChanged $event): void
|
public function handle(TicketStatusChanged $event)
|
||||||
{
|
{
|
||||||
// phpcs:enable
|
// phpcs:enable
|
||||||
$message = new Message();
|
$message = new Message();
|
||||||
|
|
|
||||||
75
app/Listeners/CreateTicketAutomatically.php
Normal file
75
app/Listeners/CreateTicketAutomatically.php
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Listeners;
|
||||||
|
|
||||||
|
use App\Events\BrevoWebhookCallReceived;
|
||||||
|
use App\Events\TicketCreated;
|
||||||
|
use App\Mail\NewTicket;
|
||||||
|
use App\Repositories\SiteRepository;
|
||||||
|
use App\Services\AutomaticTicketCreator;
|
||||||
|
use Domain\Models\ValueObjects\Email;
|
||||||
|
use Illuminate\Contracts\Events\Dispatcher;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Support\Facades\Config;
|
||||||
|
use Illuminate\Support\Facades\Mail;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
|
||||||
|
// NOTE: this should be queued in order to be eventually retried or at least keep info data.
|
||||||
|
class CreateTicketAutomatically implements ShouldQueue
|
||||||
|
{
|
||||||
|
private const string SITE_NAME_WHERE_TO_CREATE_TICKET = 'Mailing en masse';
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
private readonly LoggerInterface $logger,
|
||||||
|
private readonly AutomaticTicketCreator $automaticTicketCreator,
|
||||||
|
private readonly SiteRepository $siteRepository,
|
||||||
|
private readonly Dispatcher $dispatcher
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function handle(BrevoWebhookCallReceived $event): void
|
||||||
|
{
|
||||||
|
$fromEmail = $event->from;
|
||||||
|
$toEmail = $event->to;
|
||||||
|
$htmlRawContent = $event->htmlRawContent;
|
||||||
|
|
||||||
|
$this->logger->info('Received a ticket creation event from brevo');
|
||||||
|
$this->logger->debug(
|
||||||
|
'Payload for ticket creation form brevo',
|
||||||
|
[
|
||||||
|
'from_email' => $fromEmail->value,
|
||||||
|
'to_email' => $toEmail->value,
|
||||||
|
'html_raw_content' => base64_encode($htmlRawContent)
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
$siteReceivingTickets = $this->siteRepository->findByName(self::SITE_NAME_WHERE_TO_CREATE_TICKET);
|
||||||
|
|
||||||
|
if ($siteReceivingTickets === null) {
|
||||||
|
throw new \UnexpectedValueException(
|
||||||
|
'No site found with name \'' .
|
||||||
|
self::SITE_NAME_WHERE_TO_CREATE_TICKET . '\''
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$projectManager = $siteReceivingTickets->projectManager()->first();
|
||||||
|
|
||||||
|
if ($projectManager === null) {
|
||||||
|
throw new \UnexpectedValueException(
|
||||||
|
'No project manager found for site \'' .
|
||||||
|
self::SITE_NAME_WHERE_TO_CREATE_TICKET . '\''
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$ticket = $this->automaticTicketCreator->createTicket(
|
||||||
|
$siteReceivingTickets,
|
||||||
|
$projectManager,
|
||||||
|
$htmlRawContent,
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->dispatcher->dispatch(new TicketCreated(
|
||||||
|
siteReceivingTicket: $siteReceivingTickets,
|
||||||
|
ticket: $ticket,
|
||||||
|
byUserName: $fromEmail->value
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,21 +3,51 @@
|
||||||
namespace App\Listeners;
|
namespace App\Listeners;
|
||||||
|
|
||||||
use App\Events\NotifyAdmin;
|
use App\Events\NotifyAdmin;
|
||||||
|
use App\Events\TicketCreated;
|
||||||
|
use App\Mail\NewTicket;
|
||||||
use App\Mail\TicketUpdate;
|
use App\Mail\TicketUpdate;
|
||||||
|
use Domain\Models\ValueObjects\Email;
|
||||||
|
use Illuminate\Support\Facades\Config;
|
||||||
use Illuminate\Support\Facades\Mail;
|
use Illuminate\Support\Facades\Mail;
|
||||||
|
|
||||||
class SendNotificationMailToAdmin
|
class SendNotificationMailToAdmin
|
||||||
{
|
{
|
||||||
|
private readonly Email $mailAdmin;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->mailAdmin = new Email(
|
||||||
|
Config::string('mail.MAIL_ADMIN')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle the event.
|
* Handle the event.
|
||||||
*
|
*
|
||||||
* @param \App\Events\NotifyAdmin $event
|
* @param \App\Events\NotifyAdmin $event
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function handle(NotifyAdmin $event): void
|
public function handle(NotifyAdmin | TicketCreated $event)
|
||||||
{
|
{
|
||||||
$ticket = $event->ticket;
|
if ($event instanceof NotifyAdmin) {
|
||||||
Mail::to(config('mail.MAIL_ADMIN'))
|
$ticket = $event->ticket;
|
||||||
->send(new TicketUpdate($ticket, $event->corpsMaj));
|
Mail::to($this->mailAdmin->value)
|
||||||
|
->send(new TicketUpdate($ticket, $event->corpsMaj));
|
||||||
|
}
|
||||||
|
if ($event instanceof TicketCreated) {
|
||||||
|
$ticket = $event->ticket;
|
||||||
|
$siteReceivingTickets = $event->siteReceivingTicket;
|
||||||
|
$userName = $event->byUserName;
|
||||||
|
|
||||||
|
Mail::to($this->mailAdmin->value)
|
||||||
|
->send(new NewTicket(
|
||||||
|
ticketId: $ticket->id,
|
||||||
|
siteName: $siteReceivingTickets->name,
|
||||||
|
ticketTitle: $ticket->title,
|
||||||
|
ticketType: $ticket->type,
|
||||||
|
userName: $userName,
|
||||||
|
ticketDescription: $ticket->text,
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,12 +14,10 @@ class SendNotificationMailToTicketCreator
|
||||||
* @param \App\Events\NotifyTicketCreator $event
|
* @param \App\Events\NotifyTicketCreator $event
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function handle(NotifyTicketCreator $event): void
|
public function handle(NotifyTicketCreator $event)
|
||||||
{
|
{
|
||||||
$ticket = $event->ticket;
|
$ticket = $event->ticket;
|
||||||
/** @var \App\Models\User */
|
Mail::to($ticket->user()->withTrashed()->first()->email)
|
||||||
$user = $ticket->user();
|
|
||||||
Mail::to($user->withTrashed()->first()->email)
|
|
||||||
->send(new TicketUpdate($ticket, $event->corpsMaj));
|
->send(new TicketUpdate($ticket, $event->corpsMaj));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ class SendSubscriptionsNotificationsMail
|
||||||
* @param \App\Events\NotifySubscriptions $event
|
* @param \App\Events\NotifySubscriptions $event
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function handle(NotifySubscriptions $event): void
|
public function handle(NotifySubscriptions $event)
|
||||||
{
|
{
|
||||||
$ignoreConnectedUserEmail = Auth::user()->email ?? '';
|
$ignoreConnectedUserEmail = Auth::user()->email ?? '';
|
||||||
$ignoreUsers = $event->ignoreUsers ?? collect();
|
$ignoreUsers = $event->ignoreUsers ?? collect();
|
||||||
|
|
|
||||||
|
|
@ -2,39 +2,39 @@
|
||||||
|
|
||||||
namespace App\Mail;
|
namespace App\Mail;
|
||||||
|
|
||||||
use App\Models\Ticket;
|
use App\Enums\Tickets\TicketTypeEnum;
|
||||||
use Illuminate\Bus\Queueable;
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
use Illuminate\Mail\Mailable;
|
use Illuminate\Mail\Mailable;
|
||||||
use Illuminate\Queue\SerializesModels;
|
|
||||||
|
|
||||||
class NewTicket extends Mailable
|
class NewTicket extends Mailable implements ShouldQueue
|
||||||
{
|
{
|
||||||
use Queueable;
|
use Queueable;
|
||||||
use SerializesModels;
|
|
||||||
|
|
||||||
/** @var \App\Models\Ticket */
|
public function __construct(
|
||||||
private $ticket;
|
private readonly int $ticketId,
|
||||||
|
private readonly string $siteName,
|
||||||
/**
|
private readonly string $ticketTitle,
|
||||||
* Create a new message instance.
|
private readonly TicketTypeEnum $ticketType,
|
||||||
*
|
private readonly string $userName,
|
||||||
* @param \App\Models\Ticket $ticket
|
private readonly string $ticketDescription,
|
||||||
* @return void
|
) {}
|
||||||
*/
|
|
||||||
public function __construct(Ticket $ticket)
|
|
||||||
{
|
|
||||||
$this->ticket = $ticket;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build the message.
|
* Build the message.
|
||||||
*
|
*
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function build(): self
|
public function build()
|
||||||
{
|
{
|
||||||
$ticket = $this->ticket;
|
return $this->subject("[Support] Nouveau ticket n° {$this->ticketId} - {$this->ticketTitle}")
|
||||||
return $this->subject("[Support] Nouveau ticket n°" . $ticket->id)
|
->view('emails.new-ticket', [
|
||||||
->view('emails.new-ticket', compact('ticket'));
|
'ticketId' => $this->ticketId,
|
||||||
|
'siteName' => $this->siteName,
|
||||||
|
'ticketTitle' => $this->ticketTitle,
|
||||||
|
'ticketType' => $this->ticketType,
|
||||||
|
'userName' => $this->userName,
|
||||||
|
'ticketDescription' => $this->ticketDescription,
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,11 +37,11 @@ class TicketMention extends Mailable
|
||||||
*
|
*
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function build(): self
|
public function build()
|
||||||
{
|
{
|
||||||
$ticket = $this->ticket;
|
$ticket = $this->ticket;
|
||||||
$corpsMaj = ToolboxHelper::plainToHtml($this->corpsMaj);
|
$corpsMaj = ToolboxHelper::plainToHtml($this->corpsMaj);
|
||||||
return $this->subject("[Support] Vous avez été mentionné sur le ticket n° $ticket->id")
|
return $this->subject("[Support] Vous avez été mentionné sur le ticket n°$ticket->id - $ticket->title")
|
||||||
->view('emails.ticket-mention', compact('ticket', 'corpsMaj'));
|
->view('emails.ticket-mention', compact('ticket', 'corpsMaj'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,13 +37,11 @@ class TicketUpdate extends Mailable
|
||||||
*
|
*
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function build(): self
|
public function build()
|
||||||
{
|
{
|
||||||
$ticket = $this->ticket;
|
$ticket = $this->ticket;
|
||||||
/** @var \App\Models\Site */
|
|
||||||
$site = $ticket->site;
|
|
||||||
$corpsMaj = \html_entity_decode(ToolboxHelper::plainToHtml($this->corpsMaj));
|
$corpsMaj = \html_entity_decode(ToolboxHelper::plainToHtml($this->corpsMaj));
|
||||||
return $this->subject("[Support][{$site->name}] Ticket n°$ticket->id")
|
return $this->subject("[Support][{$ticket->site->name}] Ticket n°$ticket->id - $ticket->title")
|
||||||
->view('emails.ticket-update', compact('ticket', 'corpsMaj'));
|
->view('emails.ticket-update', compact('ticket', 'corpsMaj'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ class UserCreatedMail extends Mailable
|
||||||
*
|
*
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function build(): self
|
public function build()
|
||||||
{
|
{
|
||||||
return $this
|
return $this
|
||||||
->subject(sprintf('%s : Votre compte a été crée', config('app.name')))
|
->subject(sprintf('%s : Votre compte a été crée', config('app.name')))
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,13 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @property string $name
|
* @property int $id Doit correspondre aux ids marques de la CRM
|
||||||
|
* @property string $name Nom de la marque
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @property-read \Illuminate\Database\Eloquent\Collection<int, Account> $accounts
|
||||||
|
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Site> $sites
|
||||||
|
* @mixin \Eloquent
|
||||||
*/
|
*/
|
||||||
class Brand extends Model
|
class Brand extends Model
|
||||||
{
|
{
|
||||||
|
|
@ -16,7 +22,7 @@ class Brand extends Model
|
||||||
/**
|
/**
|
||||||
* The attributes that are fillable.
|
* The attributes that are fillable.
|
||||||
*
|
*
|
||||||
* @var list<string>
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'name'
|
'name'
|
||||||
|
|
@ -50,7 +56,6 @@ class Brand extends Model
|
||||||
*/
|
*/
|
||||||
public static function deleteSites(Brand $brand): void
|
public static function deleteSites(Brand $brand): void
|
||||||
{
|
{
|
||||||
/** @var \App\Models\Site $site */
|
|
||||||
foreach ($brand->sites as $site) {
|
foreach ($brand->sites as $site) {
|
||||||
$site->brand_id = null;
|
$site->brand_id = null;
|
||||||
$site->saveOrFail();
|
$site->saveOrFail();
|
||||||
|
|
@ -64,7 +69,7 @@ class Brand extends Model
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||||
*/
|
*/
|
||||||
public function sites(): \Illuminate\Database\Eloquent\Relations\HasMany
|
public function sites()
|
||||||
{
|
{
|
||||||
return $this->hasMany(Site::class);
|
return $this->hasMany(Site::class);
|
||||||
}
|
}
|
||||||
|
|
@ -74,7 +79,7 @@ class Brand extends Model
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||||
*/
|
*/
|
||||||
public function accounts(): \Illuminate\Database\Eloquent\Relations\HasMany
|
public function accounts()
|
||||||
{
|
{
|
||||||
return $this->hasMany(Account::class);
|
return $this->hasMany(Account::class);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,14 @@ use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @property int $id
|
||||||
* @property string $name
|
* @property string $name
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Invoice> $invoices
|
||||||
|
* @property-read mixed $value
|
||||||
|
* @method static \Database\Factories\CompanyFactory factory($count = null, $state = [])
|
||||||
|
* @mixin \Eloquent
|
||||||
*/
|
*/
|
||||||
class Company extends Model
|
class Company extends Model
|
||||||
{
|
{
|
||||||
|
|
@ -16,7 +23,7 @@ class Company extends Model
|
||||||
/**
|
/**
|
||||||
* The attributes that are fillable.
|
* The attributes that are fillable.
|
||||||
*
|
*
|
||||||
* @var list<string>
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'name'
|
'name'
|
||||||
|
|
@ -25,28 +32,28 @@ class Company extends Model
|
||||||
/**
|
/**
|
||||||
* The accessors to append to the model's array form.
|
* The accessors to append to the model's array form.
|
||||||
*
|
*
|
||||||
* @var list<string>
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $appends = [
|
protected $appends = [
|
||||||
'value'
|
'value'
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HasMany Invoices.
|
* HasMany Invoices
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||||
*/
|
*/
|
||||||
public function invoices(): \Illuminate\Database\Eloquent\Relations\HasMany
|
public function invoices()
|
||||||
{
|
{
|
||||||
return $this->hasMany(Invoice::class);
|
return $this->hasMany(Invoice::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return value attribute for belongsto search component.
|
* Return value attribute for belongsto search component
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Database\Eloquent\Casts\Attribute
|
* @return \Illuminate\Database\Eloquent\Casts\Attribute
|
||||||
*/
|
*/
|
||||||
protected function value(): \Illuminate\Database\Eloquent\Casts\Attribute
|
protected function value(): Attribute
|
||||||
{
|
{
|
||||||
return new Attribute(
|
return new Attribute(
|
||||||
get: fn () => $this->id,
|
get: fn () => $this->id,
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue