Compare commits

...
Sign in to create a new pull request.

101 commits

Author SHA1 Message Date
Vincent BRIDIER
972ce0cf6f
Merge branch 'trunk' 2022-12-14 08:37:41 +01:00
Vincent BRIDIER
033ce42b42
Merge branch 'develop' into trunk 2022-12-14 08:37:26 +01:00
Vincent BRIDIER
481b39d856
Add Sentry 2022-12-14 08:03:33 +01:00
Vincent BRIDIER
262ea2871c
Merge branch 'trunk' 2022-12-14 07:48:35 +01:00
Vincent BRIDIER
8ba5feff18
Merge branch 'develop' into trunk 2022-12-14 07:48:19 +01:00
Vincent BRIDIER
a247dba2b2 Merge branch 'fix-todays-orders' into 'develop'
fix todays orders

See merge request service-web-lab/boutique-cnc!4
2022-12-14 06:46:07 +00:00
Olivier Legat
4873cd7fc2 fix todays orders
localise sorting to current route
2022-12-13 13:55:42 +01:00
Vincent BRIDIER
69ce45d5cb
Merge branch 'trunk' 2022-12-13 10:33:59 +01:00
Vincent BRIDIER
a6d0e1ae2d
Merge branch 'develop' into trunk 2022-12-13 10:32:56 +01:00
Vincent BRIDIER
d8464a34ac Merge branch 'evol-sh-01' into 'develop'
Evol sh 01

See merge request service-web-lab/boutique-cnc!3
2022-12-13 09:30:00 +00:00
S. Hattry
4359c85b8c Fix filter order bug 2022-12-08 09:35:28 +01:00
S. Hattry
7ba2c3b2fe Fix null order bug (review feedback) 2022-11-28 13:07:49 +01:00
S. Hattry
1f235efebe Delete comment 2022-11-28 13:07:25 +01:00
S. Hattry
6eef17a390 Add translateable title (review feedback) 2022-11-28 12:59:14 +01:00
S. Hattry
5872d670fe Add translatables column names (review feedback) 2022-11-28 12:49:10 +01:00
S. Hattry
0c22695c77 Fix type input email bug (review feedback) 2022-11-28 12:38:59 +01:00
S. Hattry
1aceb54b0e Fix contact request rule bug (review feedback) 2022-11-28 12:31:25 +01:00
S. Hattry
e9085b681a Fix canceled order mail (review feedback) 2022-11-28 12:30:40 +01:00
S. Hattry
e8d1669bae Fix contact mail bug (review feedback) 2022-11-28 12:08:55 +01:00
S. Hattry
9e7fad8ebb Fix confirm admin mail bug (review feedback) 2022-11-28 12:03:19 +01:00
S. Hattry
6b3145eb8f Fix filters orders (review feedback) 2022-11-28 11:55:25 +01:00
S. Hattry
30e53b81b3 Fix sort date bug (review feedback) 2022-11-28 11:04:22 +01:00
S. Hattry
1cca69c933 BO - Add order filters 2022-11-25 15:22:16 +01:00
S. Hattry
11dad23fe2 Add confirm admin email according to shop 2022-11-25 14:42:18 +01:00
S. Hattry
9b5a68c121 Fix magasin migration bug 2022-11-25 09:51:40 +01:00
S. Hattry
6f14d1d975 Sort orders list by desc date 2022-11-24 17:10:28 +01:00
S. Hattry
039587d1e3 Add shop email destination in form contact 2022-11-24 16:31:54 +01:00
S. Hattry
825d47797b Add cancel order button for the customer 2022-11-24 13:15:21 +01:00
Vincent BRIDIER
e1820ba1ac
Merge branch 'trunk' 2022-11-24 09:23:21 +01:00
Olivier Legat
b72988b20c Merge branch 'develop' into trunk 2022-09-12 17:02:32 +02:00
Olivier Legat
8235f134cf
mixed type in signature does not fit current server execution : fixed 2022-09-12 17:01:31 +02:00
Olivier Legat
3000e1663f Merge branch 'develop' into trunk 2022-09-12 16:31:57 +02:00
Olivier Legat
f30c6cff18
fix product associated optionnal data 2022-09-12 16:31:08 +02:00
Olivier Legat
d48c9aa99b Merge branch 'develop' into trunk 2022-09-12 08:57:51 +02:00
Olivier Legat
64868010d4
proper way for cinjecting view shares taking fresh migration into account 2022-09-11 16:40:18 +02:00
Olivier Legat
b7c0e12429 Merge branch 'trunk' 2022-09-09 08:33:17 +02:00
Olivier Legat
2d65de573c Merge branch 'develop' into trunk 2022-09-09 08:32:17 +02:00
Olivier Legat
2534188942 Merge branch 'linting-cleanup' into 'develop'
Linting cleanup

See merge request service-web-lab/boutique-cnc!1
2022-09-09 06:25:18 +00:00
Olivier Legat
16213ac4e4
ignore vscode specific settings, if need should be force added 2022-09-08 13:00:41 +02:00
Olivier Legat
6e359d3c41
fix cyclomatic complexity on product update 2022-09-05 13:17:58 +02:00
Olivier Legat
1d2300ba57
solve cyclomatic complexity in avilable creneaux retreival 2022-09-05 12:19:36 +02:00
Olivier Legat
1fc4d97657
sniffing and linting - NO refactoring 2022-09-03 16:56:16 +02:00
Vincent BRIDIER
4bbb98e3c8
Merge branch 'trunk' 2022-08-25 12:52:07 +02:00
Vincent BRIDIER
80d426f470
Merge branch 'develop' into trunk 2022-08-25 12:51:56 +02:00
Vincent BRIDIER
78b5a223a7
first clean -> 1.0.1 2022-08-25 12:26:43 +02:00
Vincent BRIDIER
7ffa7f67a6
Merge branch 'trunk' 2022-08-24 15:26:09 +02:00
Vincent BRIDIER
3ee9fa91dc
Merge branch 'develop' into trunk 2022-08-24 15:25:52 +02:00
Vincent BRIDIER
02da9c7b7d
Add CI 2022-08-24 15:25:41 +02:00
Vincent BRIDIER
b932825760
Merge branch 'develop' into trunk 2022-08-24 15:24:38 +02:00
Vincent BRIDIER
869c56445c
Merge remote-tracking branch 'origin/remove_verrues_de_recette' into develop 2022-08-24 15:22:54 +02:00
Vincent BRIDIER
7d593ec5ac
Update VSCODE config 2022-08-24 14:42:24 +02:00
S. Hattry
02cfc1982b Revert "npm audit fix --force to solve all vulnerabilities"
This reverts commit 2bb67dd42d.
2022-07-28 11:59:39 +02:00
S. Hattry
3e9428d122 Revert "PHPCS correction 1"
This reverts commit e4f00ae71c.
2022-07-28 11:57:02 +02:00
Sebastien Hattry
e4f00ae71c PHPCS correction 1 2022-07-28 09:29:34 +00:00
Sebastien Hattry
2bb67dd42d npm audit fix --force to solve all vulnerabilities 2022-07-28 08:52:28 +00:00
Olivier Legat
89fd1b8516 force https for all envs 2022-07-12 17:42:08 +02:00
Olivier Legat
ce21e69af8 Merge branch 'trunk' 2022-05-19 11:23:28 +02:00
Olivier Legat
25783cdd77 Merge branch 'trunk' of https://voight001.lesidc.com/boutique-cnc into trunk 2022-05-19 11:09:57 +02:00
Olivier Legat
31fed252d6 Merge branch 'develop' of https://voight001.lesidc.com/boutique-cnc into trunk 2022-05-18 17:32:07 +02:00
Olivier Legat
e26f3afb69 Merge branch 'develop' of https://voight001.lesidc.com/boutique-cnc into develop 2022-05-18 17:24:45 +02:00
Olivier Legat
3b77148e72 Merge branch 'inco_rustine_old_new_format' into develop 2022-05-18 15:23:09 +00:00
Olivier Legat
27f02c7b89 rustine pour integrer les anciens flux nouveau format hybride 2022-05-18 15:22:47 +00:00
Olivier Legat
fd1bdc1222 Merge branch 'trunk' 2022-04-27 10:00:22 +02:00
Olivier Legat
8bf0255747 Merge branch 'develop' into trunk 2022-04-27 09:55:14 +02:00
Olivier Legat
69af67ff83 Merge branch 'develop' of https://voight001.lesidc.com/boutique-cnc into develop 2022-04-27 09:54:42 +02:00
Olivier Legat
bc3be757d6 fix customer hascode registration 2022-04-27 09:54:09 +02:00
Olivier Legat
ee894b925a Merge branch 'develop' into trunk 2022-04-26 15:42:22 +02:00
Olivier Legat
50a3495ee1 Merge branch 'develop' of https://voight001.lesidc.com/boutique-cnc into develop 2022-04-26 15:41:48 +02:00
Olivier Legat
6a8676600f Date de livraison = date de livraison 2022-04-26 15:40:32 +02:00
Olivier Legat
5ade814cb5 Merge branch 'trunk' 2022-04-22 12:51:20 +00:00
Olivier Legat
01979430fa Merge branch 'develop' into trunk 2022-04-22 12:51:02 +00:00
Olivier Legat
652d8430f5 following CRM changes, fix getting cutomer name for order index 2022-04-22 12:50:46 +00:00
Olivier Legat
b7786019df Merge branch 'trunk' 2022-04-22 14:18:41 +02:00
Olivier Legat
9db7691ac2 Merge branch 'develop' into trunk 2022-04-22 11:24:00 +00:00
Olivier Legat
a20816e0bf Merge branch 'evolutionV3' into develop 2022-04-22 11:16:36 +00:00
Olivier Legat
351023e4d3 remove second smt transport 2022-04-21 11:06:53 +02:00
Olivier Legat
81db3a3a92 Merge branch 'develop' into trunk 2022-04-14 19:35:02 +02:00
Olivier Legat
6edb8757f3 dat-bs-toggle for bootstrap 5 2022-04-14 19:34:46 +02:00
Olivier Legat
68e3e47a5c Merge branch 'develop' into trunk 2022-04-07 17:32:03 +02:00
Olivier Legat
9b0e1db5d1 Merge branch 'develop' into trunk 2022-03-24 19:39:18 +01:00
Olivier Legat
0d3d61877b Merge branch 'develop' into trunk 2022-03-20 11:59:02 +01:00
Olivier Legat
4efed5f5b3 Merge branch 'develop' into trunk 2022-03-19 11:59:38 +01:00
Olivier Legat
ec49fd6e8d Merge branch 'develop' into trunk 2022-03-19 11:26:48 +01:00
Olivier Legat
a7882b75bd Merge branch 'develop' into trunk 2022-03-19 09:02:20 +01:00
Olivier Legat
5cf76c2f0d Merge branch 'develop' into trunk 2022-03-19 08:54:51 +01:00
Olivier Legat
2328c79611 Merge branch 'develop' into trunk 2022-03-18 14:30:35 +01:00
Olivier Legat
31e6752a17 map inco name data only if empty (create use case) 2022-03-13 13:21:38 +01:00
Olivier Legat
a5ca89e3b2 Merge branch 'develop' into trunk 2022-03-13 13:17:40 +01:00
Olivier Legat
2cc5215e2a Merge branch 'develop' into trunk 2022-03-13 13:10:39 +01:00
Olivier Legat
b962678684 Merge branch 'trunk' 2022-03-12 18:38:28 +01:00
Olivier Legat
c33b3c55b5 Merge branch 'develop' into trunk 2022-03-12 18:38:11 +01:00
Olivier Legat
9f8b28e64f Merge branch 'trunk' 2022-03-12 18:02:20 +01:00
Olivier Legat
0a33c08c6e Merge branch 'develop' into trunk 2022-03-12 18:02:02 +01:00
Olivier Legat
d4860ac6dc Merge branch 'trunk' 2022-03-12 13:33:33 +01:00
Olivier Legat
5f2edbec2c Merge branch 'develop' into trunk 2022-03-12 12:05:34 +01:00
Olivier Legat
c4cb2da2af Merge branch 'trunk' 2022-03-11 08:57:47 +01:00
Olivier Legat
1b2dc4b34f Merge branch 'develop' into trunk 2022-03-11 08:57:25 +01:00
Olivier Legat
a3ebe93e90 Merge branch 'trunk' 2022-02-25 17:21:06 +01:00
Olivier Legat
ee4f404328 Merge branch 'develop' into trunk 2022-02-25 17:20:17 +01:00
Olivier Legat
ce39a598f3 Merge branch 'develop' into trunk 2022-02-18 15:31:46 +01:00
Olivier Legat
d5722b5835 Merge branch 'develop' into trunk 2022-01-21 08:24:36 +01:00
176 changed files with 6438 additions and 87653 deletions

View file

@ -1,19 +1,19 @@
APP_NAME=Laravel APP_NAME="ENV-Boutique LDC"
APP_ENV=local APP_ENV=local
APP_KEY= APP_KEY=
APP_DEBUG=true APP_DEBUG=true
APP_URL=http://localhost APP_URL=
APP_THEME=basic APP_THEME=basic
LOG_CHANNEL=stack LOG_CHANNEL=daily
LOG_LEVEL=debug LOG_LEVEL=debug
DB_CONNECTION=mysql DB_CONNECTION=mysql
DB_HOST=127.0.0.1 DB_HOST=dev-mariadb
DB_PORT=3306 DB_PORT=3306
DB_DATABASE=laravel DB_DATABASE=
DB_USERNAME=root DB_USERNAME=root
DB_PASSWORD= DB_PASSWORD=secret
BROADCAST_DRIVER=log BROADCAST_DRIVER=log
CACHE_DRIVER=file CACHE_DRIVER=file
@ -21,28 +21,23 @@ QUEUE_CONNECTION=sync
SESSION_DRIVER=file SESSION_DRIVER=file
SESSION_LIFETIME=120 SESSION_LIFETIME=120
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_MAILER=smtp MAIL_MAILER=smtp
MAIL_HOST=smtp.mailtrap.io MAIL_HOST=dev-mailhog
MAIL_PORT=2525 MAIL_PORT=1025
MAIL_USERNAME=null MAIL_USERNAME=null
MAIL_PASSWORD=null MAIL_PASSWORD=null
MAIL_ENCRYPTION=null MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=null MAIL_FROM_ADDRESS=equipe.web@ldc.fr
MAIL_FROM_NAME="${APP_NAME}" MAIL_FROM_NAME="${APP_NAME}"
AWS_ACCESS_KEY_ID= MAIL_LIST_SERVICEWEB=equipe.web@ldc.fr
AWS_SECRET_ACCESS_KEY= MAIL_LIST_INVALIDINCO=equipe.web@ldc.fr,vincent.pierre@ldc.fr,christelle.manceau@ldc.fr
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
PUSHER_APP_ID= # CRM
PUSHER_APP_KEY= CRM_ENDPOINT=https://ldcldccrm:K5cJmTsG@dev.ldc-crm.fr
PUSHER_APP_SECRET= # Service boutique
PUSHER_APP_CLUSTER=mt1 CRM_TOKEN=
# LDC Web Status Checker
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}" PROJECT_UUID=
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" # Google Analytics
ANALYTICS_GOOGLE_ID=

4
.gitignore vendored
View file

@ -5,6 +5,8 @@
/public/images/gammes /public/images/gammes
/public/images/produits /public/images/produits
/public/images/slides /public/images/slides
/public/b-o/
/public/mix-manifest.json
/storage/*.key /storage/*.key
/vendor /vendor
.env .env
@ -16,3 +18,5 @@ Homestead.json
Homestead.yaml Homestead.yaml
npm-debug.log npm-debug.log
yarn-error.log yarn-error.log
auth.json
.vscode

46
.gitlab-ci.yml Normal file
View file

@ -0,0 +1,46 @@
image: $CI_REGISTRY/service-web-lab/ldc-web-images-docker/ldcweb-qa:php7.3-1.0
stages:
- Security
- CodingStandards
composer-security:
stage: Security
script:
- local-php-security-checker --format=json --path=./composer.lock > composer-security-checker-report.json
artifacts:
when: on_failure
expose_as: 'composer-security-checker'
paths:
- composer-security-checker-report.json
allow_failure: true
npm-security:
stage: Security
script:
- audit-ci -p npm -o json > npm-security-checker-report.json
artifacts:
when: on_failure
expose_as: 'npm-security-checker'
paths:
- npm-security-checker-report.json
allow_failure: true
phpcs:
stage: CodingStandards
before_script:
- composer config gitlab-token.gitlab.com $CI_DEPLOY_USER $CI_DEPLOY_PASSWORD
- composer install
cache:
paths:
- vendor/
script:
- vendor/bin/phpcs --report=junit --report-file=phpcs-report.xml
artifacts:
when: on_failure
expose_as: 'phpcs'
paths:
- phpcs-report.xml
reports:
junit: phpcs-report.xml
allow_failure: false

View file

@ -16,7 +16,8 @@
"titleBar.activeBackground": "#630856", "titleBar.activeBackground": "#630856",
"titleBar.activeForeground": "#e7e7e7", "titleBar.activeForeground": "#e7e7e7",
"titleBar.inactiveBackground": "#63085699", "titleBar.inactiveBackground": "#63085699",
"titleBar.inactiveForeground": "#e7e7e799" "titleBar.inactiveForeground": "#e7e7e799",
"commandCenter.border": "#e7e7e799"
}, },
"peacock.remoteColor": "#630856" "peacock.remoteColor": "#630856"
} }

View file

@ -1,7 +1,20 @@
## 1.0.1
- Change LDC CRM Client repository
- composer update
- Update .gitignore
- Delete compiled assets
- Replace informatique.internet -> equipe.web
- Complete README.md
- Delete credentials from front folder..
- Delete tests folder and PHPUnit file
- Update PHPCS file
- Add mix() for assets
- PHPCBF
## 1.0.0
Init versioning
## 19-03-2022 ## 19-03-2022
* legal RGPD routes always accessible * legal RGPD routes always accessible
* privatisable routes * privatisable routes
* quickorder route * quickorder route
* quickorder route activated by theme settings * quickorder route activated by theme settings
* improved tooltip for product reference wher regate orders are active * improved tooltip for product reference wher regate orders are active

View file

@ -1,23 +1,38 @@
## Boutique Click N Collect # Boutique Click N Collect
## Required systems
* supervisor
## Installation ## Installation
``` ```
composer install composer install
php artisan storage:link php artisan storage:link
cd /ressources/views/front/ cp .env.example .env
mkdir <theme-folder> php artisan key:generate
cd <theme-folder> ```
git clone <theme-repo> . Edit .env file then :
cd ../../../.../ ```
npm install && npm run prod php artisan migrate --seed
``` ```
## Theme
```
cd resources/views/front/
git clone [REPO_URL] --branch=[THEME_BRANCH_NAME] [THEME_NAME]
```
Ex:
```
git clone [REPO_URL] --branch=develop-mairet mairet
```
Update APP_THEME value in .env :
```
APP_THEME=[THEME_NAME]
```
Ex:
```
APP_THEME=mairet
```
Project root :
```
npm install && npm run prod
```
## Back-Office ## Back-Office
Création de compte Création de compte
@ -27,3 +42,6 @@ php artisan create:admin
``` ```
URL : /bo URL : /bo
## Required systems
* supervisor

View file

@ -23,35 +23,25 @@ class CreateAdmin extends Command
protected $description = 'creates an admin user upon password entry'; protected $description = 'creates an admin user upon password entry';
/** /**
* Create a new command instance. * Execute the console command.
* *
* @return void * @return void
*/ */
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle() public function handle()
{ {
$firstname = $this->ask('What is the firstname?','Equipe'); $firstname = $this->ask('What is the firstname?', 'Equipe');
$lastname = $this->ask('What is the lastname?','Web'); $lastname = $this->ask('What is the lastname?', 'Web');
$email = $this->ask('What is the email?', 'equipe.web@ldc.fr'); $email = $this->ask('What is the email?', 'equipe.web@ldc.fr');
$pwd = $this->secret('What is the password?'); $pwd = $this->secret('What is the password?');
$user = new User(); $user = new User();
$user->firstname = $firstname; $user->firstname = $firstname;
$user->lastname = $lastname; $user->lastname = $lastname;
$user->date_of_birth = now(); $user->date_of_birth = now();
$user->email = $email; $user->email = $email;
$user->password = Hash::make($pwd); $user->password = Hash::make($pwd);
$user->email_verified_at = now(); $user->email_verified_at = now();
$user->role = 1; $user->role = 1;
$user->save(); $user->save();
$this->info('User created.'); $this->info('User created.');

View file

@ -7,7 +7,6 @@ use App\Jobs\CsvSalariesReader as JobCsvSalarieReader;
class ImportSalaries extends Command class ImportSalaries extends Command
{ {
/** /**
* The name and signature of the console command. * The name and signature of the console command.
* *
@ -22,29 +21,17 @@ class ImportSalaries extends Command
*/ */
protected $description = 'Import Salaries, pour provision des clients'; protected $description = 'Import Salaries, pour provision des clients';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/** /**
* Execute the console command. * Execute the console command.
* *
* @return int * @return void
*/ */
public function handle() public function handle()
{ {
$this->info('Running the Job, this could take some time.'); $this->info('Running the Job, this could take some time.');
$job = new JobCsvSalarieReader(); $job = new JobCsvSalarieReader();
$job->console = $this; $job->console = $this;
$job->handle(); $job->handle();
$this->info('Job completed'); $this->info('Job completed');
} }
} }

View file

@ -1,11 +1,12 @@
<?php <?php
/*
* Command Name: LDC Web Status Checker /**
* Description: Envoi des infos Serveur/Laravel vers LDC Web * Command Name: LDC Web Status Checker
* Version: 1.0 * Description: Envoi des infos Serveur/Laravel vers LDC Web
* Author: Vincent BRIDIER * Version: 1.0
* Author URI: vincent.bridier@ldc.fr * Author: Vincent BRIDIER
*/ * Author URI: vincent.bridier@ldc.fr
*/
namespace App\Console\Commands; namespace App\Console\Commands;
@ -27,16 +28,6 @@ class LDCWebStatusChecker extends Command
*/ */
protected $description = 'Envoi des infos Serveur/Laravel vers LDC Web'; protected $description = 'Envoi des infos Serveur/Laravel vers LDC Web';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/** /**
* Execute the console command. * Execute the console command.
* *
@ -44,28 +35,28 @@ class LDCWebStatusChecker extends Command
*/ */
public function handle() public function handle()
{ {
$data = []; $data = [];
$data['uuid'] = config('ldcweb.project_uuid'); $data['uuid'] = config('ldcweb.project_uuid');
// Sitemap.xml ? // Sitemap.xml ?
if (file_exists(public_path() . '/sitemap.xml')) { if (file_exists(public_path() . '/sitemap.xml')) {
$data['sitemap'] = 'true'; $data['sitemap'] = 'true';
}else{ } else {
$data['sitemap'] = 'false'; $data['sitemap'] = 'false';
} }
// Robots.txt ? // Robots.txt ?
if (file_exists(public_path() . '/robots.txt')) { if (file_exists(public_path() . '/robots.txt')) {
$data['robots'] = 'true'; $data['robots'] = 'true';
}else{ } else {
$data['robots'] = 'false'; $data['robots'] = 'false';
} }
//Check logs // Check logs.
$data['logs'] = 0; $data['logs'] = 0;
$patherror = storage_path('/logs'); $patherror = storage_path('/logs');
$files = glob($patherror.'/*.log'); $files = glob($patherror . '/*.log');
if(count($files) > 0){ if (count($files) > 0) {
foreach ($files as $file) { foreach ($files as $file) {
$data['logs'] = $data['logs'] + filesize($file); $data['logs'] = $data['logs'] + filesize($file);
} }
@ -73,9 +64,9 @@ class LDCWebStatusChecker extends Command
$data['code']['version'] = app()->version(); $data['code']['version'] = app()->version();
// Send by cURL // Send by cURL.
$url = 'https://ldc-web.ldc.fr/api/status-checker'; $url = 'https://ldc-web.ldc.fr/api/status-checker';
$ch = curl_init($url); $ch = curl_init($url);
$payload = ['token' => 'CE8S52Qq7stf5k8frF4T', 'datas' => json_encode($data)]; $payload = ['token' => 'CE8S52Qq7stf5k8frF4T', 'datas' => json_encode($data)];
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload); curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

View file

@ -7,7 +7,6 @@ use Illuminate\Console\Command;
class RefreshSiteMap extends Command class RefreshSiteMap extends Command
{ {
/** /**
* The name and signature of the console command. * The name and signature of the console command.
* *
@ -25,12 +24,12 @@ class RefreshSiteMap extends Command
/** /**
* Execute the console command. * Execute the console command.
* *
* @return int * @return void
*/ */
public function handle() public function handle()
{ {
$this->info('Running the Job, this could take some time.'); $this->info('Running the Job, this could take some time.');
$job = new JobsRefreshSiteMap(); $job = new JobsRefreshSiteMap();
$job->console = $this; $job->console = $this;
$job->handle(); $job->handle();
$this->info('Job completed'); $this->info('Job completed');

View file

@ -7,7 +7,6 @@ use Illuminate\Console\Command;
class XmlIncoReader extends Command class XmlIncoReader extends Command
{ {
/** /**
* The name and signature of the console command. * The name and signature of the console command.
* *
@ -30,7 +29,7 @@ class XmlIncoReader extends Command
public function handle() public function handle()
{ {
$this->info('Running the Job, this could take some time.'); $this->info('Running the Job, this could take some time.');
$job = new JobsXmlIncoReader(); $job = new JobsXmlIncoReader();
$job->console = $this; $job->console = $this;
$job->handle(); $job->handle();
$this->info('Job completed'); $this->info('Job completed');

View file

@ -14,13 +14,12 @@ class Kernel extends ConsoleKernel
* @var array * @var array
*/ */
protected $commands = [ protected $commands = [
// ];
];
/** /**
* Define the application's command schedule. * Define the application's command schedule.
* *
* @param \Illuminate\Console\Scheduling\Schedule $schedule * @param \Illuminate\Console\Scheduling\Schedule $schedule
* @return void * @return void
*/ */
protected function schedule(Schedule $schedule) protected function schedule(Schedule $schedule)
@ -28,7 +27,6 @@ class Kernel extends ConsoleKernel
$schedule->command('sitemap:refresh')->dailyAt('16:13'); $schedule->command('sitemap:refresh')->dailyAt('16:13');
$schedule->command('ldcweb:statuschecker')->everyFifteenMinutes(); $schedule->command('ldcweb:statuschecker')->everyFifteenMinutes();
$schedule->job(JobsXmlIncoReader::class)->name('xml-inco-reader')->onOneServer()->dailyAt('15:00'); $schedule->job(JobsXmlIncoReader::class)->name('xml-inco-reader')->onOneServer()->dailyAt('15:00');
//$schedule->job(new XmlIncoReader)->weeklyOn(1, '8:00');
} }
/** /**
@ -38,7 +36,7 @@ class Kernel extends ConsoleKernel
*/ */
protected function commands() protected function commands()
{ {
$this->load(__DIR__.'/Commands'); $this->load(__DIR__ . '/Commands');
require base_path('routes/console.php'); require base_path('routes/console.php');
} }

View file

@ -11,6 +11,11 @@ use Kwaadpepper\Enum\BaseEnum;
*/ */
final class InvoicingUnit extends BaseEnum final class InvoicingUnit extends BaseEnum
{ {
/**
* Enum values
*
* @return array
*/
protected static function values(): array protected static function values(): array
{ {
return [ return [
@ -20,6 +25,11 @@ final class InvoicingUnit extends BaseEnum
]; ];
} }
/**
* Enum labels
*
* @return array
*/
protected static function labels(): array protected static function labels(): array
{ {
return [ return [
@ -29,6 +39,10 @@ final class InvoicingUnit extends BaseEnum
]; ];
} }
/**
* Output the value as a string
* @return string
*/
public function __toString(): string public function __toString(): string
{ {
return (string)$this->label; return (string)$this->label;

View file

@ -11,6 +11,11 @@ use Kwaadpepper\Enum\BaseEnum;
*/ */
final class OrderUnit extends BaseEnum final class OrderUnit extends BaseEnum
{ {
/**
* Enum values
*
* @return array
*/
protected static function values(): array protected static function values(): array
{ {
return [ return [
@ -20,6 +25,11 @@ final class OrderUnit extends BaseEnum
]; ];
} }
/**
* Enum labels
*
* @return array
*/
protected static function labels(): array protected static function labels(): array
{ {
return [ return [
@ -29,6 +39,10 @@ final class OrderUnit extends BaseEnum
]; ];
} }
/**
* Output the value as a string
* @return string
*/
public function __toString(): string public function __toString(): string
{ {
return (string)$this->label; return (string)$this->label;

View file

@ -14,6 +14,11 @@ use Kwaadpepper\Enum\BaseEnumRoutable;
*/ */
class PriceShowingMode extends BaseEnumRoutable class PriceShowingMode extends BaseEnumRoutable
{ {
/**
* Enum values
*
* @return array
*/
protected static function values(): array protected static function values(): array
{ {
return [ return [
@ -22,6 +27,11 @@ class PriceShowingMode extends BaseEnumRoutable
]; ];
} }
/**
* Enum labels
*
* @return array
*/
protected static function labels(): array protected static function labels(): array
{ {
return [ return [

View file

@ -11,6 +11,11 @@ use Kwaadpepper\Enum\BaseEnum;
*/ */
final class SellUnit extends BaseEnum final class SellUnit extends BaseEnum
{ {
/**
* Enum values
*
* @return array
*/
protected static function values(): array protected static function values(): array
{ {
return [ return [
@ -20,6 +25,11 @@ final class SellUnit extends BaseEnum
]; ];
} }
/**
* Enum labels
*
* @return array
*/
protected static function labels(): array protected static function labels(): array
{ {
return [ return [
@ -29,6 +39,10 @@ final class SellUnit extends BaseEnum
]; ];
} }
/**
* Output the value as a string
* @return string
*/
public function __toString(): string public function __toString(): string
{ {
return (string)$this->label; return (string)$this->label;

View file

@ -10,6 +10,11 @@ use Kwaadpepper\Enum\BaseEnum;
*/ */
final class SettingRegisterMode extends BaseEnum final class SettingRegisterMode extends BaseEnum
{ {
/**
* Enum values
*
* @return array
*/
protected static function values(): array protected static function values(): array
{ {
return [ return [
@ -18,6 +23,11 @@ final class SettingRegisterMode extends BaseEnum
]; ];
} }
/**
* Enum labels
*
* @return array
*/
protected static function labels(): array protected static function labels(): array
{ {
return [ return [
@ -26,6 +36,10 @@ final class SettingRegisterMode extends BaseEnum
]; ];
} }
/**
* Output the value as a string
* @return string
*/
public function __toString(): string public function __toString(): string
{ {
return (string)$this->label; return (string)$this->label;

View file

@ -11,6 +11,11 @@ use Kwaadpepper\Enum\BaseEnum;
*/ */
final class WeightUnit extends BaseEnum final class WeightUnit extends BaseEnum
{ {
/**
* Enum values
*
* @return array
*/
protected static function values(): array protected static function values(): array
{ {
return [ return [
@ -20,6 +25,11 @@ final class WeightUnit extends BaseEnum
]; ];
} }
/**
* Enum labels
*
* @return array
*/
protected static function labels(): array protected static function labels(): array
{ {
return [ return [
@ -29,6 +39,12 @@ final class WeightUnit extends BaseEnum
]; ];
} }
/**
* conversion values
* base kg()
*
* @return array
*/
public static function convert(): array public static function convert(): array
{ {
return [ return [
@ -38,6 +54,10 @@ final class WeightUnit extends BaseEnum
]; ];
} }
/**
* Output the value as a string
* @return string
*/
public function __toString(): string public function __toString(): string
{ {
return (string)$this->label; return (string)$this->label;

View file

@ -6,5 +6,4 @@ use Exception;
class AbortCsvImportException extends Exception class AbortCsvImportException extends Exception
{ {
//
} }

View file

@ -4,10 +4,6 @@ namespace App\Exceptions;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler; use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Auth\AuthenticationException; use Illuminate\Auth\AuthenticationException;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Session;
use RuntimeException;
use Throwable;
class Handler extends ExceptionHandler class Handler extends ExceptionHandler
{ {
@ -16,9 +12,7 @@ class Handler extends ExceptionHandler
* *
* @var array * @var array
*/ */
protected $dontReport = [ protected $dontReport = [];
//
];
/** /**
* A list of the inputs that are never flashed for validation exceptions. * A list of the inputs that are never flashed for validation exceptions.
@ -37,9 +31,21 @@ class Handler extends ExceptionHandler
*/ */
public function register() public function register()
{ {
// $this->reportable(function (\Throwable $e) {
if (app()->bound('sentry')) {
app('sentry')->captureException($e);
}
});
} }
/**
* Handle unauthenticated as exception
*
* @param mixed $request
* @param AuthenticationException $exception
* @return \Illuminate\Http\RedirectResponse
*/
protected function unauthenticated($request, AuthenticationException $exception) protected function unauthenticated($request, AuthenticationException $exception)
{ {
if ($request->expectsJson()) { if ($request->expectsJson()) {
@ -54,47 +60,9 @@ class Handler extends ExceptionHandler
$login = 'auth.login'; $login = 'auth.login';
break; break;
} }
//cf. issue https://stackoverflow.com/questions/52417438/laravel-unauthenticated-redirect-issue-with-multiple-authentication // Cf. issue :
//Session::forget('url.intented'); // Https://stackoverflow.com/questions/52417438/laravel-unauthenticated-redirect-issue-with-multiple-authentication.
// Session::forget('url.intented'); .
return redirect()->guest(route($login)); return redirect()->guest(route($login));
} }
/**
* Report or log an exception.
*
* @param \Throwable $exception
* @return void
*
* @throws \Exception
*/
public function report(Throwable $e)
{
if (get_class($e) == RedirectTo::class) {
abort(redirect($e->url));
}
try {
if (config('app.debug') === false) {
if ($this->shouldntReport($e)) {
return;
}
Mail::send([
'html' => 'emails.exception',
'text' => 'emails.exception-plain'
], [
'exception' => $e,
'appName' => config('app.name')
], function ($m) {
$m->to(
config('mail.contactsList.serviceweb'),
sprintf('%s Exception Handler', config('app.name'))
)->subject('Need help !, an error occured in your application, please check Logs ASAP');
});
}
// phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch
} catch (RuntimeException $e) {
// do nothing, mail send error, let laravel only handle this
} finally {
parent::report($e);
}
}
} }

View file

@ -8,11 +8,27 @@ use Illuminate\Support\Facades\Auth;
class LoginController extends Controller class LoginController extends Controller
{ {
/**
* Display login form
*
* @param Request $request
* @return \Illuminate\Contracts\View\View
*
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
*/
public function index(Request $request) public function index(Request $request)
{ {
// @phpcs:enable
return view('auth.login-bo'); return view('auth.login-bo');
} }
/**
* Compute login form
*
* @param Request $request
* @return \Illuminate\Contracts\View\View
*
*/
public function login(Request $request) public function login(Request $request)
{ {
$request->validate([ $request->validate([
@ -37,8 +53,17 @@ class LoginController extends Controller
return view('auth.login')->withErrors('Informations incorrectes.'); return view('auth.login')->withErrors('Informations incorrectes.');
} }
/**
* logout
*
* @param Request $request
* @return \Illuminate\Contracts\View\View
*
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
*/
public function logout(Request $request) public function logout(Request $request)
{ {
// @phpcs:enable
Auth::logout(); Auth::logout();
return redirect()->route('home'); return redirect()->route('home');
} }

View file

@ -10,11 +10,27 @@ use Illuminate\Support\Facades\Hash;
class RegisterController extends Controller class RegisterController extends Controller
{ {
/**
* Display register form
*
* @param Request $request
* @return \Illuminate\Contracts\View\View
*
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
*/
public function index(Request $request) public function index(Request $request)
{ {
// @phpcs:enable
return view('auth.register'); return view('auth.register');
} }
/**
* Compute regioster form
*
* @param Request $request
* @return \Illuminate\Http\RedirectResponse
*
*/
public function register(Request $request) public function register(Request $request)
{ {
$request->validate([ $request->validate([
@ -34,8 +50,7 @@ class RegisterController extends Controller
'role' => 3 'role' => 3
]); ]);
// Envoi mail activation // Envoi mail activation.
return redirect()->route('auth.register')->with('success', 'Mail envoyé pour confirmation'); return redirect()->route('auth.register')->with('success', 'Mail envoyé pour confirmation');
} }
} }

View file

@ -7,8 +7,17 @@ use Illuminate\Http\Request;
class ResetPasswordController extends Controller class ResetPasswordController extends Controller
{ {
/**
* Display reset password form
*
* @param Request $request
* @return \Illuminate\Contracts\View\View
*
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
*/
public function index(Request $request) public function index(Request $request)
{ {
// @phpcs:enable
return view('auth.reset-password'); return view('auth.reset-password');
} }
} }

View file

@ -12,11 +12,15 @@ class BasketController extends Controller
{ {
/** /**
* ajout de produit au panier * ajout de produit au panier
*
* @param \Illuminate\Http\Request $request
*
* @return array
*/ */
public function addToCart(Request $request) public function addToCart(Request $request)
{ {
$instance = $request->instance ?? "panier"; $instance = $request->instance ?? "panier";
$product = Product::find($request->id); $product = Product::find($request->id);
Cart::instance($instance); Cart::instance($instance);
Cart::add($product, $request->qty); Cart::add($product, $request->qty);
return $this->getCart($instance); return $this->getCart($instance);
@ -24,13 +28,17 @@ class BasketController extends Controller
/** /**
* ajout de plusieurs produits au panier * ajout de plusieurs produits au panier
*
* @param \Illuminate\Http\Request $request
*
* @return array
*/ */
public function addToCartLot(Request $request) public function addToCartLot(Request $request)
{ {
$instance = $request->instance ?? "panier"; $instance = $request->instance ?? "panier";
Cart::instance($instance); Cart::instance($instance);
$lot = $request->items; $lot = $request->items;
foreach($lot as $item) { foreach ($lot as $item) {
$product = Product::find($item["cartItem"]["id"]); $product = Product::find($item["cartItem"]["id"]);
Cart::add($product, $item["cartItem"]["qty"]); Cart::add($product, $item["cartItem"]["qty"]);
} }
@ -39,11 +47,15 @@ class BasketController extends Controller
/** /**
* suppression de produit du panier * suppression de produit du panier
*
* @param \Illuminate\Http\Request $request
*
* @return array
*/ */
public function removeFromCart(Request $request) public function removeFromCart(Request $request)
{ {
$instance = $request->instance ?? "panier"; $instance = $request->instance ?? "panier";
$rowId = $request->rowId; $rowId = $request->rowId;
Cart::instance($instance); Cart::instance($instance);
Cart::remove($rowId); Cart::remove($rowId);
return $this->getCart($instance); return $this->getCart($instance);
@ -51,8 +63,13 @@ class BasketController extends Controller
/** /**
* vidage de panier * vidage de panier
*
* @param \Illuminate\Http\Request $request
*
* @return array
*/ */
public function emptyCart(Request $request) { public function emptyCart(Request $request)
{
$instance = $request->instance ?? "panier"; $instance = $request->instance ?? "panier";
Cart::instance($instance); Cart::instance($instance);
Cart::destroy(); Cart::destroy();
@ -61,6 +78,10 @@ class BasketController extends Controller
/** /**
* récupération du panier * récupération du panier
*
* @param \Illuminate\Http\Request $request
*
* @return array
*/ */
public function getCartRequest(Request $request) public function getCartRequest(Request $request)
{ {
@ -69,14 +90,19 @@ class BasketController extends Controller
return $this->getCart($instance); return $this->getCart($instance);
} }
/**
public function getCart($instance = "panier") * return cart data array
*
* @param string $instance
* @return array
*/
public function getCart(string $instance = "panier")
{ {
Cart::instance($instance); Cart::instance($instance);
$dbpanier = new Collection(); $dbpanier = new Collection();
foreach (Cart::content() as $row) { foreach (Cart::content() as $row) {
$product = $row->model; $product = $row->model;
//$product->additionnalProductInfo = $product->additionnalProductInfo($product->product_type);
$product->calculatedPrices = $product->getCalcPrices(); $product->calculatedPrices = $product->getCalcPrices();
$row->setTaxRate($product->tax->rate); $row->setTaxRate($product->tax->rate);
@ -91,30 +117,42 @@ class BasketController extends Controller
$cartInfos = array( $cartInfos = array(
"totalTTC" => Cart::total(), "totalTTC" => Cart::total(),
'totalTVA' => Cart::tax(), //total des taxes // Total des taxes.
'totalHT' => Cart::subtotal(), //total sans les taxes 'totalTVA' => Cart::tax(),
'totalweight' => Cart::weight(), //poids total des items // Total sans les taxes.
'totalHTbefore' => Cart::priceTotal(), //total avant taxes et remises 'totalHT' => Cart::subtotal(),
'totaldiscount' => Cart::discount(), //total des remises // Poids total des items.
'countItems' => Cart::count(), //nb de produits dans le cart 'totalweight' => Cart::weight(),
// Total avant taxes et remises.
'totalHTbefore' => Cart::priceTotal(),
// Total des remises.
'totaldiscount' => Cart::discount(),
// Nb de produits dans le cart.
'countItems' => Cart::count(),
); );
$cartInfosNoPrice = array( $cartInfosNoPrice = array(
"totalTTC" => "-.--", "totalTTC" => "-.--",
'totalTVA' => "-.--", //total des taxes // Total des taxes.
'totalHT' => "-.--", //total sans les taxes 'totalTVA' => "-.--",
'totalweight' => Cart::weight(), //poids total des items // Total sans les taxes.
'totalHTbefore' => "-.--", //total avant taxes et remises 'totalHT' => "-.--",
'totaldiscount' => "-.--", //total des remises // Poids total des items.
'countItems' => Cart::count(), //nb de produits dans le cart 'totalweight' => Cart::weight(),
// Total avant taxes et remises.
'totalHTbefore' => "-.--",
// Total des remises.
'totaldiscount' => "-.--",
// Nb de produits dans le cart.
'countItems' => Cart::count(),
); );
$cartReturn = array($dbpanier,$cartInfosNoPrice); $cartReturn = array($dbpanier,$cartInfosNoPrice);
if (config('bosettings.show_prices_authenticated') == "authenticated") { if (config('bosettings.show_prices_authenticated') == "authenticated") {
{ {
if (Auth::guard('customer')->check()) { if (Auth::guard('customer')->check()) {
$cartReturn = array($dbpanier,$cartInfos); $cartReturn = array($dbpanier,$cartInfos);
} }
} }
} }
if (config('bosettings.show_prices_guest') == "guest") { if (config('bosettings.show_prices_guest') == "guest") {

View file

@ -8,14 +8,22 @@ use Illuminate\Http\Request;
class ContentController extends Controller class ContentController extends Controller
{ {
public function manage(Request $request, $key) /**
* Manage content page
*
* @param Request $request
* @param string $key
* @return \Illuminate\Http\Response
*
*/
public function manage(Request $request, string $key)
{ {
$content = Content::where('key', $key)->first(); $content = Content::where('key', $key)->first();
if ($_SERVER["REQUEST_METHOD"] === "POST") { if ($_SERVER["REQUEST_METHOD"] === "POST") {
$banner = $request->banner; $banner = $request->banner;
$title = $request->title; $title = $request->title;
$chapeau = $request->chapeau; $chapeau = $request->chapeau;
$maintext = $request->value; $maintext = $request->value;
$request->validate([ $request->validate([
@ -34,14 +42,14 @@ class ContentController extends Controller
$content->banner = $imageName; $content->banner = $imageName;
} }
$content->title = $title; $content->title = $title;
$content->chapeau = $chapeau; $content->chapeau = $chapeau;
$content->value = $maintext; $content->value = $maintext;
$content->save(); $content->save();
return redirect()->route('bo.content', ['key' => $content->key, 'content' => $content]) return redirect()->route('bo.content', ['key' => $content->key, 'content' => $content])
->with('success', 'Modifications enregistrés !'); ->with('success', 'Modifications enregistrés !');
} }//end if
return view('bo.content.manage', compact('content')); return view('bo.content.manage', compact('content'));
} }

View file

@ -9,46 +9,69 @@ use Illuminate\Http\Request;
class CreneauxController extends Controller class CreneauxController extends Controller
{ {
public function settings(Request $request,$id) /**
* Display creneaux settings form
*
* @param Request $request
* @param integer $id
* @return \Illuminate\Contracts\View\View
*
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
*/
public function settings(Request $request, int $id)
{ {
// @phpcs:enable
$magasin = Magasin::findOrFail($id); $magasin = Magasin::findOrFail($id);
$timeslotSettings = $magasin->timeslotSettings; $timeslotSettings = $magasin->timeslotSettings;
if ($timeslotSettings->count() === 0) { if ($timeslotSettings->count() === 0) {
//Aucun settings pour ce magasin // Aucun settings pour ce magasin.
$timeslotSettings = $this->makeCreneauxSettings($id); $timeslotSettings = $this->makeCreneauxSettings($id);
} }
return view('bo.creneaux.settings', compact('timeslotSettings', 'magasin')); return view('bo.creneaux.settings', compact('timeslotSettings', 'magasin'));
} }
public function makeCreneauxSettings($id) { /**
for ($i=0;$i<7;$i++) { * Retrieve creneaux settings
$dayset = new TimeslotSetting(); *
* @param integer $id
* @return mixed
*/
public function makeCreneauxSettings(int $id)
{
for ($i = 0; $i < 7; $i++) {
$dayset = new TimeslotSetting();
$dayset->magasin_id = $id; $dayset->magasin_id = $id;
$dayset->day_index = ''.$i; $dayset->day_index = '' . $i;
$dayset->save(); $dayset->save();
} }
return Magasin::findOrFail($id)->timeslotSettings; return Magasin::findOrFail($id)->timeslotSettings;
} }
public function updateSettings(Request $request,$id) /**
* save settings
*
* @param Request $request
* @param integer $id
* @return \Illuminate\Http\RedirectResponse
*/
public function updateSettings(Request $request, int $id)
{ {
$plage = $request->plage; $plage = $request->plage;
$magasin_id = $id; $magasin_id = $id;
foreach($plage as $index => $day) { foreach ($plage as $index => $day) {
$setting = TimeslotSetting::where('day_index', ''.$index) $setting = TimeslotSetting::where('day_index', '' . $index)
->where('magasin_id', $magasin_id) ->where('magasin_id', $magasin_id)
->firstOrFail(); ->firstOrFail();
//$setting->magasin_id = $magasin_id; ne doit pas changer // $setting->magasin_id = $magasin_id; ne doit pas changer
$setting->morning_start = $day['morning_start']; $setting->morning_start = $day['morning_start'];
$setting->morning_end = $day['morning_end']; $setting->morning_end = $day['morning_end'];
$setting->afternoon_start = $day['afternoon_start']; $setting->afternoon_start = $day['afternoon_start'];
$setting->afternoon_end = $day['afternoon_end']; $setting->afternoon_end = $day['afternoon_end'];
$setting->interval = $day['interval']; $setting->interval = $day['interval'];
$setting->max_orders_per_interval = $day['max_orders_per_interval']; $setting->max_orders_per_interval = $day['max_orders_per_interval'];
$setting->min_order_preparation = $day['min_order_preparation']; $setting->min_order_preparation = $day['min_order_preparation'];
$setting->save(); $setting->save();
} }

View file

@ -6,6 +6,11 @@ use App\Http\Controllers\Controller;
class DashboardController extends Controller class DashboardController extends Controller
{ {
/**
* Dashboard Page
*
* @return \Illuminate\Contracts\View\View
*/
public function index() public function index()
{ {
return view('bo.dashboard'); return view('bo.dashboard');

View file

@ -8,24 +8,41 @@ use Illuminate\Http\Request;
class FaqController extends Controller class FaqController extends Controller
{ {
public function index() { /**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
$faq = Faq::all(); $faq = Faq::all();
return view('bo.faq.index', compact('faq')); return view('bo.faq.index', compact('faq'));
} }
public function saveDatas(Request $request) { /**
* Update faq data.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function saveDatas(Request $request)
{
$faq = $request->faq; $faq = $request->faq;
for ($i = 0; $i < count($faq); $i++) { $looplimit = count($faq);
for ($i = 0; $i < $looplimit; $i++) {
$faqToInsert = !empty($faq[$i]["question"]) && !empty($faq[$i]["answer"]); $faqToInsert = !empty($faq[$i]["question"]) && !empty($faq[$i]["answer"]);
if (isset($faq[$i]["id"]) && $faq[$i]["id"] !== null && $faqToInsert) { if (isset($faq[$i]["id"]) && $faq[$i]["id"] !== null && $faqToInsert) {
$f = Faq::findOrFail($faq[$i]["id"]); $f = Faq::findOrFail($faq[$i]["id"]);
$f->question = $faq[$i]["question"]; $f->question = $faq[$i]["question"];
$f->answer = $faq[$i]["answer"]; $f->answer = $faq[$i]["answer"];
$f->save(); $f->save();
} else { } else {
if ($faqToInsert) { if ($faqToInsert) {
$c = Faq::updateOrCreate(['question' => $faq[$i]["question"], 'answer' => $faq[$i]["answer"]]); $c = Faq::updateOrCreate([
'question' => $faq[$i]["question"],
'answer' => $faq[$i]["answer"]
]);
$faq[$i]["id"] = $c->id; $faq[$i]["id"] = $c->id;
} else { } else {
unset($faq[$i]); unset($faq[$i]);
@ -37,7 +54,14 @@ class FaqController extends Controller
return $faq; return $faq;
} }
public function destroy(Request $request) { /**
* Remove the specified resource from storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function destroy(Request $request)
{
$faq = Faq::findOrFail($request->id); $faq = Faq::findOrFail($request->id);
$faq->delete(); $faq->delete();

View file

@ -33,13 +33,15 @@ class MagasinsController extends Controller
/** /**
* Store a newly created resource in storage. * Store a newly created resource in storage.
* *
* @param \Illuminate\Http\Request $request * @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response * @return \Illuminate\Http\Response
*/ */
public function store(Request $request) public function store(Request $request)
{ {
$request->validate([ $request->validate([
'name' => 'required|string|max:255', 'name' => 'required|string|max:255',
'email_contact' => 'required|email:rfc,dns,spoof|max:255',
'email_confirm' => 'nullable|email:rfc,dns,spoof|max:255',
'address' => 'required|string|max:255', 'address' => 'required|string|max:255',
'postcode' => 'required', 'postcode' => 'required',
'city' => 'required|string|max:255', 'city' => 'required|string|max:255',
@ -49,26 +51,15 @@ class MagasinsController extends Controller
return redirect()->route('bo.magasins.edit', $shop->id)->with('success', 'Nouveau Magasin enregistré !'); return redirect()->route('bo.magasins.edit', $shop->id)->with('success', 'Nouveau Magasin enregistré !');
} }
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
{
//
}
/** /**
* Show the form for editing the specified resource. * Show the form for editing the specified resource.
* *
* @param int $id * @param integer $id
* @return \Illuminate\Http\Response * @return \Illuminate\Http\Response
*/ */
public function edit($id) public function edit(int $id)
{ {
$magasin = Magasin::findOrFail($id); $magasin = Magasin::findOrFail($id);
$exceptionsCollecte = $magasin->collecteExceptions()->orderBy('date')->get(); $exceptionsCollecte = $magasin->collecteExceptions()->orderBy('date')->get();
return view('bo.magasins.edit', compact('magasin', 'exceptionsCollecte')); return view('bo.magasins.edit', compact('magasin', 'exceptionsCollecte'));
} }
@ -76,14 +67,16 @@ class MagasinsController extends Controller
/** /**
* Update the specified resource in storage. * Update the specified resource in storage.
* *
* @param \Illuminate\Http\Request $request * @param \Illuminate\Http\Request $request
* @param int $id * @param integer $id
* @return \Illuminate\Http\Response * @return \Illuminate\Http\Response
*/ */
public function update(Request $request, $id) public function update(Request $request, int $id)
{ {
$request->validate([ $request->validate([
'name' => 'required|string|max:255', 'name' => 'required|string|max:255',
'email_contact' => 'required|email:rfc,dns,spoof|max:255',
'email_confirm' => 'nullable|email:rfc,dns,spoof|max:255',
'address' => 'required|string|max:255', 'address' => 'required|string|max:255',
'postcode' => 'required', 'postcode' => 'required',
'city' => 'required|string|max:255', 'city' => 'required|string|max:255',
@ -97,20 +90,19 @@ class MagasinsController extends Controller
/** /**
* Remove the specified resource from storage. * Remove the specified resource from storage.
* *
* @param int $id * @param integer $id
* @return \Illuminate\Http\Response * @return \Illuminate\Http\Response
*/ */
public function destroy($id) public function destroy(int $id)
{ {
$shop = Magasin::findOrFail($id); $shop = Magasin::findOrFail($id);
$count = Magasin::count(); $count = Magasin::count();
if ($count === 1) { if ($count === 1) {
return redirect()->back()->withErrors("Suppression impossible : Vous devez conserver au moins 1 point de retrait."); return redirect()->back()
->withErrors("Suppression impossible : Vous devez conserver au moins 1 point de retrait.");
} }
// @todo : controller les crenaux settings liés
$shop->delete(); $shop->delete();
return redirect()->route('bo.magasins.index'); return redirect()->route('bo.magasins.index');
} }
@ -118,15 +110,19 @@ class MagasinsController extends Controller
/** /**
* bo * bo
* ajx : affichage d'infos sur un magasin * ajx : affichage d'infos sur un magasin
*
* @param integer $id
* @param string|null $mode
* @return \Illuminate\Contracts\View\View
*/ */
public function getMagasinInfo($id, $mode = null) public function getMagasinInfo(int $id, string $mode = null)
{ {
$magasin = Magasin::findOrFail($id); $magasin = Magasin::findOrFail($id);
if(!is_null($mode)) { if (!is_null($mode)) {
if($mode=="tippy") { if ($mode == "tippy") {
return view('bo.magasins.tippy-card', compact('magasin')); return view('bo.magasins.tippy-card', compact('magasin'));
} }
if($mode=="json") { if ($mode == "json") {
return $magasin; return $magasin;
} }
return view('bo.magasins.info-card', compact('magasin')); return view('bo.magasins.info-card', compact('magasin'));
@ -134,54 +130,74 @@ class MagasinsController extends Controller
return view('bo.magasins.info-popup', compact('magasin')); return view('bo.magasins.info-popup', compact('magasin'));
} }
/**
* Save collect exceptions
*
* @param Request $request
* @return array
*/
public function saveExceptions(Request $request) public function saveExceptions(Request $request)
{ {
$collecteException = $request->collecte_exception; $collecteException = $request->collecte_exception;
for ($i = 0; $i < count($collecteException); $i++) { $looplimit = count($collecteException);
for ($i = 0; $i < $looplimit; $i++) {
$collecteExceptionToInsert = !empty($collecteException[$i]["date"]); $collecteExceptionToInsert = !empty($collecteException[$i]["date"]);
if (isset($collecteException[$i]["id"]) && $collecteException[$i]["id"] !== null && $collecteExceptionToInsert) { if (
$ce = CollecteException::findOrFail($collecteException[$i]["id"]); isset($collecteException[$i]["id"]) &&
$ce->date = $collecteException[$i]["date"]; $collecteException[$i]["id"] !== null &&
$ce->comment = $collecteException[$i]["comment"]; $collecteExceptionToInsert
) {
$ce = CollecteException::findOrFail($collecteException[$i]["id"]);
$ce->date = $collecteException[$i]["date"];
$ce->comment = $collecteException[$i]["comment"];
$ce->magasin_id = $collecteException[$i]["magasin_id"]; $ce->magasin_id = $collecteException[$i]["magasin_id"];
$ce->save(); $ce->save();
} else { } else {
if ($collecteExceptionToInsert) { if ($collecteExceptionToInsert) {
$ce = CollecteException::updateOrCreate([ $ce = CollecteException::updateOrCreate([
'date' => $collecteException[$i]["date"], 'date' => $collecteException[$i]["date"],
'comment' => $collecteException[$i]["comment"], 'comment' => $collecteException[$i]["comment"],
'magasin_id' => $collecteException[$i]["magasin_id"] 'magasin_id' => $collecteException[$i]["magasin_id"]
]); ]);
$collecteException[$i]["id"] = $ce->id; $collecteException[$i]["id"] = $ce->id;
} else { } else {
unset($collecteException[$i]); unset($collecteException[$i]);
$i--; $i--;
} }
} }
} }//end for
//remet dans l'ordre avant de renvoyer // Remet dans l'ordre avant de renvoyer.
//$collecteException = CollecteException::where('magasin_id',)->orderBy('date')->get();
$this->arraySortByColumn($collecteException, "date"); $this->arraySortByColumn($collecteException, "date");
return $collecteException; return $collecteException;
} }
/** /**
* helper function * helper function
*
* @param array $array
* @param string $column
* @param integer $direction
* @return void
*/ */
public function arraySortByColumn(&$array, $column, $direction = SORT_ASC) { public function arraySortByColumn(array &$array, string $column, int $direction = SORT_ASC)
{
$reference_array = array(); $reference_array = array();
foreach($array as $key => $row) { foreach ($array as $key => $row) {
$reference_array[$key] = $row[$column]; $reference_array[$key] = $row[$column];
} }
array_multisort($reference_array, $direction, $array); array_multisort($reference_array, $direction, $array);
} }
/**
* delete collecte exception
*
* @param Request $request
* @return string
*/
public function destroyExceptions(Request $request) public function destroyExceptions(Request $request)
{ {
$collecteException = CollecteException::findOrFail($request->id); $collecteException = CollecteException::findOrFail($request->id);

View file

@ -16,56 +16,89 @@ use App\Mail\OrderConfirmMail;
use App\Mail\OrderConfirmAdminMail; use App\Mail\OrderConfirmAdminMail;
use App\Jobs\CsvOrderWrite; use App\Jobs\CsvOrderWrite;
use App\Models\Customers; use App\Models\Customers;
use App\Models\OrdersStatus;
use App\Models\Setting; use App\Models\Setting;
use Carbon\Carbon; use Carbon\Carbon;
use Carbon\CarbonImmutable; use Carbon\CarbonImmutable;
use Carbon\CarbonInterval; use Carbon\CarbonInterval;
use Gloudemans\Shoppingcart\Facades\Cart; use Gloudemans\Shoppingcart\Facades\Cart;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Str;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Session; use Illuminate\Support\Facades\Session;
use Exception;
class OrdersController extends Controller class OrdersController extends Controller
{ {
/** /**
* index of orders (Bo) * Display a listing of the resource.
*
* @param \App\Http\Requests\SortOrders $request
* @return \Illuminate\Contracts\View\View
*/ */
public function index(SortOrders $request) public function index(SortOrders $request)
{ {
//$orders = Order::orderBy('date', 'DESC')->get();
$orders = $this->filterOrders($request); $orders = $this->filterOrders($request);
$status_orders = OrdersStatus::all();
$magasins = Magasin::all();
$filter_status_order = $request->query('filter_status_order');
$filter_magasin = $request->query('filter_magasin');
$filter_reference = $request->query('filter_reference');
if (!empty($filter_status_order)) {
$orders = $orders->where('status_id', $filter_status_order);
}
if (!empty($filter_magasin)) {
$orders = $orders->whereHas(
'timeslot',
function (Builder $q) use ($filter_magasin) {
$q->where('timeslots.magasin_id', $filter_magasin);
}
);
}
if (!empty($filter_reference)) {
$orders = $orders->where('reference', 'like', "%{$filter_reference}%");
}
$orders = $orders->paginate(10); $orders = $orders->paginate(10);
return view('bo.orders.index', compact('orders')); return view(
'bo.orders.index',
compact('orders', 'status_orders', 'magasins', 'filter_status_order', 'filter_magasin', 'filter_reference')
);
} }
/**
* orders that ship today
*
* @param SortOrders $request
* @return \Illuminate\Contracts\View\View
*/
public function today(SortOrders $request) public function today(SortOrders $request)
{ {
//$orders = Order::orderBy('date', 'DESC')->get();
$orders = $this->filterOrders($request); $orders = $this->filterOrders($request);
//filter today // Filter today.
$today = CarbonImmutable::now()->startOfDay(); $today = CarbonImmutable::now()->startOfDay();
$orders = $orders->whereHas('timeslot', function ($q) use ($today) { $orders = $orders->whereHas('timeslot', function ($q) use ($today) {
$q->where('day', '=', $today->format('d/m/Y')); $q->where('day', '=', $today->format('d/m/Y'));
}); });
$orders = $orders->get(); //paginate(20); $orders = $orders->get();
return view('bo.orders.index', compact('orders', 'today')); return view('bo.orders.index', compact('orders', 'today'));
} }
/**
* Filter orders
*
* @param Request $request
* @return \Illuminate\Database\Eloquent\Builder
*/
protected function filterOrders(Request $request) protected function filterOrders(Request $request)
{ {
$orders = Order::query(); $orders = Order::query();
if ($request->rst) { if ($request->rst) {
Session::remove('orders.sort_col'); Session::remove('orders.sort_col');
Session::remove('orders.sort_way'); Session::remove('orders.sort_way');
@ -102,8 +135,10 @@ class OrdersController extends Controller
case 'customer_id': case 'customer_id':
$orders = $orders->orderBy('customer_id', Session::get('orders.sort_way')); $orders = $orders->orderBy('customer_id', Session::get('orders.sort_way'));
break; break;
} } //end switch
} } else {
$orders->orderByDesc('date');
}//end if
return $orders; return $orders;
} }
@ -111,41 +146,47 @@ class OrdersController extends Controller
/** /**
* action de changement de statut vers l'avant * action de changement de statut vers l'avant
* envoi de mails transctionnels * envoi de mails transctionnels
* @param String $reference reference de la commande *
* @param string $reference Reference de la commande.
* @return \Illuminate\Http\RedirectResponse
*/ */
public function changeStatus($reference) public function changeStatus(string $reference)
{ {
$order = Order::where('reference', $reference)->first(); $order = Order::where('reference', $reference)->first();
$order->status_id = $order->status_id + 1; $order->status_id = $order->status_id + 1;
$order->save(); $order->save();
//send confirm mail // Send confirm mail.
Mail::to($order->customer->email)->send(new OrderStatusMail($order)); Mail::to($order->customer->email)->send(new OrderStatusMail($order));
Mail::mailer('smtp2')->to($order->customer->email)->send(new OrderStatusMail($order));
//return redirect()->route('bo.orders')->with('success', "Changement de status enregistré pour la commande " . $order->reference . ".");
return back()->with('success', "Changement de status enregistré pour la commande " . $order->reference . "."); return back()->with('success', "Changement de status enregistré pour la commande " . $order->reference . ".");
} }
/** /**
* mise au statut annulé d'une commande * mise au statut annulé d'une commande
*
* @param string $reference
* @return \Illuminate\Http\RedirectResponse
*/ */
public function cancelOrder($reference) public function cancelOrder(string $reference)
{ {
$order = Order::where('reference', $reference)->first(); $order = Order::where('reference', $reference)->first();
$order->status_id = 7; $order->status_id = 7;
$order->save(); $order->save();
//return redirect()->route('bo.orders')->with('success', "La commande à été annulée.");
return back()->with('success', "La commande " . $order->reference . " à été annulée."); return back()->with('success', "La commande " . $order->reference . " à été annulée.");
} }
/** /**
* @deprecated * @deprecated Supprimer cette méthode qui repose sur un modèle de donnée osolète.
* ajout de produits à la commande * ajout de produits à la commande
* @todo : supprimer cette méthode qui repose sur un modèle de donnée osolète *
* @param string $orderReference
* @param integer $productId
* @param integer $quantity
* @return \Illuminate\Http\RedirectResponse
*/ */
public function addProduct($orderReference, $productId, $quantity) public function addProduct(string $orderReference, int $productId, int $quantity)
{ {
$product = Product::findOrFail($productId); $product = Product::findOrFail($productId);
$order = Order::where('reference', $orderReference)->first(); $order = Order::where('reference', $orderReference)->first();
@ -164,7 +205,8 @@ class OrdersController extends Controller
/** /**
* front * front
* récap panier du tunnel de commande * récap panier du tunnel de commande
* @todo : déplacer vers le controller idoine *
* @return \Illuminate\Contracts\View\View
*/ */
public function recapOrder() public function recapOrder()
{ {
@ -174,12 +216,18 @@ class OrdersController extends Controller
$cartInfos = array( $cartInfos = array(
"totalTTC" => Cart::total(), "totalTTC" => Cart::total(),
'totalTVA' => Cart::tax(), //total des taxes // Total des taxes.
'totalHT' => Cart::subtotal(), //total sans les taxes 'totalTVA' => Cart::tax(),
'totalweight' => Cart::weight(), //poids total des items // Total sans les taxes.
'totalHTbefore' => Cart::priceTotal(), //total avant taxes et remises 'totalHT' => Cart::subtotal(),
'totaldiscount' => Cart::discount(), //total des remises // Poids total des items.
'countItems' => Cart::count(), //nb de produits dans le cart 'totalweight' => Cart::weight(),
// Total avant taxes et remises.
'totalHTbefore' => Cart::priceTotal(),
// Total des remises.
'totaldiscount' => Cart::discount(),
// Nb de produits dans le cart.
'countItems' => Cart::count(),
); );
return view('sales.recap', compact('activestep', 'cart', 'cartInfos')); return view('sales.recap', compact('activestep', 'cart', 'cartInfos'));
@ -188,13 +236,15 @@ class OrdersController extends Controller
/** /**
* front * front
* Storing order from sales tunnel * Storing order from sales tunnel
*
* @return \Illuminate\Http\RedirectResponse
*/ */
public function store() public function store()
{ {
//save // Save.
Cart::instance('panier'); Cart::instance('panier');
$order = new Order(); $order = new Order();
//generate order ref // Generate order ref.
$order->reference = $this->generateOrderRef(); $order->reference = $this->generateOrderRef();
$order->date = Carbon::now(); $order->date = Carbon::now();
$order->status_id = 1; $order->status_id = 1;
@ -203,7 +253,7 @@ class OrdersController extends Controller
$order->save(); $order->save();
//order_id // Order_id.
Cart::instance('panier'); Cart::instance('panier');
$cart = Cart::content(); $cart = Cart::content();
foreach ($cart as $cartItem) { foreach ($cart as $cartItem) {
@ -211,47 +261,48 @@ class OrdersController extends Controller
$order_line->order_id = $order->id; $order_line->order_id = $order->id;
$order_line->product_id = $cartItem->model->id; $order_line->product_id = $cartItem->model->id;
$order_line->quantity = $cartItem->qty; $order_line->quantity = $cartItem->qty;
//gross unit price // Gross unit price.
$order_line->unit_price = $cartItem->model->priceHt; $order_line->unit_price = $cartItem->model->priceHt;
//discount per unit // Discount per unit.
$order_line->unit_discount = $cartItem->model->discountAmount; $order_line->unit_discount = $cartItem->model->discountAmount;
//tax rate for this line // Tax rate for this line.
$order_line->tax_rate = $cartItem->taxRate; $order_line->tax_rate = $cartItem->taxRate;
//tax amount par unit // Tax amount par unit.
$order_line->unit_tax = round(( ($order_line->unit_price - $order_line->unit_discount) * ($order_line->tax_rate / 100) ) * 100) / 100; $order_line->unit_tax = round(
//discount amount for the line (($order_line->unit_price - $order_line->unit_discount) * ($order_line->tax_rate / 100)) * 100
) / 100;
// Discount amount for the line.
$order_line->total_discount = $order_line->unit_discount * $order_line->quantity; $order_line->total_discount = $order_line->unit_discount * $order_line->quantity;
//gross amount for the line // Gross amount for the line.
$order_line->total_ht = ($order_line->unit_price - $order_line->unit_discount) * $order_line->quantity; $order_line->total_ht = ($order_line->unit_price - $order_line->unit_discount) * $order_line->quantity;
//tax amount for the line // Tax amount for the line.
$order_line->total_tax = $order_line->unit_tax * $order_line->quantity; $order_line->total_tax = $order_line->unit_tax * $order_line->quantity;
//total TTC avec remises de la ligne // Total TTC avec remises de la ligne.
$order_line->total_ttc = $order_line->total_ht + $order_line->total_tax; $order_line->total_ttc = $order_line->total_ht + $order_line->total_tax;
$order_line->save(); $order_line->save();
} }//end foreach
//empty cart // Empty cart.
Cart::destroy(); Cart::destroy();
//then redirect // Then redirect.
return redirect()->route('sales.pick-slot', ['reference' => $order->reference]); return redirect()->route('sales.pick-slot', ['reference' => $order->reference]);
} }
/** /**
* generate order Reference * generate order Reference
* for a new order * for a new order
*
* @return string
*/ */
public function generateOrderRef() public function generateOrderRef()
{ {
//Avant // Format : YYYYMMDDHHMM000.
//Str::uuid();
//maintenant
//format : YYYYMMDDHHMM000
$now = Carbon::now(); $now = Carbon::now();
//count todays orders // Count todays orders.
$countorders = Order::whereDate('created_at', Carbon::today())->count(); $countorders = Order::whereDate('created_at', Carbon::today())->count();
//add one // Add one.
$countorders++; $countorders++;
$ref = $now->isoFormat('YYYYMMDDHHmm') . str_pad($countorders, 3, "0", STR_PAD_LEFT); $ref = $now->isoFormat('YYYYMMDDHHmm') . str_pad($countorders, 3, "0", STR_PAD_LEFT);
return $ref; return $ref;
@ -259,8 +310,11 @@ class OrdersController extends Controller
/** /**
* front tunnel de commande étape 3 : choix de créneau * front tunnel de commande étape 3 : choix de créneau
*
* @param string $reference
* @return \Illuminate\Contracts\View\View
*/ */
public function timeSlotPick($reference) public function timeSlotPick(string $reference)
{ {
$activestep = 3; $activestep = 3;
if (config('theme.multi_relay')) { if (config('theme.multi_relay')) {
@ -270,26 +324,81 @@ class OrdersController extends Controller
} }
$availCreneaux = array(); $availCreneaux = array();
//plus besoin car chargé par le composant vue. $order = Order::where('reference', '=', $reference)->firstOrFail();
//$availCreneaux = $this->getAvailableCreneauxByShop($magasin->id);
$order = Order::where('reference', '=', $reference)->firstOrFail();
return view('sales.pick-slot', compact('activestep', 'availCreneaux', 'order', 'magasin')); return view('sales.pick-slot', compact('activestep', 'availCreneaux', 'order', 'magasin'));
} }
/** /**
* @return mixed * add timeslot by interval between start and end hour
*
* @param array $plage
* @param integer $weekDay
* @param CarbonImmutable $current
* @param Magasin $magasin
* @param CarbonImmutable $now
* @param CarbonImmutable $today
* @param CarbonInterval $delaiPrepa
* @param CarbonInterval $interval
* @param Carbon $currentTime
* @param Carbon $endTime
* @return array
*/ */
public function getAvailableCreneauxByShop($id) private function addCreneaux(
array $plage,
int $weekDay,
CarbonImmutable $current,
Magasin $magasin,
CarbonImmutable $now,
CarbonImmutable $today,
CarbonInterval $delaiPrepa,
CarbonInterval $interval,
Carbon $currentTime,
Carbon $endTime
) {
$retArray = array();
do {
$creneau = $currentTime->format('H:i');
$nbtakens = $magasin->timeslots()
->where('day', $current->format('d/m/Y'))
->where('time', $creneau)->count();
if ($nbtakens >= $plage[$weekDay]['max_orders_per_interval']) {
$isDispo = false;
} else {
$isDispo = true;
}
if (
$current->addHours($currentTime->format('H'))->addMinutes($currentTime->format('i')) <
$now->add($delaiPrepa)
) {
$isDispo = false;
}
// Attention si la date est passée (today mais avant maintenant) : pas de créneau.
if ($current > $today || $currentTime >= $now) {
$retArray[] = array($creneau, $isDispo);
}
$currentTime->add($interval);
} while ($currentTime <= $endTime);
return $retArray;
}
/**
* give array of available crenaux
*
* @param integer $id
* @return array
*/
public function getAvailableCreneauxByShop(int $id)
{ {
//setting à stocker et réutiliser // Setting à stocker et réutiliser.
$plage_days = Setting::where('key', 'order_withdrawal_period')->firstOrFail()->value; $plage_days = Setting::where('key', 'order_withdrawal_period')->firstOrFail()->value;
$magasin = Magasin::findOrFail($id); $magasin = Magasin::findOrFail($id);
$timeslotSettings = $magasin->timeslotSettings; $timeslotSettings = $magasin->timeslotSettings;
//$timeslotSettings = TimeslotSetting::all(); // $timeslotSettings = TimeslotSetting::all();
//fabriquons un tableau recap // Fabriquons un tableau recap.
$plage = array(); $plage = array();
foreach ($timeslotSettings as $day) { foreach ($timeslotSettings as $day) {
$plage[$day->day_index] = array( $plage[$day->day_index] = array(
@ -303,18 +412,14 @@ class OrdersController extends Controller
); );
} }
//génération des plages // Génération des plages.
//start today // Start today.
$today = CarbonImmutable::now()->startOfDay(); $today = CarbonImmutable::now()->startOfDay();
$weekDay = $today->weekday(); $weekDay = $today->weekday();
//final boundary (permet de limiter la liste des jours d'exception) // Final boundary (permet de limiter la liste des jours d'exception).
$finalday = $today->add($plage_days, 'day'); $finalday = $today->add($plage_days, 'day');
$now = CarbonImmutable::now(); $now = CarbonImmutable::now();
//jours exceptions // Jours exceptions.
// $noCollectDays = CollecteException::where('magasin_id',$magasin->id)
// ->whereDate('date', '>', $now)
// ->whereDate('date', '<=', $finalday)
// ->orderBy('date')->get();
$noCollectDays = $magasin->collecteExceptions() $noCollectDays = $magasin->collecteExceptions()
->whereDate('date', '>', $now) ->whereDate('date', '>', $now)
->whereDate('date', '<=', $finalday) ->whereDate('date', '<=', $finalday)
@ -325,12 +430,11 @@ class OrdersController extends Controller
$availCreneaux = array(); $availCreneaux = array();
for ($i = 0; $i < $plage_days; $i++) { for ($i = 0; $i < $plage_days; $i++) {
/** @var Carbon */
$current = $today->add($i, 'day'); $current = $today->add($i, 'day');
$weekDay = $current->weekday(); $weekDay = $current->weekday();
$interval = CarbonInterval::createFromFormat('h:i', $plage[$weekDay]['interval'] ?? '00:15'); $interval = CarbonInterval::createFromFormat('h:i', $plage[$weekDay]['interval'] ?? '00:15');
//si c'est un jour exception skip // Si c'est un jour exception skip.
$skip = false; $skip = false;
foreach ($noCollectDays as $not_today) { foreach ($noCollectDays as $not_today) {
if ($current->isSameDay($not_today->date)) { if ($current->isSameDay($not_today->date)) {
@ -340,64 +444,63 @@ class OrdersController extends Controller
if ($skip) { if ($skip) {
continue; continue;
} }
//matinée $availCreneaux[$current->format('d/m/Y')] = array();
// Matinée.
if (!empty($plage[$weekDay]['morning_start'])) { if (!empty($plage[$weekDay]['morning_start'])) {
$currentTime = Carbon::createFromTimeString($plage[$weekDay]['morning_start']); $currentTime = Carbon::createFromTimeString($plage[$weekDay]['morning_start']);
$endTime = Carbon::createFromTimeString($plage[$weekDay]['morning_end']); $endTime = Carbon::createFromTimeString($plage[$weekDay]['morning_end']);
do {
$creneau = $currentTime->format('H:i');
$nbtakens = $magasin->timeslots()
->where('day', $current->format('d/m/Y'))
->where('time', $creneau)->count();
// $nbtakens = Timeslot::where('day', $current->format('d/m/Y')) $morningCreneaux = $this->addCreneaux(
// ->where('time', $creneau)->count(); $plage,
$weekDay,
$current,
$magasin,
$now,
$today,
$delaiPrepa,
$interval,
$currentTime,
$endTime
);
if ($nbtakens >= $plage[$weekDay]['max_orders_per_interval']) { $availCreneaux[$current->format('d/m/Y')] = array_merge(
$isDispo = false; $availCreneaux[$current->format('d/m/Y')],
} else { $morningCreneaux
$isDispo = true; );
} } //end if
// Aprem.
if ($current->addHours($currentTime->format('H'))->addMinutes($currentTime->format('i')) < $now->add($delaiPrepa)) {
$isDispo = false;
}
//attention si la date est passée (today mais avant maintenant) : pas de créneau
if ($current > $today || $currentTime >= $now) {
$availCreneaux[$current->format('d/m/Y')][] = array($creneau,$isDispo);
}
$currentTime->add($interval);
} while ($currentTime <= $endTime);
}
//aprem
if (!empty($plage[$weekDay]['afternoon_start'])) { if (!empty($plage[$weekDay]['afternoon_start'])) {
$currentTime = Carbon::createFromTimeString($plage[$weekDay]['afternoon_start']); $currentTime = Carbon::createFromTimeString($plage[$weekDay]['afternoon_start']);
$endTime = Carbon::createFromTimeString($plage[$weekDay]['afternoon_end']); $endTime = Carbon::createFromTimeString($plage[$weekDay]['afternoon_end']);
do {
$creneau = $currentTime->format('H:i');
$nbtakens = Timeslot::where('day', $current->format('d/m/Y'))->where('time', $creneau)->count();
if ($nbtakens >= $plage[$weekDay]['max_orders_per_interval']) {
$isDispo = false;
} else {
$isDispo = true;
}
if ($current->addHours($currentTime->format('H'))->addMinutes($currentTime->format('i')) < $now->add($delaiPrepa)) { $afternoonCreneaux = $this->addCreneaux(
$isDispo = false; $plage,
} $weekDay,
$current,
$magasin,
$now,
$today,
$delaiPrepa,
$interval,
$currentTime,
$endTime
);
//attention si la date est passée (today mais avant maintenant) : pas de créneau $availCreneaux[$current->format('d/m/Y')] = array_merge(
if ($current > $today || $currentTime >= $now) { $availCreneaux[$current->format('d/m/Y')],
$availCreneaux[$current->format('d/m/Y')][] = array($creneau,$isDispo); $afternoonCreneaux
} );
$currentTime->add($interval); } //end if
} while ($currentTime <= $endTime); }//end for
}
}
return $availCreneaux; return $availCreneaux;
} }
//call ajax pour le composant vue de timeslots /**
* Call ajax pour le composant vue de timeslots.
*
* @param Request $request
* @return array
*/
public function getAvailableCreneaux(Request $request) public function getAvailableCreneaux(Request $request)
{ {
return $this->getAvailableCreneauxByShop($request->id); return $this->getAvailableCreneauxByShop($request->id);
@ -407,6 +510,10 @@ class OrdersController extends Controller
* front * front
* enregistrement du créneau de collect * enregistrement du créneau de collect
* et validation de la commande * et validation de la commande
*
* @param Request $request
* @return \Illuminate\Http\RedirectResponse
* @throws \RuntimeException If email missing.
*/ */
public function setTimeSlot(Request $request) public function setTimeSlot(Request $request)
{ {
@ -416,7 +523,6 @@ class OrdersController extends Controller
'ok_cgv' => 'accepted', 'ok_cgv' => 'accepted',
]); ]);
$time_slot = Carbon::createFromFormat('d/m/Y-H:i', $request->selectedcreneau);
$tsday = explode('-', $request->selectedcreneau)[0]; $tsday = explode('-', $request->selectedcreneau)[0];
$tstime = explode('-', $request->selectedcreneau)[1]; $tstime = explode('-', $request->selectedcreneau)[1];
$magasin_id = $request->selectedmagasin; $magasin_id = $request->selectedmagasin;
@ -424,8 +530,8 @@ class OrdersController extends Controller
$order = Order::where('reference', '=', $reference)->firstOrFail(); $order = Order::where('reference', '=', $reference)->firstOrFail();
if ($order->status_id == 1) { if ($order->status_id == 1) {
// on ne traite l'enregistrement que pour les commandes en attente venant de l'étape de récap // On ne traite l'enregistrement que pour les commandes en attente venant de l'étape de récap.
//save timeslot // Save timeslot.
$timeslot = Timeslot::firstOrNew(['order_id' => $order->id]); $timeslot = Timeslot::firstOrNew(['order_id' => $order->id]);
$timeslot->order_id = $order->id; $timeslot->order_id = $order->id;
$timeslot->magasin_id = $magasin_id; $timeslot->magasin_id = $magasin_id;
@ -433,35 +539,53 @@ class OrdersController extends Controller
$timeslot->time = $tstime; $timeslot->time = $tstime;
$timeslot->save(); $timeslot->save();
//save order status // Save order status.
$order->status_id = 3; $order->status_id = 3;
$order->save(); $order->save();
//send confirm mail // Send confirm mail.
Mail::to($order->customer->email)->queue(new OrderConfirmMail($order)); Mail::to($order->customer->email)->queue(new OrderConfirmMail($order));
Mail::mailer('smtp2')->to($order->customer->email)->queue(new OrderConfirmMail($order));
//envoi du mail de confirmation aux admins site // Envoi du mail de confirmation aux admins site.
$toMailSetting = Setting::where('key', 'send_order_confirm_mail_to')->first(); /** @var \App\Model\Magasin|null */
if (empty($toMailSetting->value)) { $shop = Magasin::where('id', $magasin_id)->first();
$toMail = config('mail.from.address');
if ($shop and $shop->email_confirm) {
/** @var string */
$toMail = $shop->email_confirm;
} else { } else {
$toMail = $toMailSetting->value; /** @var string|null */
$toMail = \optional(Setting::where('key', 'send_order_confirm_mail_to')->first())->value;
if (!$toMail) {
/** @var string|null */
$toMail = config('mail.from.address');
}
} }
Mail::to($toMail)->queue(new OrderConfirmAdminMail($order));
Mail::mailer('smtp2')->to($toMail)->queue(new OrderConfirmAdminMail($order));
//export commande if (!$toMail) {
throw new \RuntimeException('Impossible de trouver un mail');
}
Mail::to($toMail)->queue(new OrderConfirmAdminMail($order));
// Export commande.
if (config('bosettings.regate_orders')) { if (config('bosettings.regate_orders')) {
CsvOrderWrite::dispatch($order); CsvOrderWrite::dispatch($order);
} }
} }//end if
//redirect to final confirmation // Redirect to final confirmation.
return redirect()->route('sales.confirm', ['reference' => $order->reference]); return redirect()->route('sales.confirm', ['reference' => $order->reference]);
} }
public function generateOrder($reference) /**
* generate Order
* Test method
*
* @param string $reference
* @return void
*/
public function generateOrder(string $reference)
{ {
$order = Order::where('reference', '=', $reference)->with('lines')->firstOrFail(); $order = Order::where('reference', '=', $reference)->with('lines')->firstOrFail();
$job = new CsvOrderWrite($order); $job = new CsvOrderWrite($order);
@ -472,15 +596,18 @@ class OrdersController extends Controller
/** /**
* front * front
* page de confirmation de commande * page de confirmation de commande
*
* @param string $reference
* @return \Illuminate\Contracts\View\View
*/ */
public function confirmOrder($reference) public function confirmOrder(string $reference)
{ {
$activestep = 4; $activestep = 4;
$idcommande = Session::get('idcommande'); $idcommande = Session::get('idcommande');
$order = Order::where('reference', '=', $reference)->firstOrFail(); $order = Order::where('reference', '=', $reference)->firstOrFail();
//1 seul magasin en base pour le moment // 1 seul magasin en base pour le moment
$magasin = Magasin::find($order->timeslot->magasin->id); $magasin = Magasin::find($order->timeslot->magasin->id);
return view('sales.confirm', compact('activestep', 'order', 'magasin')); return view('sales.confirm', compact('activestep', 'order', 'magasin'));
@ -489,9 +616,12 @@ class OrdersController extends Controller
/** /**
* bo * bo
* ajx : affichage d'infos sur un client * ajx : affichage d'infos sur un client
* @todo : déplacer dans le controller idoine *
* @param integer $id
* @param string|null $mode
* @return \Illuminate\Contracts\View\View
*/ */
public function getCustomerInfo($id, $mode = null) public function getCustomerInfo(int $id, string $mode = null)
{ {
$cust = Customers::findOrFail($id); $cust = Customers::findOrFail($id);
if (!is_null($mode)) { if (!is_null($mode)) {
@ -499,7 +629,7 @@ class OrdersController extends Controller
return view('bo.customer.tippy-card', compact('cust')); return view('bo.customer.tippy-card', compact('cust'));
} }
if ($mode == "json") { if ($mode == "json") {
return $cust; return $cust->apiData;
} }
return view('bo.customer.info-card', compact('cust')); return view('bo.customer.info-card', compact('cust'));
} }
@ -507,9 +637,12 @@ class OrdersController extends Controller
} }
/** /**
* bo : page détatil commande * bo : page détail commande
*
* @param string $reference
* @return \Illuminate\Contracts\View\View
*/ */
public function orderDetail($reference) public function orderDetail(string $reference)
{ {
$order = Order::where('reference', '=', $reference)->firstOrFail(); $order = Order::where('reference', '=', $reference)->firstOrFail();
return view('bo.orders.detail', compact('order')); return view('bo.orders.detail', compact('order'));

View file

@ -21,7 +21,10 @@ use Illuminate\Support\Facades\File;
class ProductsController extends Controller class ProductsController extends Controller
{ {
/** /**
* Bo index page for products * Display a listing of the resource.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/ */
public function index(Request $request) public function index(Request $request)
{ {
@ -40,13 +43,12 @@ class ProductsController extends Controller
} }
$products = $products->paginate(10); $products = $products->paginate(10);
//ici récupération des infos additionnelles pour affichage dans la liste // Ici récupération des infos additionnelles pour affichage dans la liste.
// @todo : parametrer l'occurence de ces affichages car ça n'aura aucun sens selon le type de produit
foreach ($products as &$product) { foreach ($products as &$product) {
if(!empty($product->product_type)) { if (!empty($product->product_type)) {
$product->additionnalProductInfo = $product->additionnalProductInfo($product->product_type); $product->additionnalProductInfo = $product->additionnalProductInfo($product->product_type);
if ($product->additionnalProductInfo === null) { if ($product->additionnalProductInfo === null) {
//n'existe pas on renseigne un vide // N'existe pas on renseigne un vide.
$product_type = $product->product_type; $product_type = $product->product_type;
$modelClass = 'App\Models\\' . ucfirst($product_type); $modelClass = 'App\Models\\' . ucfirst($product_type);
$product->$product_type = new $modelClass(); $product->$product_type = new $modelClass();
@ -58,32 +60,34 @@ class ProductsController extends Controller
} }
/** /**
* create à product * Show the form for creating a new resource.
* @param string $product_type
* @return \Illuminate\Http\Response
*/ */
public function create($product_type = null) public function create(string $product_type = null)
{ {
if (!empty($product_type) && !array_key_exists($product_type, config('theme.enum_product_types'))) { if (!empty($product_type) && !array_key_exists($product_type, config('theme.enum_product_types'))) {
abort(404, "Cette page n'existe pas."); abort(404, "Cette page n'existe pas.");
//return redirect()->route('bo.products.index');
} }
$modelClass = 'App\Models\\' . ucfirst($product_type); $modelClass = 'App\Models\\' . ucfirst($product_type);
$product = new Product(); $product = new Product();
if(!empty($product_type)) { if (!empty($product_type)) {
$product->$product_type = new $modelClass(); $product->$product_type = new $modelClass();
} }
$ranges = Range::all(); $ranges = Range::all();
$taxes = TaxRate::all(); $taxes = TaxRate::all();
return view('bo.products.create', compact('product_type', 'product', 'ranges', 'taxes')); return view('bo.products.create', compact('product_type', 'product', 'ranges', 'taxes'));
} }
/** /**
* store a new product * store a new product
* @todo : manage tags and associated products *
* @todo : enregistrer unité de vente, poids et unité de poids * @param ProductRequest $request
* @return \Illuminate\Http\Response
*/ */
public function store(ProductRequest $request) public function store(ProductRequest $request)
{ {
//products fields // Products fields.
$name = $request->name; $name = $request->name;
$description = $request->description; $description = $request->description;
$picture = $request->picture; $picture = $request->picture;
@ -98,15 +102,17 @@ class ProductsController extends Controller
$weight = $request->weight; $weight = $request->weight;
$weight_unit = $request->weight_unit; $weight_unit = $request->weight_unit;
$status = $request->status === null ? 0 : 1; $status = $request->status === null ? 0 : 1;
$orderable_start = $request->orderable_start_date === null ? null : $request->orderable_start_date . " " . $request->orderable_start_time; $orderable_start = $request->orderable_start_date === null ? null
$orderable_end = $request->orderable_end_date === null ? null : $request->orderable_end_date . " " . $request->orderable_end_time; : $request->orderable_start_date . " " . $request->orderable_start_time;
$orderable_end = $request->orderable_end_date === null ? null
: $request->orderable_end_date . " " . $request->orderable_end_time;
$star = $request->star === null ? 0 : 1; $star = $request->star === null ? 0 : 1;
$slug = Str::slug($name); $slug = Str::slug($name);
$rangeId = $request->range_id; $rangeId = $request->range_id;
$taxRateId = $request->tax_rate_id; $taxRateId = $request->tax_rate_id;
// Check si le slug existe déjà dans cette gamme de produits // Check si le slug existe déjà dans cette gamme de produits.
$slugExist = Product::where([ $slugExist = Product::where([
['range_id', $rangeId], ['range_id', $rangeId],
['slug', $slug] ['slug', $slug]
@ -140,7 +146,7 @@ class ProductsController extends Controller
$product->tax_rate_id = $taxRateId; $product->tax_rate_id = $taxRateId;
$product->save(); $product->save();
// Check si le slug existe dans la table old_slugs, auquel cas il est attribué a ce nouveau produit // Check si le slug existe dans la table old_slugs, auquel cas il est attribué a ce nouveau produit.
$oldSlug = OldSlug::where('slug', $slug)->first(); $oldSlug = OldSlug::where('slug', $slug)->first();
if ($oldSlug && $oldSlug->product_id !== $product->id) { if ($oldSlug && $oldSlug->product_id !== $product->id) {
$oldSlug->product_id = $product->id; $oldSlug->product_id = $product->id;
@ -163,7 +169,7 @@ class ProductsController extends Controller
$product->save(); $product->save();
} }
//ajout des infos additionnelles // Ajout des infos additionnelles.
$product_type = $request->product_type; $product_type = $request->product_type;
if ($product_type !== null) { if ($product_type !== null) {
@ -174,23 +180,27 @@ class ProductsController extends Controller
} }
//additionnal product info (foodProduct) // Additionnal product info (foodProduct).
return redirect()->route('bo.products.index'); return redirect()->route('bo.products.index');
} }
/** /**
* edit an existing product * Show the form for editing the specified resource.
*
* @param integer $id
* @return \Illuminate\Http\Response
*/ */
public function edit($id) public function edit(int $id)
{ {
$product = Product::findOrFail($id); $product = Product::findOrFail($id);
if(!empty($product->product_type)) { if (!empty($product->product_type)) {
$product->additionnalProductInfo = $product->additionnalProductInfo($product->product_type); $product->additionnalProductInfo = $product->additionnalProductInfo($product->product_type);
//above lines equivalent to : /**
//$product = Product::with('additionnalProductInfo')->findOrFail($id); * Above lines equivalent to
* $product = Product::with('additionnalProductInfo')->findOrFail($id);
*/
if ($product->additionnalProductInfo === null) { if ($product->additionnalProductInfo === null) {
//n'existe pas on renseigne un vide // N'existe pas on renseigne un vide.
$product_type = $product->product_type; $product_type = $product->product_type;
$modelClass = 'App\Models\\' . ucfirst($product_type); $modelClass = 'App\Models\\' . ucfirst($product_type);
$product->$product_type = new $modelClass(); $product->$product_type = new $modelClass();
@ -206,23 +216,30 @@ class ProductsController extends Controller
$selectedProds = $product->products; $selectedProds = $product->products;
$existingProds = $existingProds->diff($selectedProds); $existingProds = $existingProds->diff($selectedProds);
return view('bo.products.edit', compact('product', 'ranges', 'taxes', 'existingTags', 'selectedtags', 'existingProds', 'selectedProds')); return view('bo.products.edit', compact(
'product',
'ranges',
'taxes',
'existingTags',
'selectedtags',
'existingProds',
'selectedProds'
));
} }
/** /**
* update an existing product * Update the specified resource.
*
* @param \App\Models\Product $product
* @param ProductRequest $request
* @return \Illuminate\Http\Response
*/ */
public function update(Product $product, ProductRequest $request) public function update(Product $product, ProductRequest $request)
{ {
//$product = Product::findOrFail($id);
$orderable_end_time = $request->orderable_end_time === null ? "23:59" : $request->orderable_end_time; $orderable_end_time = $request->orderable_end_time === null ? "23:59" : $request->orderable_end_time;
$name = $request->name; $name = $request->name;
$description = $request->description; $description = $request->description;
$picture = $request->picture;
$picture_large = $request->picture_large;
$price = $request->price; $price = $request->price;
$invoicing_unit = $request->invoicing_unit; $invoicing_unit = $request->invoicing_unit;
$priceBuy = $request->price_buy; $priceBuy = $request->price_buy;
@ -233,59 +250,22 @@ class ProductsController extends Controller
$weight = $request->weight; $weight = $request->weight;
$weight_unit = $request->weight_unit; $weight_unit = $request->weight_unit;
$status = $request->status === null ? 0 : 1; $status = $request->status === null ? 0 : 1;
$orderable_start = $request->orderable_start_date === null ? null : $request->orderable_start_date . " " . $request->orderable_start_time; $orderable_start = $request->orderable_start_date === null ? null
$orderable_end = $request->orderable_end_date === null ? null : $request->orderable_end_date . " " . $orderable_end_time; : $request->orderable_start_date . " " . $request->orderable_start_time;
$orderable_end = $request->orderable_end_date === null ? null
: $request->orderable_end_date . " " . $orderable_end_time;
$star = $request->star === null ? 0 : 1; $star = $request->star === null ? 0 : 1;
$slug = Str::slug($name); $slug = Str::slug($name);
$rangeId = $request->range_id; $rangeId = $request->range_id;
$taxRateId = $request->tax_rate_id; $taxRateId = $request->tax_rate_id;
$tags = $request->tags;
// Check si le slug existe déjà dans cette gamme de produits $this->checkSlugExistsWithinRange($request, $rangeId, $slug, $product->id);
$slugExist = Product::where([
['range_id', $rangeId],
['slug', $slug],
['id', '<>', $product->id]
])->first();
if ($slugExist) { $this->manageProductImages($request->picture, $product, $request->picture_large);
return redirect()->back()
->withInput($request->input())
->withErrors("Erreur : un produit avec le slug d'accès \"" . $slug .
"\" éxiste déjà. Veuillez changer le nom du produit.");
}
$str_random = Str::random(5);
if ($picture !== null) {
if ($product->picture !== null && file_exists(public_path('images/produits/') . $product->picture)) {
unlink(public_path('images/produits/') . $product->picture);
}
$imageName = $product->id . '_' . $str_random . '.' . $picture->extension();
$picture->move(public_path('images/produits'), $imageName);
$product->picture = $imageName;
}
if ($picture_large !== null) {
if ($product->picture_large !== null && file_exists(public_path('images/produits/') . $product->picture_large)) {
unlink(public_path('images/produits/') . $product->picture_large);
}
$imageName = $product->id . '_' . $str_random . '_large.' . $picture_large->extension();
$picture_large->move(public_path('images/produits'), $imageName);
$product->picture_large = $imageName;
}
$product->name = $name; $product->name = $name;
if ($product->slug != $slug) { $this->saveNewSlugForProduct($product, $slug);
$exist = OldSlug::where('slug', $product->slug)->first();
if ($exist === null) {
$oldSlug = new OldSlug();
$oldSlug->product_id = $product->id;
$oldSlug->slug = $product->slug;
$oldSlug->save();
}
}
$product->description = $description; $product->description = $description;
$product->price = $price; $product->price = $price;
@ -306,65 +286,189 @@ class ProductsController extends Controller
$product->tax_rate_id = $taxRateId; $product->tax_rate_id = $taxRateId;
$product->save(); $product->save();
// Check si le slug existe dans la table old_slug, auquel cas il est attribué a ce nouveau produit // Check si le slug existe dans la table old_slug, auquel cas il est attribué a ce nouveau produit.
$oldSlug = OldSlug::where('slug', $slug)->first(); $this->cleanOldSlug($slug);
if ($oldSlug) {
$oldSlug->delete();
}
//ajout des infos additionnelles // Ajout des infos additionnelles.
$product_type = $request->product_type; $product_type = $request->product_type;
//save additionnal // Save additionnal.
if ($product_type !== null) { if ($product_type !== null) {
$methodName = "save" . ucfirst($product_type); $methodName = "save" . ucfirst($product_type);
$this->$methodName($request, $product->id); $this->$methodName($request, $product->id);
} }
//tags associés // Tags associés.
if (!empty($tags)) { $this->syncTags($request->tags, $product);
$arTagIds = array();
foreach ($tags as $tag) {
$oTag = json_decode($tag);
if (empty($oTag->id)) {
//we need a new tag
$arTagIds[] = $this->storeTag($oTag);
} else {
$arTagIds[] = $oTag->id;
}
}
//prise en charge de la liaison avec les produits
$product->tags()->sync($arTagIds);
} else {
$product->tags()->sync(array());
}
//produits associés // Produits associés.
if (!empty($request->prods)) { $this->syncProduitsAssocies($request->prods, $product);
$productIds = explode(",", $request->prods);
//prise en charge de la liaison avec les produits
$product->products()->sync($productIds);
} else {
$product->products()->sync(array());
}
return redirect()->route('bo.products.edit', $product->id)->with('success', 'Modifications enregistrés !'); return redirect()->route('bo.products.edit', $product->id)->with('success', 'Modifications enregistrés !');
} }
/**
* Check if slug already exists, if so redirect
*
* @param Request $request
* @param integer $rangeId
* @param string $slug
* @param integer|null $productId
* @return \Illuminate\Http\RedirectResponse|void
*/
private function checkSlugExistsWithinRange(Request $request, int $rangeId, string $slug, int $productId = null)
{
// Check si le slug existe déjà dans cette gamme de produits.
$slugExist = Product::where([
['range_id', $rangeId],
['slug', $slug],
['id', '<>', $productId]
])->first();
if ($slugExist) {
return redirect()->back()
->withInput($request->input())
->withErrors("Erreur : un produit avec le slug d'accès \"" . $slug .
"\" éxiste déjà. Veuillez changer le nom du produit.");
}
}
/**
* If new slug for product then save oldslug
*
* @param Product $product
* @param string $slug
* @return void
*/
private function saveNewSlugForProduct(Product $product, string $slug)
{
if ($product->slug != $slug) {
$exist = OldSlug::where('slug', $product->slug)->first();
if ($exist === null) {
$oldSlug = new OldSlug();
$oldSlug->product_id = $product->id;
$oldSlug->slug = $product->slug;
$oldSlug->save();
}
}
}
/**
* clean oldslug if exists
*
* @param string $slug
* @return void
*/
private function cleanOldSlug(string $slug)
{
// Check si le slug existe dans la table old_slug, auquel cas il est attribué a ce nouveau produit.
$oldSlug = OldSlug::where('slug', $slug)->first();
if ($oldSlug) {
$oldSlug->delete();
}
}
/**
* Store and update saved images on product
*
* @param UploadedFile|null $picture
* @param Product $product
* @param UploadedFile|null $picture_large
* @return void
*/
private function manageProductImages($picture, Product &$product, $picture_large)
{
$str_random = Str::random(5);
if ($picture !== null) {
if (
$product->picture !== null &&
file_exists(public_path('images/produits/') . $product->picture)
) {
unlink(public_path('images/produits/') . $product->picture);
}
$imageName = $product->id . '_' . $str_random . '.' . $picture->extension();
$picture->move(public_path('images/produits'), $imageName);
$product->picture = $imageName;
}
if ($picture_large !== null) {
if (
$product->picture_large !== null &&
file_exists(public_path('images/produits/') . $product->picture_large)
) {
unlink(public_path('images/produits/') . $product->picture_large);
}
$imageName = $product->id . '_' . $str_random . '_large.' . $picture_large->extension();
$picture_large->move(public_path('images/produits'), $imageName);
$product->picture_large = $imageName;
}
}
/**
* sync tags to product
*
* @param array|null $tags
* @param Product $product
* @return void
*/
private function syncTags(array $tags = null, Product &$product)
{
if (!empty($tags)) {
$arTagIds = array();
foreach ($tags as $tag) {
$oTag = json_decode($tag);
if (empty($oTag->id)) {
// We need a new tag.
$arTagIds[] = $this->storeTag($oTag);
} else {
$arTagIds[] = $oTag->id;
}
}
// Prise en charge de la liaison avec les produits.
$product->tags()->sync($arTagIds);
} else {
$product->tags()->sync(array());
}
}
/**
* sync associated products to product
*
* @param string|null $prods
* @param Product $product
* @return void
*/
private function syncProduitsAssocies(string $prods = null, Product $product)
{
if (!empty($prods)) {
$productIds = explode(",", $prods);
// Prise en charge de la liaison avec les produits.
$product->products()->sync($productIds);
} else {
$product->products()->sync(array());
}
}
/** /**
* Helper method to store a new tag if necessary * Helper method to store a new tag if necessary
* Otherwise retreive an existing tag to associate its id * Otherwise retreive an existing tag to associate its id
*
* @param \App\Models\Tag $oTag
* @return integer
*/ */
public function storeTag($oTag) public function storeTag(Tag $oTag)
{ {
$slug = Str::slug($oTag->label); $slug = Str::slug($oTag->label);
$tag = Tag::where('slug', $slug)->first(); $tag = Tag::where('slug', $slug)->first();
if ($tag === null) { if ($tag === null) {
//si on pas encore ce tag on le crée // Si on pas encore ce tag on le crée.
$tag = new Tag(); $tag = new Tag();
$tag->label = $oTag->label; $tag->label = $oTag->label;
$tag->slug = Str::slug($oTag->label); $tag->slug = Str::slug($oTag->label);
$tag->status = 1; //a new tag is published by default // A new tag is published by default.
$tag->status = 1;
$tag->order = TagsController::getLastOrder(); $tag->order = TagsController::getLastOrder();
$tag->save(); $tag->save();
} }
@ -373,16 +477,21 @@ class ProductsController extends Controller
/** /**
* destroy a product (soft delete) * destroy a product (soft delete)
* @todo : manage liaisons *
* @param integer $id
* @return \Illuminate\Http\Response
*/ */
public function destroy($id) public function destroy(int $id)
{ {
$product = Product::findOrFail($id); $product = Product::findOrFail($id);
if ($product->picture !== null && file_exists(public_path('images/produits/') . $product->picture)) { if ($product->picture !== null && file_exists(public_path('images/produits/') . $product->picture)) {
unlink(public_path('images/produits/') . $product->picture); unlink(public_path('images/produits/') . $product->picture);
} }
if ($product->picture_large !== null && file_exists(public_path('images/produits/') . $product->picture_large)) { if (
$product->picture_large !== null &&
file_exists(public_path('images/produits/') . $product->picture_large)
) {
unlink(public_path('images/produits/') . $product->picture_large); unlink(public_path('images/produits/') . $product->picture_large);
} }
@ -394,41 +503,55 @@ class ProductsController extends Controller
/** /**
* check if inco data exists * check if inco data exists
*
* @param \Illuminate\Http\Request $request
* @return mixed
*/ */
public function checkIncoData(Request $request) { public function checkIncoData(Request $request)
$id = $request->id; {
$id = $request->id;
$xmlInco = XmlInco::find($id); $xmlInco = XmlInco::find($id);
if(!empty($xmlInco)) { if (!empty($xmlInco)) {
//we have data // We have data.
$hasInco = __("Des données Inco sont disponibles, souhaitez vous les associer à ce produit ?"); $hasInco = __("Des données Inco sont disponibles, souhaitez vous les associer à ce produit ?");
$preparedImages = $this->prepareIncoImages($xmlInco->picture); $preparedImages = $this->prepareIncoImages($xmlInco->picture);
return view('bo.products.load-inco',compact('hasInco','xmlInco','preparedImages')); return view('bo.products.load-inco', compact('hasInco', 'xmlInco', 'preparedImages'));
} else { } else {
return array("data"=> array()); return array("data" => array());
} }
} }
public function getPrepareIncoImages(Request $request) { /**
$picture = $request->picture; * Show prepared images
*
* @param Request $request
* @return \Illuminate\Contracts\View\View
*/
public function getPrepareIncoImages(Request $request)
{
$picture = $request->picture;
$preparedImages = $this->prepareIncoImages($picture); $preparedImages = $this->prepareIncoImages($picture);
return view('bo.products.inco-images', compact('preparedImages')); return view('bo.products.inco-images', compact('preparedImages'));
} }
/** /**
* prepare Inco Images * prepared images
*
* @param array $picture
* @return \Illuminate\Contracts\View\View
*/ */
public function prepareIncoImages($picture) { public function prepareIncoImages(array $picture)
{
$preparedImages = array(); $preparedImages = array();
foreach ($picture as $incoImage) { foreach ($picture as $incoImage) {
//charge // Charge.
if(File::exists(storage_path($incoImage))) { if (File::exists(storage_path($incoImage))) {
$imagePath = storage_path($incoImage); $imagePath = storage_path($incoImage);
//redimensionne // Redimensionne.
//create mask // Create mask.
//Resize original image into mask // Resize original image into mask.
$this->resizeImg( $this->resizeImg(
$imagePath, $imagePath,
config('theme.product_image_large_maxwidth'), config('theme.product_image_large_maxwidth'),
@ -445,15 +568,24 @@ class ProductsController extends Controller
$preparedImages[] = "inco/images/" . File::name($incoImage) . "_large.png"; $preparedImages[] = "inco/images/" . File::name($incoImage) . "_large.png";
} }//end if
} }//end foreach
return $preparedImages; return $preparedImages;
} }
/** /**
* redimensionne une image dans un masque * redimensionne une image dans un masque
*/ */
private function resizeImg($imagePath, $maskWidth, $maskHeight, $resizedName) /**
* redimensionne une image dans un masque
*
* @param string $imagePath
* @param integer $maskWidth
* @param integer $maskHeight
* @param string $resizedName
* @return boolean|void
*/
private function resizeImg(string $imagePath, int $maskWidth, int $maskHeight, string $resizedName)
{ {
// ---- création du masque // ---- création du masque
$mask = imagecreatetruecolor($maskWidth, $maskHeight); $mask = imagecreatetruecolor($maskWidth, $maskHeight);
@ -479,34 +611,43 @@ class ProductsController extends Controller
} }
// ---- Chargement de l'image source // ---- Chargement de l'image source
$img = $image_create_func($imagePath); $img = $image_create_func($imagePath);
list($imgWidth, $imgHeight) = getimagesize($imagePath); list($imgWidth, $imgHeight) = getimagesize($imagePath);
// ---- Calcul les nouvelles dimensions de l'image // ---- Calcul les nouvelles dimensions de l'image
if($imgWidth > $imgHeight){ if ($imgWidth > $imgHeight) {
$finalWidth = $maskWidth; $finalWidth = $maskWidth;
$finalHeight = ($finalWidth*$imgHeight)/$imgWidth; $finalHeight = ($finalWidth * $imgHeight) / $imgWidth;
}else{ } else {
$finalHeight = $maskHeight; $finalHeight = $maskHeight;
$finalWidth = ($finalHeight*$imgWidth)/$imgHeight; $finalWidth = ($finalHeight * $imgWidth) / $imgHeight;
} }
// ---- Redimensionne l'image source // ---- Redimensionne l'image source
$resizeImg = imagecreatetruecolor($finalWidth, $finalHeight); $resizeImg = imagecreatetruecolor($finalWidth, $finalHeight);
imagealphablending( $resizeImg, false ); imagealphablending($resizeImg, false);
imagesavealpha( $resizeImg, true ); imagesavealpha($resizeImg, true);
imagecopyresampled($resizeImg, $img, 0, 0, 0, 0, $finalWidth, $finalHeight, $imgWidth, $imgHeight); imagecopyresampled($resizeImg, $img, 0, 0, 0, 0, $finalWidth, $finalHeight, $imgWidth, $imgHeight);
// ---- Copie l'image redimensionnée dans le mask // Copie l'image redimensionnée dans le mask.
imagecopy($mask, $resizeImg, ($maskWidth-$finalWidth)/2, ($maskHeight-$finalHeight)/2, 0, 0, imagesx($resizeImg), imagesy($resizeImg)); imagecopy(
imagealphablending( $mask, false ); $mask,
imagesavealpha( $mask, true ); $resizeImg,
($maskWidth - $finalWidth) / 2,
($maskHeight - $finalHeight) / 2,
0,
0,
imagesx($resizeImg),
imagesy($resizeImg)
);
imagealphablending($mask, false);
imagesavealpha($mask, true);
//écrit dans storage/app/public // Ecrit dans storage/app/public.
// ---- Créer le fichier final // Créer le fichier final.
imagepng($mask, storage_path('app/public/inco/images/' . $resizedName), 5); imagepng($mask, storage_path('app/public/inco/images/' . $resizedName), 5);
// ---- Libère la mémoire associée aux images manipulées // Libère la mémoire associée aux images manipulées.
imagedestroy($img); imagedestroy($img);
imagedestroy($resizeImg); imagedestroy($resizeImg);
imagedestroy($mask); imagedestroy($mask);
@ -515,6 +656,12 @@ class ProductsController extends Controller
/** /**
* set une image préparée comme image du produit * set une image préparée comme image du produit
*/ */
/**
* set une image préparée comme image du produit
*
* @param Request $request
* @return \App\Models\Product
*/
public function setIncoImage(Request $request) public function setIncoImage(Request $request)
{ {
$imagePath = $request->picture; $imagePath = $request->picture;
@ -522,34 +669,37 @@ class ProductsController extends Controller
$imagePath = storage_path("app/public/" . $imagePath); $imagePath = storage_path("app/public/" . $imagePath);
$product_id = $request->product; $product_id = $request->product;
$product = Product::findOrFail($product_id); $product = Product::findOrFail($product_id);
$str_random = Str::random(5); $str_random = Str::random(5);
//default is large image // Default is large image.
$finalImageName = $product->id . '_' . $str_random . '_large.' . File::extension($imagePath); $finalImageName = $product->id . '_' . $str_random . '_large.' . File::extension($imagePath);
$productimagespath = public_path('images/produits'); $productimagespath = public_path('images/produits');
if(!File::isDirectory($productimagespath)) { if (!File::isDirectory($productimagespath)) {
File::makeDirectory($productimagespath, 0644, true); File::makeDirectory($productimagespath, 0644, true);
} }
File::copy($imagePath, $productimagespath . "/" . $finalImageName); File::copy($imagePath, $productimagespath . "/" . $finalImageName);
//suppression de l'ancien fichier // Suppression de l'ancien fichier.
if ($product->picture_large !== null && file_exists(public_path('images/produits/') . $product->picture_large)) { if (
$product->picture_large !== null &&
file_exists(public_path('images/produits/') . $product->picture_large)
) {
unlink(public_path('images/produits/') . $product->picture_large); unlink(public_path('images/produits/') . $product->picture_large);
} }
$product->picture_large = $finalImageName; $product->picture_large = $finalImageName;
//now set small image // Now set small image.
$imagePath = str_replace("_large", "_small", $imagePath); $imagePath = str_replace("_large", "_small", $imagePath);
$finalImageName = $product->id . '_' . $str_random . '.' . File::extension($imagePath); $finalImageName = $product->id . '_' . $str_random . '.' . File::extension($imagePath);
File::copy($imagePath, $productimagespath . "/" . $finalImageName); File::copy($imagePath, $productimagespath . "/" . $finalImageName);
//suppression de l'ancien fichier // Suppression de l'ancien fichier.
if ($product->picture !== null && file_exists(public_path('images/produits/') . $product->picture)) { if ($product->picture !== null && file_exists(public_path('images/produits/') . $product->picture)) {
unlink(public_path('images/produits/') . $product->picture); unlink(public_path('images/produits/') . $product->picture);
} }
@ -558,15 +708,17 @@ class ProductsController extends Controller
$product->save(); $product->save();
//@TODO : envoyer une réponse pour maj de l'interface
return $product; return $product;
} }
/** /**
* helper method to update additionnal product info * helper method to update additionnal product info
* foodProduct *
* @param Request $request
* @param integer $product_id
* @return void
*/ */
public function saveFoodProduct(Request $request, $product_id) public function saveFoodProduct(Request $request, int $product_id)
{ {
$foodProduct = FoodProduct::firstOrNew([ $foodProduct = FoodProduct::firstOrNew([
'product_id' => $product_id, 'product_id' => $product_id,
@ -618,11 +770,17 @@ class ProductsController extends Controller
} }
/** /**
* helper method to update additionnal product info * helper method to update toolproduct info
* toolProduct *
* @param Request $request
* @param integer $product_id
* @return void
*
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
*/ */
public function saveToolProduct(Request $request, $product_id) public function saveToolProduct(Request $request, int $product_id)
{ {
// phpcs:enable
$toolProduct = ToolProduct::firstOrNew([ $toolProduct = ToolProduct::firstOrNew([
'product_id' => $product_id, 'product_id' => $product_id,
]); ]);
@ -631,58 +789,50 @@ class ProductsController extends Controller
} }
/** /**
* helper method to update additionnal product info * helper method to update anifoodProduct info
* anifoodProduct *
* @param Request $request
* @param integer $product_id
* @return void
*/ */
public function saveAnifoodProduct(Request $request, $product_id) public function saveAnifoodProduct(Request $request, int $product_id)
{ {
$anifoodProduct = AnifoodProduct::firstOrNew([ $anifoodProduct = AnifoodProduct::firstOrNew([
'product_id' => $product_id, 'product_id' => $product_id,
]); ]);
$anifoodProduct->composition = $request->composition; $anifoodProduct->composition = $request->composition;
$anifoodProduct->servings = $request->servings; $anifoodProduct->servings = $request->servings;
$anifoodProduct->save(); $anifoodProduct->save();
} }
/** /**
* helper method to update additionnal product info * helper method to update garmentProduct info
* garmentProduct *
* @param Request $request
* @param integer $product_id
* @return void
*/ */
public function saveGarmentProduct(Request $request, $product_id) public function saveGarmentProduct(Request $request, int $product_id)
{ {
$garmentProduct = GarmentProduct::firstOrNew([ $garmentProduct = GarmentProduct::firstOrNew([
'product_id' => $product_id, 'product_id' => $product_id,
]); ]);
$garmentProduct->size = $request->size; $garmentProduct->size = $request->size;
$garmentProduct->color = $request->color; $garmentProduct->color = $request->color;
$garmentProduct->material = $request->material; $garmentProduct->material = $request->material;
$garmentProduct->save(); $garmentProduct->save();
} }
/**
* product detail intended for Bo
*/
public function show()
{
//not in use
}
/** /**
* index des produits mis en avant * index des produits mis en avant
*
* @return * @return \Illuminate\Contracts\View\View
*/ */
public function starred() public function starred()
{ {
$products = Product::where('star', 1)->paginate(10); $products = Product::where('star', 1)->paginate(10);
return view('bo.products.starred', compact('products')); return view('bo.products.starred', compact('products'));
} }
/**
* working method to start the mapping of inco fields into foodproduct
*/
/*
public function mapIncoFieldsToFoodProduct () {
}*/
} }

View file

@ -31,17 +31,15 @@ class PromotionsController extends Controller
$discTypes = DiscountType::all(); $discTypes = DiscountType::all();
$existingProds = Product::all(); $existingProds = Product::all();
$promotion = new Promotion(); $promotion = new Promotion();
$selectedProds = $promotion->products; $selectedProds = $promotion->products;
//$existingProds = $existingProds->diff($selectedProds);
return view('bo.promotions.create', compact('discTypes', 'existingProds', 'selectedProds')); return view('bo.promotions.create', compact('discTypes', 'existingProds', 'selectedProds'));
} }
/** /**
* Store a newly created resource in storage. * Store a newly created resource in storage.
* *
* @param \Illuminate\Http\Request $request * @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response * @return \Illuminate\Http\Response
*/ */
public function store(Request $request) public function store(Request $request)
@ -52,42 +50,31 @@ class PromotionsController extends Controller
]); ]);
$productIds = explode(",", $request->product_id); $productIds = explode(",", $request->product_id);
$discType = $request->discount_type_id; $discType = $request->discount_type_id;
$value = $request->discount_value; $value = $request->discount_value;
$date_start = $request->date_start_date . " " . $request->date_start_time; $date_start = $request->date_start_date . " " . $request->date_start_time;
$date_end = $request->date_end_date . " " . $request->date_end_time; $date_end = $request->date_end_date . " " . $request->date_end_time;
$promotion = new Promotion(); $promotion = new Promotion();
$promotion->discount_type_id = $discType; $promotion->discount_type_id = $discType;
$promotion->discount_value = $value; $promotion->discount_value = $value;
$promotion->date_start = $date_start; $promotion->date_start = $date_start;
$promotion->date_end = $date_end; $promotion->date_end = $date_end;
$promotion->save(); $promotion->save();
//prise en charge de la liaison avec les produits // Prise en charge de la liaison avec les produits.
$promotion->products()->sync($productIds); $promotion->products()->sync($productIds);
return redirect()->route('bo.promotions.index'); return redirect()->route('bo.promotions.index');
} }
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
{
//
}
/** /**
* Show the form for editing the specified resource. * Show the form for editing the specified resource.
* *
* @param int $id * @param integer $id
* @return \Illuminate\Http\Response * @return \Illuminate\Http\Response
*/ */
public function edit($id) public function edit(int $id)
{ {
$promotion = Promotion::findOrFail($id); $promotion = Promotion::findOrFail($id);
$discTypes = DiscountType::all(); $discTypes = DiscountType::all();
@ -102,11 +89,11 @@ class PromotionsController extends Controller
/** /**
* Update the specified resource in storage. * Update the specified resource in storage.
* *
* @param \Illuminate\Http\Request $request * @param \Illuminate\Http\Request $request
* @param int $id * @param integer $id
* @return \Illuminate\Http\Response * @return \Illuminate\Http\Response
*/ */
public function update(Request $request, $id) public function update(Request $request, int $id)
{ {
$promotion = Promotion::findOrFail($id); $promotion = Promotion::findOrFail($id);
@ -115,35 +102,34 @@ class PromotionsController extends Controller
]); ]);
$productIds = explode(",", $request->product_id); $productIds = explode(",", $request->product_id);
$discType = $request->discount_type_id; $discType = $request->discount_type_id;
$value = $request->discount_value; $value = $request->discount_value;
$date_start = $request->date_start_date . " " . $request->date_start_time; $date_start = $request->date_start_date . " " . $request->date_start_time;
$date_end = $request->date_end_date . " " . $request->date_end_time; $date_end = $request->date_end_date . " " . $request->date_end_time;
$promotion->discount_type_id = $discType; $promotion->discount_type_id = $discType;
$promotion->discount_value = $value; $promotion->discount_value = $value;
$promotion->date_start = $date_start; $promotion->date_start = $date_start;
$promotion->date_end = $date_end; $promotion->date_end = $date_end;
$promotion->save(); $promotion->save();
//prise en charge de la liaison avec les produits // Prise en charge de la liaison avec les produits.
$promotion->products()->sync($productIds); $promotion->products()->sync($productIds);
return redirect()->route('bo.promotions.edit', $promotion->id)->with('success', 'Modifications enregistrés !'); return redirect()->route('bo.promotions.edit', $promotion->id)->with('success', 'Modifications enregistrés !');
} }
/** /**
* Remove the specified resource from storage. * Remove the specified resource from storage.
* *
* @param int $id * @param integer $id
* @return \Illuminate\Http\Response * @return \Illuminate\Http\Response
*/ */
public function destroy($id) public function destroy(int $id)
{ {
$p = Promotion::findOrFail($id); $p = Promotion::findOrFail($id);
//prise en charge de la liaison avec les produits // Prise en charge de la liaison avec les produits.
$p->products()->detach(); $p->products()->detach();
$p->delete(); $p->delete();

View file

@ -11,24 +11,40 @@ use Illuminate\Support\Str;
class RangesController extends Controller class RangesController extends Controller
{ {
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index() public function index()
{ {
$ranges = Range::all(); $ranges = Range::all();
return view('bo.ranges.index', compact('ranges')); return view('bo.ranges.index', compact('ranges'));
} }
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create() public function create()
{ {
return view('bo.ranges.create'); return view('bo.ranges.create');
} }
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request) public function store(Request $request)
{ {
$name = $request->name; $name = $request->name;
$slug = Str::slug($name); $slug = Str::slug($name);
$description = $request->description; $description = $request->description;
$picture = $request->picture; $picture = $request->picture;
$status = $request->status === null ? 0 : 1; $status = $request->status === null ? 0 : 1;
$request->validate([ $request->validate([
'name' => 'required|string|max:255', 'name' => 'required|string|max:255',
@ -38,11 +54,11 @@ class RangesController extends Controller
config('theme.range_image_maxheight'), config('theme.range_image_maxheight'),
]); ]);
$range = new Range(); $range = new Range();
$range->name = $name; $range->name = $name;
$range->slug = $slug; $range->slug = $slug;
$range->description = $description; $range->description = $description;
$range->status = $status; $range->status = $status;
$range->save(); $range->save();
if ($picture !== null) { if ($picture !== null) {
@ -55,19 +71,32 @@ class RangesController extends Controller
return redirect()->route('bo.ranges.index'); return redirect()->route('bo.ranges.index');
} }
public function edit($id) /**
* Show the form for editing the specified resource.
*
* @param integer $id
* @return \Illuminate\Http\Response
*/
public function edit(int $id)
{ {
$range = Range::findOrFail($id); $range = Range::findOrFail($id);
return view('bo.ranges.edit', compact('range')); return view('bo.ranges.edit', compact('range'));
} }
public function update(Request $request, $id) /**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param integer $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, int $id)
{ {
$name = $request->name; $name = $request->name;
$slug = Str::slug($name); $slug = Str::slug($name);
$description = $request->description; $description = $request->description;
$picture = $request->picture; $picture = $request->picture;
$status = $request->status === null ? 0 : 1; $status = $request->status === null ? 0 : 1;
$request->validate([ $request->validate([
'name' => 'required|string|max:255', 'name' => 'required|string|max:255',
@ -80,8 +109,9 @@ class RangesController extends Controller
$range = Range::findOrFail($id); $range = Range::findOrFail($id);
if ($picture !== null) { if ($picture !== null) {
if ($range->picture !== null && file_exists(public_path('images/gammes/') . $range->picture)) if ($range->picture !== null && file_exists(public_path('images/gammes/') . $range->picture)) {
unlink(public_path('images/gammes/') . $range->picture); unlink(public_path('images/gammes/') . $range->picture);
}
$imageName = $range->id . '_' . $slug . '_' . Str::random(5) . '.' . $picture->extension(); $imageName = $range->id . '_' . $slug . '_' . Str::random(5) . '.' . $picture->extension();
$picture->move(public_path('images/gammes'), $imageName); $picture->move(public_path('images/gammes'), $imageName);
} }
@ -91,30 +121,38 @@ class RangesController extends Controller
if ($range->slug != $slug) { if ($range->slug != $slug) {
$exist = OldSlug::where('slug', $range->slug)->first(); $exist = OldSlug::where('slug', $range->slug)->first();
if ($exist === null) { if ($exist === null) {
$oldSlug = new OldSlug(); $oldSlug = new OldSlug();
$oldSlug->range_id = $range->id; $oldSlug->range_id = $range->id;
$oldSlug->slug = $range->slug; $oldSlug->slug = $range->slug;
$oldSlug->save(); $oldSlug->save();
} }
} }
$range->slug = $slug; $range->slug = $slug;
$range->description = $description; $range->description = $description;
if ($picture !== null) if ($picture !== null) {
$range->picture = $imageName; $range->picture = $imageName;
}
$range->status = $status; $range->status = $status;
$range->save(); $range->save();
return redirect()->route('bo.ranges.edit', $range->id)->with('success', 'Modifications enregistrés !'); return redirect()->route('bo.ranges.edit', $range->id)->with('success', 'Modifications enregistrés !');
} }
public function destroy($id) /**
* Remove the specified resource from storage.
*
* @param integer $id
* @return \Illuminate\Http\Response
*/
public function destroy(int $id)
{ {
$range = Range::findOrFail($id); $range = Range::findOrFail($id);
$product = Product::where('range_id', $range->id)->count(); $product = Product::where('range_id', $range->id)->count();
if ($product !== 0) { if ($product !== 0) {
return redirect()->back()->withErrors("Suppression impossible : \"" . $range->name . "\" contient encore des produits."); return redirect()->back()
->withErrors("Suppression impossible : \"" . $range->name . "\" contient encore des produits.");
} }
if ($range->picture !== null) { if ($range->picture !== null) {

View file

@ -10,9 +10,16 @@ use Illuminate\Support\Facades\Config;
class SettingsController extends Controller class SettingsController extends Controller
{ {
public function manage(Request $request) { /**
* Manage settings page
$settings = Setting::all(); *
* @param Request $request
* @return \Illuminate\Http\Response
*
*/
public function manage(Request $request)
{
$settings = Setting::all();
$settingsToPrint = []; $settingsToPrint = [];
foreach ($settings as $setting) { foreach ($settings as $setting) {
$settingsToPrint[$setting->key] = $setting->value; $settingsToPrint[$setting->key] = $setting->value;
@ -21,47 +28,55 @@ class SettingsController extends Controller
if ($_SERVER["REQUEST_METHOD"] === "POST") { if ($_SERVER["REQUEST_METHOD"] === "POST") {
$input = $request->all(); $input = $request->all();
//comparer les settingsToPrint (en base) avec les inputs (pour trouver un nouveau) // Comparer les settingsToPrint (en base) avec les inputs (pour trouver un nouveau).
foreach($input as $key=>$value) { foreach ($input as $key => $value) {
if(!isset($settingsToPrint[$key]) if (
!isset($settingsToPrint[$key])
&& $key != "_method" && $key != "_method"
&& $key != "_token") && $key != "_token"
{ ) {
//new setting // New setting.
$setting = new Setting(); $setting = new Setting();
$setting->key = $key; $setting->key = $key;
$setting->value = $value ?? 0; $setting->value = $value ?? 0;
$setting->save(); $setting->save();
} }
} }
for($i = 0; $i < count($settings); $i++) { $looplimit = count($settings);
if(is_array($request->input($settings[$i]->key))) { for ($i = 0; $i < $looplimit; $i++) {
if (is_array($request->input($settings[$i]->key))) {
$settings[$i]->value = implode(',', $request->input($settings[$i]->key)); $settings[$i]->value = implode(',', $request->input($settings[$i]->key));
} else { } else {
$settings[$i]->value = $request->input($settings[$i]->key) === null ? 0 : $request->input($settings[$i]->key); $settings[$i]->value = $request->input($settings[$i]->key) === null ? 0
: $request->input($settings[$i]->key);
} }
$settings[$i]->save(); $settings[$i]->save();
} }
//store redirector to keep flash message from being wipe pby artisan call below // Store redirector to keep flash message from being wipe pby artisan call below.
$redirector = redirect()->route('bo.settings')->with('success', 'Modifications enregistrés !'); $redirector = redirect()->route('bo.settings')->with('success', 'Modifications enregistrés !');
//all settings saved : cache routes // All settings saved : cache routes.
Artisan::call('route:clear'); Artisan::call('route:clear');
//programmer un php artisan optimize ? (une fois par jour la nuit par exemple) // Programmer un php artisan optimize ? (une fois par jour la nuit par exemple).
return $redirector; return $redirector;
} }//end if
return view('bo.settings', compact('settingsToPrint')); return view('bo.settings', compact('settingsToPrint'));
} }
/** /**
* Manage Theme settings page
* Management des settings dont la clé est préfixée theme_ * Management des settings dont la clé est préfixée theme_
*
* @param Request $request
* @return \Illuminate\Http\Response
*
*/ */
public function manageTheme(Request $request) { public function manageTheme(Request $request)
$settings = Setting::where('key', 'LIKE', 'theme_%')->get(); {
$settings = Setting::where('key', 'LIKE', 'theme_%')->get();
$settingsToPrint = []; $settingsToPrint = [];
foreach ($settings as $setting) { foreach ($settings as $setting) {
$settingsToPrint[$setting->key] = $setting->value; $settingsToPrint[$setting->key] = $setting->value;
@ -69,22 +84,24 @@ class SettingsController extends Controller
$config_settings = Config::get(('theme.bo_theme_settings')); $config_settings = Config::get(('theme.bo_theme_settings'));
//check if, for each of the theme defined settings we have a database setting // Check if, for each of the theme defined settings we have a database setting.
foreach ($config_settings as $onekey => $params) { foreach ($config_settings as $onekey => $params) {
if (!isset($settingsToPrint['theme_' . $onekey])) { if (!isset($settingsToPrint['theme_' . $onekey])) {
$dbsetting = new Setting(); $dbsetting = new Setting();
$dbsetting->key = 'theme_' . $onekey; $dbsetting->key = 'theme_' . $onekey;
$dbsetting->value = $params['default_value']; $dbsetting->value = $params['default_value'];
$dbsetting->save(); $dbsetting->save();
//injection dans settings to print // Injection dans settings to print.
$settingsToPrint[$dbsetting->key] = $dbsetting->value; $settingsToPrint[$dbsetting->key] = $dbsetting->value;
} }
} }
if ($_SERVER["REQUEST_METHOD"] === "POST") { if ($_SERVER["REQUEST_METHOD"] === "POST") {
for($i = 0; $i < count($settings); $i++) { $looplimit = count($settings);
//attention pour les booléens/checkbox on enregistre 'on' for ($i = 0; $i < $looplimit; $i++) {
$settings[$i]->value = $request->input($settings[$i]->key) === null ? 0 : $request->input($settings[$i]->key); // Attention pour les booléens/checkbox on enregistre 'on'.
$settings[$i]->value = $request->input($settings[$i]->key) === null ? 0
: $request->input($settings[$i]->key);
$settings[$i]->save(); $settings[$i]->save();
} }
return redirect()->route('bo.themesettings')->with('success', 'Modifications enregistrés !'); return redirect()->route('bo.themesettings')->with('success', 'Modifications enregistrés !');

View file

@ -33,7 +33,7 @@ class SlidersController extends Controller
/** /**
* Store a newly created resource in storage. * Store a newly created resource in storage.
* *
* @param \Illuminate\Http\Request $request * @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response * @return \Illuminate\Http\Response
*/ */
public function store(Request $request) public function store(Request $request)
@ -59,24 +59,13 @@ class SlidersController extends Controller
return redirect()->route('bo.sliders.edit', $slider->id)->with('success', 'Slider créé !'); return redirect()->route('bo.sliders.edit', $slider->id)->with('success', 'Slider créé !');
} }
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
{
//
}
/** /**
* Show the form for editing the specified resource. * Show the form for editing the specified resource.
* *
* @param int $id * @param integer $id
* @return \Illuminate\Http\Response * @return \Illuminate\Http\Response
*/ */
public function edit($id) public function edit(int $id)
{ {
$slider = Slider::findOrFail($id); $slider = Slider::findOrFail($id);
return view('bo.sliders.edit', compact('slider')); return view('bo.sliders.edit', compact('slider'));
@ -85,11 +74,11 @@ class SlidersController extends Controller
/** /**
* Update the specified resource in storage. * Update the specified resource in storage.
* *
* @param \Illuminate\Http\Request $request * @param \Illuminate\Http\Request $request
* @param int $id * @param integer $id
* @return \Illuminate\Http\Response * @return \Illuminate\Http\Response
*/ */
public function update(Request $request, $id) public function update(Request $request, int $id)
{ {
$slider = Slider::findOrFail($id); $slider = Slider::findOrFail($id);
$label = $request->label; $label = $request->label;
@ -113,10 +102,10 @@ class SlidersController extends Controller
/** /**
* Remove the specified resource from storage. * Remove the specified resource from storage.
* *
* @param int $id * @param integer $id
* @return \Illuminate\Http\Response * @return \Illuminate\Http\Response
*/ */
public function destroy($id) public function destroy(int $id)
{ {
$slider = Slider::findOrFail($id); $slider = Slider::findOrFail($id);
@ -125,8 +114,6 @@ class SlidersController extends Controller
if ($count === 1) { if ($count === 1) {
return redirect()->back()->withErrors("Suppression impossible : Vous devez conserver au moins 1 Slider"); return redirect()->back()->withErrors("Suppression impossible : Vous devez conserver au moins 1 Slider");
} }
// @todo : controller les slides liés
$slider->delete(); $slider->delete();
return redirect()->route('bo.sliders.index'); return redirect()->route('bo.sliders.index');
} }

View file

@ -35,9 +35,7 @@ class SlidesController extends Controller
/** /**
* Store a newly created resource in storage. * Store a newly created resource in storage.
* *
* @todo : validation des dates * @param \Illuminate\Http\Request $request
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response * @return \Illuminate\Http\Response
*/ */
public function store(Request $request) public function store(Request $request)
@ -101,24 +99,13 @@ class SlidesController extends Controller
return redirect()->route('bo.slides.edit', $slide->id)->with('success', 'Slide créé !'); return redirect()->route('bo.slides.edit', $slide->id)->with('success', 'Slide créé !');
} }
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
{
//
}
/** /**
* Show the form for editing the specified resource. * Show the form for editing the specified resource.
* *
* @param int $id * @param integer $id
* @return \Illuminate\Http\Response * @return \Illuminate\Http\Response
*/ */
public function edit($id) public function edit(int $id)
{ {
$slide = Slide::findOrFail($id); $slide = Slide::findOrFail($id);
$sliders = Slider::all(); $sliders = Slider::all();
@ -128,11 +115,11 @@ class SlidesController extends Controller
/** /**
* Update the specified resource in storage. * Update the specified resource in storage.
* *
* @param \Illuminate\Http\Request $request * @param \Illuminate\Http\Request $request
* @param int $id * @param integer $id
* @return \Illuminate\Http\Response * @return \Illuminate\Http\Response
*/ */
public function update(Request $request, $id) public function update(Request $request, int $id)
{ {
$title = $request->title; $title = $request->title;
$picture = $request->picture; $picture = $request->picture;
@ -198,10 +185,10 @@ class SlidesController extends Controller
/** /**
* Remove the specified resource from storage. * Remove the specified resource from storage.
* *
* @param int $id * @param integer $id
* @return \Illuminate\Http\Response * @return \Illuminate\Http\Response
*/ */
public function destroy($id) public function destroy(int $id)
{ {
$s = Slide::findOrFail($id); $s = Slide::findOrFail($id);
@ -210,8 +197,14 @@ class SlidesController extends Controller
return redirect()->route('bo.slides.index'); return redirect()->route('bo.slides.index');
} }
/**
public function changeOrder($id, $action) * Change Slide Order
*
* @param integer $id
* @param string $action
* @return \Illuminate\Http\Response
*/
public function changeOrder(int $id, string $action)
{ {
$current = Slide::findOrFail($id); $current = Slide::findOrFail($id);
@ -230,11 +223,12 @@ class SlidesController extends Controller
$current->save(); $current->save();
return back(); return back();
//return redirect()->route('bo.slides.index');
} }
/** /**
* retreive order position to put a new slide to * retreive order position to put a new slide to
*
* @return integer
*/ */
private function getLastOrder() private function getLastOrder()
{ {

View file

@ -33,20 +33,20 @@ class TagsController extends Controller
/** /**
* Store a newly created resource in storage. * Store a newly created resource in storage.
* *
* @param \Illuminate\Http\Request $request * @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response * @return \Illuminate\Http\Response
*/ */
public function store(Request $request) public function store(Request $request)
{ {
$label = $request->label; $label = $request->label;
$slug = Str::slug($label); $slug = Str::slug($label);
$status = $request->status === null ? 0 : 1; $status = $request->status === null ? 0 : 1;
$request->validate([ $request->validate([
'label' => 'required|string|max:255', 'label' => 'required|string|max:255',
]); ]);
$tag = new Tag(); $tag = new Tag();
$tag->label = $label; $tag->label = $label;
$tag->slug = $slug; $tag->slug = $slug;
$tag->status = $status; $tag->status = $status;
@ -56,24 +56,13 @@ class TagsController extends Controller
return redirect()->route('bo.tags.index'); return redirect()->route('bo.tags.index');
} }
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
{
//
}
/** /**
* Show the form for editing the specified resource. * Show the form for editing the specified resource.
* *
* @param int $id * @param integer $id
* @return \Illuminate\Http\Response * @return \Illuminate\Http\Response
*/ */
public function edit($id) public function edit(int $id)
{ {
$tag = Tag::findOrFail($id); $tag = Tag::findOrFail($id);
return view('bo.tags.edit', compact('tag')); return view('bo.tags.edit', compact('tag'));
@ -82,14 +71,14 @@ class TagsController extends Controller
/** /**
* Update the specified resource in storage. * Update the specified resource in storage.
* *
* @param \Illuminate\Http\Request $request * @param \Illuminate\Http\Request $request
* @param int $id * @param integer $id
* @return \Illuminate\Http\Response * @return \Illuminate\Http\Response
*/ */
public function update(Request $request, $id) public function update(Request $request, int $id)
{ {
$label = $request->label; $label = $request->label;
$slug = Str::slug($label); $slug = Str::slug($label);
$status = $request->status === null ? 0 : 1; $status = $request->status === null ? 0 : 1;
$request->validate([ $request->validate([
@ -98,8 +87,8 @@ class TagsController extends Controller
$tag = Tag::findOrFail($id); $tag = Tag::findOrFail($id);
$tag->label = $label; $tag->label = $label;
$tag->slug = $slug; $tag->slug = $slug;
$tag->status = $status; $tag->status = $status;
$tag->save(); $tag->save();
@ -109,24 +98,31 @@ class TagsController extends Controller
/** /**
* Remove the specified resource from storage. * Remove the specified resource from storage.
* *
* @param int $id * @param integer $id
* @return \Illuminate\Http\Response * @return \Illuminate\Http\Response
*/ */
public function destroy($id) public function destroy(int $id)
{ {
$tag = Tag::findOrFail($id); $tag = Tag::findOrFail($id);
$products = $tag->products()->count(); $products = $tag->products()->count();
if ($products !== 0) { if ($products !== 0) {
return redirect()->back()->withErrors("Suppression impossible : \"" . $tag->label . "\" est associé à des produits."); return redirect()->back()
->withErrors("Suppression impossible : \"" . $tag->label . "\" est associé à des produits.");
} }
$tag->delete(); $tag->delete();
return redirect()->route('bo.tags.index'); return redirect()->route('bo.tags.index');
} }
/**
public function changeOrder($id, $action) * Change Tag Order
*
* @param integer $id
* @param string $action
* @return \Illuminate\Http\Response
*/
public function changeOrder(int $id, string $action)
{ {
$current = Tag::findOrFail($id); $current = Tag::findOrFail($id);
@ -145,11 +141,17 @@ class TagsController extends Controller
$current->save(); $current->save();
return back(); return back();
//return redirect()->route('bo.slides.index');
} }
public function toggleStatus($id) { /**
$tag = Tag::findOrFail($id); * Toggle tag status
*
* @param integer $id
* @return \Illuminate\Http\Response
*/
public function toggleStatus(int $id)
{
$tag = Tag::findOrFail($id);
$tag->status = !($tag->status); $tag->status = !($tag->status);
$tag->save(); $tag->save();
return back(); return back();
@ -158,6 +160,8 @@ class TagsController extends Controller
/** /**
* retreive order position to put a new slide to * retreive order position to put a new slide to
*
* @return integer
*/ */
public static function getLastOrder() public static function getLastOrder()
{ {

View file

@ -12,30 +12,57 @@ use Illuminate\Http\Request;
class ContactController extends Controller class ContactController extends Controller
{ {
/**
* legal notice page
*
* @param Request $request
* @return \Illuminate\Contracts\View\View
*
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
*/
public function contact(Request $request) public function contact(Request $request)
{ {
// @phpcs:enable
$status = $request->session()->get('status'); $status = $request->session()->get('status');
//1er magasin en base pour le moment $magasin = Magasin::first();
$magasin = Magasin::first(); $magasins = Magasin::all();
$content = Content::where('key', 'contact')->first(); $content = Content::where('key', 'contact')->first();
return view('contact', compact('status', 'magasin', 'content')); return view('contact', compact('status', 'magasins', 'magasin', 'content'));
} }
/**
* submit contact form
*
* @param ContactFormRequest $request
* @return \Illuminate\Http\Response
* @throws \RuntimeException If email missing.
*/
public function contactSubmit(ContactFormRequest $request) public function contactSubmit(ContactFormRequest $request)
{ {
$data = $request->all(); /** @var \App\Model\Magasin|null */
$shop = Magasin::where('name', $request->shop)->first();
$toMailSetting = Setting::where('key', 'send_contact_mail_to')->first(); if ($shop and $shop->email_contact) {
if(empty($toMailSetting->value)) { /** @var string */
$toMail = config('mail.from.address'); $toMail = $shop->email_contact;
} else { } else {
$toMail = $toMailSetting->value; /** @var string|null */
$toMail = \optional(Setting::where('key', 'send_contact_mail_to')->first())->value;
if (!$toMail) {
/** @var string|null */
$toMail = config('mail.from.address');
}
} }
//envoi du mail d'alerte
if (!$toMail) {
throw new \RuntimeException('Impossible de trouver un mail');
}
// Envoi du mail d'alerte.
Mail::to($toMail)->send(new SendContactMail($request)); Mail::to($toMail)->send(new SendContactMail($request));
Mail::mailer('smtp2')->to($toMail)->send(new SendContactMail($request));
return back()->with('status', true); return back()->with('status', true);
} }

View file

@ -9,5 +9,7 @@ use Illuminate\Routing\Controller as BaseController;
class Controller extends BaseController class Controller extends BaseController
{ {
use AuthorizesRequests, DispatchesJobs, ValidatesRequests; use AuthorizesRequests;
use DispatchesJobs;
use ValidatesRequests;
} }

View file

@ -5,6 +5,7 @@ namespace App\Http\Controllers;
use App\Http\Requests\CustomerRegisterRequest; use App\Http\Requests\CustomerRegisterRequest;
use App\Http\Requests\LoginRequest; use App\Http\Requests\LoginRequest;
use App\Http\Requests\UpdateInfosRequest; use App\Http\Requests\UpdateInfosRequest;
use App\Mail\OrderCanceledConfirmMail;
use App\Mail\PasswordResetMail; use App\Mail\PasswordResetMail;
use App\Mail\RegisterConfirmMail; use App\Mail\RegisterConfirmMail;
use App\Models\Customers; use App\Models\Customers;
@ -12,6 +13,7 @@ use App\Models\Magasin;
use App\Models\Order; use App\Models\Order;
use App\Models\PasswordReset; use App\Models\PasswordReset;
use App\Models\Salarie; use App\Models\Salarie;
use App\Models\Setting;
use Illuminate\Database\Eloquent\ModelNotFoundException; use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
@ -31,6 +33,8 @@ class CustomerController extends Controller
{ {
/** /**
* Affiche la page d'inscription * Affiche la page d'inscription
*
* @return \Illuminate\Http\Response
*/ */
public function registerForm() public function registerForm()
{ {
@ -77,13 +81,14 @@ class CustomerController extends Controller
$crmCustomer->country = Country::france(); $crmCustomer->country = Country::france();
$crmCustomer->save(); $crmCustomer->save();
// * Enrregistrement du Hashcode
/** @var \App\Models\Customers $customer */
$customer = new Customers($request->all());
$customer->hashcode = $crmCustomer->hashcode;
$customer->saveOrFail();
// * liaison éventuelle avec la table salaries // * liaison éventuelle avec la table salaries
if ($request->matricule && $request->code) { if ($request->matricule && $request->code) {
/** @var \App\Models\Customers $customer */
$customer = new Customers($request->all());
$customer->hashcode = $crmCustomer->hashcode;
$customer->saveOrFail();
/** @var \App\Models\Salarie $salarie */ /** @var \App\Models\Salarie $salarie */
$salarie = Salarie::where('matricule', '=', $request->matricule) $salarie = Salarie::where('matricule', '=', $request->matricule)
->where('code', '=', $request->code) ->where('code', '=', $request->code)
@ -93,8 +98,6 @@ class CustomerController extends Controller
} }
Mail::to($request->email)->send(new RegisterConfirmMail($customer, $request->firstname)); Mail::to($request->email)->send(new RegisterConfirmMail($customer, $request->firstname));
Mail::mailer('smtp2')->to($request->email)
->send(new RegisterConfirmMail($customer, $request->firstname));
return view('auth.register-success', ['mail' => $request->email]); return view('auth.register-success', ['mail' => $request->email]);
}); });
@ -121,6 +124,9 @@ class CustomerController extends Controller
/** /**
* Retourne la page de connexion * Retourne la page de connexion
*
* @param Request $request
* @return \Illuminate\Http\Response
*/ */
public function authenticateForm(Request $request) public function authenticateForm(Request $request)
{ {
@ -190,29 +196,31 @@ class CustomerController extends Controller
$crmCustomer = $customer->apiData; $crmCustomer = $customer->apiData;
if ($crmCustomer->activate()) { if ($crmCustomer->activate()) {
return view('auth.activate') return view('auth.activate')
->with('message', 'Votre compte a bien été activé, vous pouvez désormais vous connecter.'); ->with('message', 'Votre compte a bien été activé, vous pouvez désormais vous connecter.');
} }
} catch (ApiErrorException $e) { } catch (ApiErrorException $e) {
if ($e->getApiError()->equals(ApiError::customerAlreadyActive())) { if ($e->getApiError()->equals(ApiError::customerAlreadyActive())) {
// phpcs:disable Generic.Files.LineLength.TooLong // phpcs:disable Generic.Files.LineLength.TooLong
return view('auth.activate') return view('auth.activate')
->with('message', 'Votre compte est déjà activé, vous pouvez dès à présent vous connecter avec celui-ci.'); ->with('message', 'Votre compte est déjà activé, vous pouvez dès à présent vous connecter avec celui-ci.');
} }
report($e); report($e);
// Une erreur critique est survenue avec la CRM. // Une erreur critique est survenue avec la CRM.
return view('auth.activate') return view('auth.activate')
->with('message', 'Une erreur est survenue, merci de réessayer ultérieurement.'); ->with('message', 'Une erreur est survenue, merci de réessayer ultérieurement.');
} catch (CrmException $e) { } catch (CrmException $e) {
report($e); report($e);
// Une erreur critique est survenue avec la CRM. // Une erreur critique est survenue avec la CRM.
return view('auth.activate') return view('auth.activate')
->with('message', 'Une erreur est survenue, merci de réessayer ultérieurement.'); ->with('message', 'Une erreur est survenue, merci de réessayer ultérieurement.');
} //end try } //end try
return view('auth.activate')->with('message', 'Ce lien d\'activation n\'est pas valide.'); return view('auth.activate')->with('message', 'Ce lien d\'activation n\'est pas valide.');
} }
/** /**
* deconnexion customer * deconnexion customer
*
* @return \Illuminate\Http\RedirectResponse
*/ */
public function logout() public function logout()
{ {
@ -224,14 +232,23 @@ class CustomerController extends Controller
/** /**
* page d'accès à la procédure mdp oublié * page d'accès à la procédure mdp oublié
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Contracts\View\View
*
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
*/ */
public function forgotPasswordForm(Request $request) public function forgotPasswordForm(Request $request)
{ {
// @phpcs:enable
return view('auth.passwords.forgot'); return view('auth.passwords.forgot');
} }
/** /**
* initialisation de la procédure de mdp oublié * initialisation de la procédure de mdp oublié
*
* @param Request $request
* @return \Illuminate\Http\RedirectResponse
*/ */
public function passwordReset(Request $request) public function passwordReset(Request $request)
{ {
@ -244,7 +261,7 @@ class CustomerController extends Controller
$customerExist = Customers::where('email', $email)->count() === 0 ? false : true; $customerExist = Customers::where('email', $email)->count() === 0 ? false : true;
if ($customerExist) { if ($customerExist) {
// Suppression des anciens tokens // Suppression des anciens tokens.
PasswordReset::where('email', $email)->delete(); PasswordReset::where('email', $email)->delete();
$token = Str::random(80); $token = Str::random(80);
@ -256,9 +273,10 @@ class CustomerController extends Controller
$passwordReset->save(); $passwordReset->save();
Mail::to($email)->send(new PasswordResetMail($token)); Mail::to($email)->send(new PasswordResetMail($token));
Mail::mailer('smtp2')->to($email)->send(new PasswordResetMail($token)); return back()->with(
// @phpcs:ignore Generic.Files.LineLength 'success',
return back()->with('success', __("La procédure pour changer votre mot de passe a été envoyé sur votre email.")); __("La procédure pour changer votre mot de passe a été envoyé sur votre email.")
);
} else { } else {
return back()->withErrors(__("Cette adresse email n'est pas enregistrée dans nos services.")); return back()->withErrors(__("Cette adresse email n'est pas enregistrée dans nos services."));
} }
@ -266,10 +284,10 @@ class CustomerController extends Controller
/** /**
* Print the view used to change the password of a user when he required it * Print the view used to change the password of a user when he required it
* @param $token Token used to identificate the user to change the password of * @param string $token Token used to identificate the user to change the password.
* @return View The view to print * @return \Illuminate\Contracts\View\View The view to print
*/ */
public function viewChangePassword($token) public function viewChangePassword(string $token)
{ {
$pwdReset = PasswordReset::where('token', $token)->first(); $pwdReset = PasswordReset::where('token', $token)->first();
if (!$pwdReset) { if (!$pwdReset) {
@ -335,11 +353,16 @@ class CustomerController extends Controller
/** /**
* profil client (mon compte) * profil client (mon compte)
*
* @param Request $request
* @return \Illuminate\Contracts\View\View
*
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
*/ */
public function dashboard(Request $request) public function dashboard(Request $request)
{ {
// @phpcs:enable
//show Profile // Show Profile.
/** @var \App\Models\Customers|null $customer */ /** @var \App\Models\Customers|null $customer */
$customer = Auth::guard('customer')->user(); $customer = Auth::guard('customer')->user();
if (!$customer) { if (!$customer) {
@ -378,6 +401,9 @@ class CustomerController extends Controller
/** /**
* changement de mot de passe depuis le profil * changement de mot de passe depuis le profil
*
* @param Request $request
* @return \Illuminate\Http\RedirectResponse
*/ */
public function changePasswordWhenAuthenticated(Request $request) public function changePasswordWhenAuthenticated(Request $request)
{ {
@ -397,18 +423,30 @@ class CustomerController extends Controller
/** /**
* affichage des commandes du customer connecté * affichage des commandes du customer connecté
*
* @param Request $request
* @return \Illuminate\Contracts\View\View
*
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
*/ */
public function myOrders(Request $request) public function myOrders(Request $request)
{ {
// @phpcs:enable
$orders = Order::where('customer_id', Auth::guard('customer')->user()->id)->orderBy('date', 'DESC')->get(); $orders = Order::where('customer_id', Auth::guard('customer')->user()->id)->orderBy('date', 'DESC')->get();
return view('customer.my-orders', compact('orders')); return view('customer.my-orders', compact('orders'));
} }
public function orderDetail($reference) /**
* Show detail commande
*
* @param string $reference
* @return \Illuminate\Contracts\View\View
*/
public function orderDetail(string $reference)
{ {
$order = Order::where('reference', '=', $reference) $order = Order::where('reference', '=', $reference)
->where('customer_id', Auth::guard('customer')->user()->id) ->where('customer_id', Auth::guard('customer')->user()->id)
->firstOrFail(); ->firstOrFail();
if ($order->status_id == 1) { if ($order->status_id == 1) {
$magasin = null; $magasin = null;
@ -419,25 +457,50 @@ class CustomerController extends Controller
return view('customer.order-detail', compact('order', 'magasin')); return view('customer.order-detail', compact('order', 'magasin'));
} }
public function delete($id) /**
* mise au statut annulé d'une commande
*
* @param string $reference
* @return \Illuminate\Http\RedirectResponse
* @throws \RuntimeException If email missing.
*/
public function cancelOrder(string $reference)
{ {
// TODO : Implémenter la suppression lorsque la CRM sera prête pour le faire aussi /** @var \App\Models\Order|null */
die('Not implemented yet'); $order = Order::where('reference', $reference)->first();
// Suppression d'un compte client if (!$order) {
$customer = Customers::findOrFail($id); throw new \RuntimeException('Impossible de trouver un enregistrement Order');
$customer->recipes()->delete();
$customer->products()->delete();
$customer->answers()->delete();
$customer->forums()->delete();
// TODO : Suppression via la CRM
if (Auth::guard('customer')->user()->id === $customer->id) {
Auth::guard('customer')->logout();
} }
$customer->delete(); $order->status_id = 7;
$order->save();
return redirect()->route('home'); // Envoi du mail d'annulation aux admins site.
/** @var string|null */
$toMail = \optional(Setting::where('key', 'send_order_confirm_mail_to')->first())->value;
if (!$toMail) {
/** @var string|null */
$toMail = config('mail.from.address');
}
if (!$toMail) {
throw new \RuntimeException('Impossible de trouver un mail');
}
Mail::to($toMail)->queue(new OrderCanceledConfirmMail($order));
return back()->with('success', "La commande " . $order->reference . " à été annulée.");
}
/**
* delete customers
*
* @param integer $id
* @return void
*/
public function delete(int $id)
{
dump('deleting' . $id);
die('Not implemented yet');
} }
/** /**
@ -495,7 +558,6 @@ class CustomerController extends Controller
} }
} }
Mail::to($request->email)->send(new RegisterConfirmMail($customer, null)); Mail::to($request->email)->send(new RegisterConfirmMail($customer, null));
Mail::mailer('smtp2')->to($request->email)->send(new RegisterConfirmMail($customer, null));
return back() return back()
->withErrors( ->withErrors(
trans('Votre compte n\'est pas activé, vérifiez dans vos emails pour y trouver trans('Votre compte n\'est pas activé, vérifiez dans vos emails pour y trouver
@ -541,7 +603,6 @@ class CustomerController extends Controller
return \redirect()->back(); return \redirect()->back();
} }
// TODO: Activer le changement d'email quand ce sera possible dans la CRM.
/** @var \LDC\LDCCRM\Models\Customer */ /** @var \LDC\LDCCRM\Models\Customer */
$crmCustomer = $customer->apiData; $crmCustomer = $customer->apiData;

View file

@ -7,7 +7,6 @@ use App\Models\Product;
use App\Models\Slider; use App\Models\Slider;
use App\Models\Range; use App\Models\Range;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator; use Illuminate\Support\Facades\Validator;
use LDC\LDCCRM\Enums\ApiError; use LDC\LDCCRM\Enums\ApiError;
use LDC\LDCCRM\Exceptions\ApiErrorException; use LDC\LDCCRM\Exceptions\ApiErrorException;
@ -16,10 +15,19 @@ use LDC\LDCCRM\Models\SingleOptin;
class HomeController extends Controller class HomeController extends Controller
{ {
/**
* Display homepage
*
* @param Request $request
* @return \Illuminate\Contracts\View\View
*
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
*/
public function index(Request $request) public function index(Request $request)
{ {
// @phpcs:enable
$content = Content::where('key', 'accueil')->first(); $content = Content::where('key', 'accueil')->first();
//star products // Star products.
$products = Product::where('status', 1)->where('star', 1)->get(); $products = Product::where('status', 1)->where('star', 1)->get();
$slider = Slider::where('slug', 'home')->first(); $slider = Slider::where('slug', 'home')->first();
@ -37,8 +45,10 @@ class HomeController extends Controller
/** /**
* Call the CRM to add a single optin * Call the CRM to add a single optin
* @param String $email Email to add as a single optin *
* @return String Message to print to the customer * @param Request $request
* @return \Illuminate\Contracts\View\View
*
*/ */
public function addOptIn(Request $request) public function addOptIn(Request $request)
{ {

View file

@ -8,38 +8,64 @@ use Illuminate\Http\Request;
class IndexController extends Controller class IndexController extends Controller
{ {
/** /**
* deprecated * legal notice page
*
* @param Request $request
* @return \Illuminate\Contracts\View\View
*
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
*/ */
public function contact(Request $request)
{
$content = Content::where('key', 'contact')->first();
return view('contact', compact('content'));
}
public function legalNotice(Request $request) public function legalNotice(Request $request)
{ {
// @phpcs:enable
$content = Content::where('key', 'legals')->first(); $content = Content::where('key', 'legals')->first();
return view('legal-notice', compact('content')); return view('legal-notice', compact('content'));
} }
/**
* terms and conditions page
*
* @param Request $request
* @return \Illuminate\Contracts\View\View
*
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
*/
public function terms(Request $request) public function terms(Request $request)
{ {
// @phpcs:enable
$content = Content::where('key', 'cgv')->first(); $content = Content::where('key', 'cgv')->first();
return view('terms', compact('content')); return view('terms', compact('content'));
} }
/**
* privacy page
*
* @param Request $request
* @return \Illuminate\Contracts\View\View
*
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
*/
public function privacy(Request $request) public function privacy(Request $request)
{ {
// @phpcs:enable
$content = Content::where('key', 'confidentialite')->first(); $content = Content::where('key', 'confidentialite')->first();
return view('privacy', compact('content')); return view('privacy', compact('content'));
} }
/**
* faq page
*
* @param Request $request
* @return \Illuminate\Contracts\View\View
*
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
*/
public function faq(Request $request) public function faq(Request $request)
{ {
// @phpcs:enable
$content = Content::where('key', 'faq')->first(); $content = Content::where('key', 'faq')->first();
$faq = Faq::all(); $faq = Faq::all();
return view('faq', compact('faq','content')); return view('faq', compact('faq', 'content'));
} }
} }

View file

@ -6,49 +6,68 @@ use App\Models\Product;
use App\Models\Range; use App\Models\Range;
use App\Models\Tag; use App\Models\Tag;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Str;
class ProductsController extends Controller class ProductsController extends Controller
{ {
/** /**
* page des gammes * Ranges page
*
* @param Request $request
* @return \Illuminate\Contracts\View\View
*
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
*/ */
public function ranges(Request $request) public function ranges(Request $request)
{ {
//now in AppServiceProvider // @phpcs:enable
//$ranges = Range::all(); // $ranges shared in AppServiceProvider.
//return view('ranges', compact('ranges'));
return view('ranges'); return view('ranges');
} }
/** /**
* page une gamme * One Range page
*
* @param Request $request
* @param string $range_slug
* @return \Illuminate\Contracts\View\View
*
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
*/ */
public function range(Request $request, $range_slug) public function range(Request $request, string $range_slug)
{ {
// @phpcs:enable
$range = Range::where('slug', $range_slug)->first(); $range = Range::where('slug', $range_slug)->first();
if (!$range || !$range->status) { if (!$range || !$range->status) {
abort(404); abort(404);
} }
$products = Product::where('range_id', $range->id)->where('status', 1)->paginate(9); $products = Product::where('range_id', $range->id)->where('status', 1)->paginate(9);
//find promo within range // Find promo within range.
$offres = Product::where('range_id', $range->id)->where('status', 1)->has('promotions')->with('promotions')->get(); $offres = Product::where('range_id', $range->id)
->where('status', 1)
->has('promotions')
->with('promotions')->get();
return view('range', compact('range', 'products', 'offres')); return view('range', compact('range', 'products', 'offres'));
} }
/** /**
* page produit * One product page
*
* @param Request $request
* @param string $product_slug
* @return \Illuminate\Contracts\View\View
*
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
*/ */
public function product(Request $request, $product_slug) public function product(Request $request, string $product_slug)
{ {
// @phpcs:enable
$product = Product::where('slug', $product_slug)->first(); $product = Product::where('slug', $product_slug)->first();
if (!$product || !$product->status) { if (!$product || !$product->status) {
abort(404); abort(404);
} }
$product->additionnalProductInfo = $product->additionnalProductInfo($product->product_type); $product->additionnalProductInfo = $product->additionnalProductInfo($product->product_type);
if ($product->additionnalProductInfo === null && !empty($product_type)) { if ($product->additionnalProductInfo === null && !empty($product_type)) {
//n'existe pas on renseigne un vide // N'existe pas on renseigne un vide.
$product_type = $product->product_type; $product_type = $product->product_type;
$modelClass = 'App\Models\\' . ucfirst($product_type); $modelClass = 'App\Models\\' . ucfirst($product_type);
$product->$product_type = new $modelClass(); $product->$product_type = new $modelClass();
@ -62,6 +81,10 @@ class ProductsController extends Controller
/** /**
* tous les produits * tous les produits
* recherche par nom de produit * recherche par nom de produit
*
* @param Request $request
* @return \Illuminate\Contracts\View\View
*
*/ */
public function allProducts(Request $request) public function allProducts(Request $request)
{ {
@ -82,10 +105,18 @@ class ProductsController extends Controller
} }
/** /**
* produits filtrés par tag (1 tag) * tous les produits
* filtrage par tag
*
* @param Request $request
* @param string $tag_slug
* @return \Illuminate\Contracts\View\View
*
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
*/ */
public function tagFiltered(Request $request, $tag_slug) public function tagFiltered(Request $request, string $tag_slug)
{ {
// @phpcs:enable
$products = Product::where('status', 1) $products = Product::where('status', 1)
->whereHas('tags', function ($q) use ($tag_slug) { ->whereHas('tags', function ($q) use ($tag_slug) {
$q->where('slug', '=', $tag_slug); $q->where('slug', '=', $tag_slug);

View file

@ -7,8 +7,17 @@ use Illuminate\Http\Request;
class QuickOrderController extends Controller class QuickOrderController extends Controller
{ {
/**
* Quickorder page
*
* @param Request $request
* @return \Illuminate\Contracts\View\View
*
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
*/
public function index(Request $request) public function index(Request $request)
{ {
// @phpcs:enable
$quickorder_ranges = Range::with('products')->get(); $quickorder_ranges = Range::with('products')->get();
foreach ($quickorder_ranges as $range) { foreach ($quickorder_ranges as $range) {
foreach ($range->products as $product) { foreach ($range->products as $product) {

View file

@ -2,7 +2,7 @@
namespace App\Http; namespace App\Http;
use App\Http\Middleware\isAdmin; use App\Http\Middleware\IsAdmin;
use Illuminate\Foundation\Http\Kernel as HttpKernel; use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel class Kernel extends HttpKernel
@ -15,7 +15,6 @@ class Kernel extends HttpKernel
* @var array * @var array
*/ */
protected $middleware = [ protected $middleware = [
// \App\Http\Middleware\TrustHosts::class,
\App\Http\Middleware\TrustProxies::class, \App\Http\Middleware\TrustProxies::class,
\Fruitcake\Cors\HandleCors::class, \Fruitcake\Cors\HandleCors::class,
\App\Http\Middleware\PreventRequestsDuringMaintenance::class, \App\Http\Middleware\PreventRequestsDuringMaintenance::class,
@ -34,7 +33,6 @@ class Kernel extends HttpKernel
\App\Http\Middleware\EncryptCookies::class, \App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class, \Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class, \App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class, \Illuminate\Routing\Middleware\SubstituteBindings::class,
@ -64,6 +62,6 @@ class Kernel extends HttpKernel
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class, 'signed' => \Illuminate\Routing\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,
'is-admin' => isAdmin::class, 'is-admin' => IsAdmin::class,
]; ];
} }

View file

@ -9,7 +9,7 @@ class Authenticate extends Middleware
/** /**
* Get the path the user should be redirected to when they are not authenticated. * Get the path the user should be redirected to when they are not authenticated.
* *
* @param \Illuminate\Http\Request $request * @param mixed $request
* @return string|null * @return string|null
*/ */
protected function redirectTo($request) protected function redirectTo($request)

View file

@ -12,6 +12,5 @@ class EncryptCookies extends Middleware
* @var array * @var array
*/ */
protected $except = [ protected $except = [
// ];
];
} }

View file

@ -3,22 +3,24 @@
namespace App\Http\Middleware; namespace App\Http\Middleware;
use Closure; use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
class isAdmin class IsAdmin
{ {
/** /**
* Handle an incoming request. * Handle an incoming request.
* *
* @param \Illuminate\Http\Request $request * @param \Illuminate\Http\Request $request
* @param \Closure $next * @param \Closure $next
* @return mixed * @return mixed
*/ */
public function handle($request, Closure $next) public function handle(Request $request, Closure $next)
{ {
$role = Auth::user()->role; $role = Auth::user()->role;
if ($role === 1 || $role === 2) if ($role === 1 || $role === 2) {
return $next($request); return $next($request);
}
abort(404, "Cette page n'existe pas."); abort(404, "Cette page n'existe pas.");
} }
} }

View file

@ -12,6 +12,5 @@ class PreventRequestsDuringMaintenance extends Middleware
* @var array * @var array
*/ */
protected $except = [ protected $except = [
// ];
];
} }

View file

@ -12,9 +12,9 @@ class RedirectIfAuthenticated
/** /**
* Handle an incoming request. * Handle an incoming request.
* *
* @param \Illuminate\Http\Request $request * @param \Illuminate\Http\Request $request
* @param \Closure $next * @param \Closure $next
* @param string|null ...$guards * @param string|null ...$guards
* @return mixed * @return mixed
*/ */
public function handle(Request $request, Closure $next, ...$guards) public function handle(Request $request, Closure $next, ...$guards)

View file

@ -6,20 +6,21 @@ use App\Models\OldSlug;
use App\Models\Product; use App\Models\Product;
use App\Models\Range; use App\Models\Range;
use Closure; use Closure;
use Illuminate\Http\Request;
class RedirectOldSlugs class RedirectOldSlugs
{ {
/** /**
* Handle an incoming request. * Handle an incoming request.
* *
* @param \Illuminate\Http\Request $request * @param \Illuminate\Http\Request $request
* @param \Closure $next * @param \Closure $next
* @return mixed * @return mixed
*/ */
public function handle($request, Closure $next) public function handle(Request $request, Closure $next)
{ {
$productSlug = $request->route('productSlug'); $productSlug = $request->route('productSlug');
$rangeSlug = $request->route('rangeSlug'); $rangeSlug = $request->route('rangeSlug');
if ($productSlug !== null) { if ($productSlug !== null) {
$product = Product::where('slug', $productSlug)->first(); $product = Product::where('slug', $productSlug)->first();

View file

@ -17,7 +17,7 @@ class TrustProxies extends Middleware
/** /**
* The headers that should be used to detect proxies. * The headers that should be used to detect proxies.
* *
* @var int * @var integer
*/ */
protected $headers = Request::HEADER_X_FORWARDED_ALL; protected $headers = Request::HEADER_X_FORWARDED_ALL;
} }

View file

@ -12,6 +12,5 @@ class VerifyCsrfToken extends Middleware
* @var array * @var array
*/ */
protected $except = [ protected $except = [
// ];
];
} }

View file

@ -2,8 +2,6 @@
namespace App\Http\Requests; namespace App\Http\Requests;
use App\Enums\ContactFormCivility;
use App\Enums\ContactFormType;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
class ContactFormRequest extends FormRequest class ContactFormRequest extends FormRequest
@ -11,7 +9,7 @@ class ContactFormRequest extends FormRequest
/** /**
* Determine if the user is authorized to make this request. * Determine if the user is authorized to make this request.
* *
* @return bool * @return boolean
*/ */
public function authorize() public function authorize()
{ {
@ -28,8 +26,8 @@ class ContactFormRequest extends FormRequest
return [ return [
'last_name' => 'required|min:2', 'last_name' => 'required|min:2',
'first_name' => 'required|min:2', 'first_name' => 'required|min:2',
// TODO: The dns and spoof validators require the PHP intl extension. (présent sur prod ?)
'email' => 'required|email:rfc,dns,spoof', 'email' => 'required|email:rfc,dns,spoof',
'shop' => 'present|nullable|string|exists:magasins,name',
'subject' => 'required|min:2', 'subject' => 'required|min:2',
'order_ref' => 'sometimes', 'order_ref' => 'sometimes',
'message' => 'required|min:20|max:1900', 'message' => 'required|min:20|max:1900',
@ -49,6 +47,7 @@ class ContactFormRequest extends FormRequest
'ok_cgv.accepted' => __('You must accept the terms and conditions and the privacy policy'), 'ok_cgv.accepted' => __('You must accept the terms and conditions and the privacy policy'),
'file.max' => __('La taille du fichier ne peut pas dépasser :max kilo-octets.'), 'file.max' => __('La taille du fichier ne peut pas dépasser :max kilo-octets.'),
'file.mimes' => __('Le fichier doit être de type : :values.'), 'file.mimes' => __('Le fichier doit être de type : :values.'),
'shop.exists' => __('Le magasin :exists est introuvable.')
]; ];
} }
} }

View file

@ -10,7 +10,7 @@ class ProductRequest extends FormRequest
/** /**
* Determine if the user is authorized to make this request. * Determine if the user is authorized to make this request.
* *
* @return bool * @return boolean
*/ */
public function authorize() public function authorize()
{ {

View file

@ -9,7 +9,7 @@ class SortOrders extends FormRequest
/** /**
* Determine if the user is authorized to make this request. * Determine if the user is authorized to make this request.
* *
* @return bool * @return boolean
*/ */
public function authorize() public function authorize()
{ {

View file

@ -4,16 +4,20 @@ namespace App\Jobs;
abstract class CsvJobs extends XArcadiaFlux abstract class CsvJobs extends XArcadiaFlux
{ {
/** /**
* parse csv file * parse csv file
*
* @param string $csvFile
*
* @return array
*/ */
protected function parseCsv($csvFile) { protected function parseCsv(string $csvFile)
{
$file_handle = fopen($csvFile, 'r'); $file_handle = fopen($csvFile, 'r');
while (!feof($file_handle)) { while (!feof($file_handle)) {
$line_of_text[] = fgetcsv($file_handle, 0, ";"); $line_of_text[] = fgetcsv($file_handle, 0, ";");
if(!end($line_of_text)) { if (!end($line_of_text)) {
//supprime les lignes vides du csv // Supprime les lignes vides du csv.
array_pop($line_of_text); array_pop($line_of_text);
} }
} }
@ -36,10 +40,19 @@ abstract class CsvJobs extends XArcadiaFlux
/** /**
* converts an array to a csv stream * converts an array to a csv stream
* *
* @param array $data
* @param string $delimiter
* @param string $enclosure
* @param string $escape_char
*
* @return string * @return string
*/ */
protected function array2csv($data, $delimiter = ',', $enclosure = '"', $escape_char = "\\") protected function array2csv(
{ array $data,
string $delimiter = ',',
string $enclosure = '"',
string $escape_char = "\\"
) {
$f = fopen('php://memory', 'r+'); $f = fopen('php://memory', 'r+');
foreach ($data as $item) { foreach ($data as $item) {
fputcsv($f, $item, $delimiter, $enclosure, $escape_char); fputcsv($f, $item, $delimiter, $enclosure, $escape_char);

View file

@ -4,20 +4,27 @@ namespace App\Jobs;
use Illuminate\Support\Carbon; use Illuminate\Support\Carbon;
use App\Models\Order; use App\Models\Order;
use App\Models\OrderLine;
use App\Models\Customers;
use App\Models\Timeslot;
class CsvOrderWrite extends CsvJobs class CsvOrderWrite extends CsvJobs
{ {
/**
* The Laravel disk name
*
* @var string
*/
protected $disk = 'orders'; protected $disk = 'orders';
/** @var Order */ /**
* The Order to be exported
*
* @var Order
* */
private $order; private $order;
/** /**
* en-têtes * CSV File headers
*
* @var array
*/ */
private $header = [ private $header = [
"CodeArt", "CodeArt",
@ -34,6 +41,8 @@ class CsvOrderWrite extends CsvJobs
/** /**
* correspondance unité d'appro/mode de commande * correspondance unité d'appro/mode de commande
*
* @var array
*/ */
private $mode_commande = [ private $mode_commande = [
"COLIS" => "UEA", "COLIS" => "UEA",
@ -44,6 +53,8 @@ class CsvOrderWrite extends CsvJobs
/** /**
* Create a new job instance. * Create a new job instance.
* *
* @param Order $order
*
* @return void * @return void
*/ */
public function __construct(Order $order) public function __construct(Order $order)
@ -70,44 +81,48 @@ class CsvOrderWrite extends CsvJobs
/** @var Timeslot */ /** @var Timeslot */
$timeslot = $this->order->timeslot; $timeslot = $this->order->timeslot;
//insertion de la ligne d'en-têtes // Insertion de la ligne d'en-têtes.
$csvlines[] = $this->header; $csvlines[] = $this->header;
foreach ($orderlines as $orderline) { foreach ($orderlines as $orderline) {
$product = $orderline->product; $product = $orderline->product;
// COLIS, KGM, PCE (faut il introduire un nouveau champs type unité de commande).
$unité_commande = $product->order_unit ?? 'PCE'; //COLIS, KGM, PCE (faut il introduire un nouveau champs type unité de commande) $unité_commande = $product->order_unit ?? 'PCE';
$code_client = preg_replace('/[^\d]/', '', $customer->salarie->matricule); //matricule rh transmis sans les lettres de l'identifiant windows // Matricule rh transmis sans les lettres de l'identifiant windows.
$code_client = preg_replace('/[^\d]/', '', $customer->salarie->matricule);
//convert to date object // Convert to date object.
$datLivraison = Carbon::createFromFormat('d/m/Y H:i', $timeslot->day . " " . $timeslot->time); $datLivraison = Carbon::createFromFormat('d/m/Y H:i', $timeslot->day . " " . $timeslot->time);
//on enleve un jour pour avoir le produit la veille
$datLivraison = $datLivraison->subDay();
$oneline = [ $oneline = [
$product->foodProduct->no_art, //21/01/2022 : suppression du pcb ici $product->foodProduct->no_art,
// 21/01/2022 : suppression du pcb ici
$code_client, $code_client,
$product->reference, $product->reference,
"commande ferme", "commande ferme",
$unité_commande, $unité_commande,
$this->mode_commande[$unité_commande], //UEA,KGM,UB (respectivement selon le champ précédent) // UEA,KGM,UB (respectivement selon le champ précédent).
"", //on vide la colonne pcb comme demandé $this->mode_commande[$unité_commande],
$datLivraison->format('d/m/Y'), //dd/mm/yyyy // On vide la colonne pcb comme demandé.
"",
$datLivraison->format('d/m/Y'),
$orderline->quantity, $orderline->quantity,
$this->order->reference, $this->order->reference,
]; ];
$csvlines[] = $oneline; $csvlines[] = $oneline;
} }//end foreach
$data = $this->array2csv($csvlines, ";"); $data = $this->array2csv($csvlines, ";");
//$outputfilename = date("Ymd_His") . microtime(true) . ".csv"; $outputfilename = "BTQ_" .
$outputfilename = "BTQ_" . $this->order->reference . "_" . $code_client . "_" . $customer->salarie->nom . "_" . $customer->salarie->prenom . "_" . str_pad($customer->salarie->code_societe, 3, "0", STR_PAD_LEFT) . ".csv"; $this->order->reference . "_" .
$code_client . "_" .
$customer->salarie->nom . "_" .
$customer->salarie->prenom . "_" .
str_pad($customer->salarie->code_societe, 3, "0", STR_PAD_LEFT) . ".csv";
$disk->put($outputfilename, $data); $disk->put($outputfilename, $data);
//send this file by mail // Send this file by mail.
} }
} }

View file

@ -8,17 +8,21 @@ use ErrorException;
use TypeError; use TypeError;
use Illuminate\Database\QueryException; use Illuminate\Database\QueryException;
use App\Exceptions\AbortCsvImportException; use App\Exceptions\AbortCsvImportException;
use Illuminate\Contracts\Filesystem\Filesystem;
use Illuminate\Support\Str; use Illuminate\Support\Str;
class CsvSalariesReader extends CsvJobs class CsvSalariesReader extends CsvJobs
{ {
/** /**
* This is for Laravel Console usage * This is for Laravel Console usage
* @var \Illuminate\Console\Command|null
*/ */
public $console = null; public $console = null;
/**
* The Laravel disk name
*
* @var string
*/
protected $disk = 'salaries'; protected $disk = 'salaries';
/** /**
@ -28,7 +32,6 @@ class CsvSalariesReader extends CsvJobs
*/ */
public function __construct() public function __construct()
{ {
//
} }
/** /**
@ -44,7 +47,7 @@ class CsvSalariesReader extends CsvJobs
$files = $disk->files(); $files = $disk->files();
$progress = 1; $progress = 1;
$total = count(array_filter($files, function ($filename) { $total = count(array_filter($files, function ($filename) {
if ($this->fileHasToBeIgnored($filename)) { if ($this->fileHasToBeIgnored($filename)) {
return false; return false;
} }
@ -63,17 +66,17 @@ class CsvSalariesReader extends CsvJobs
try { try {
$data = $this->parseCsv($filepath); $data = $this->parseCsv($filepath);
//first line is header (mandatory) // First line is header (mandatory).
$header = array_flip(array_shift($data)); $header = array_flip(array_shift($data));
foreach ($data as $line) { foreach ($data as $line) {
$matricule = $line[$header['matricule']]; $matricule = $line[$header['matricule']];
$prenom = $line[$header['prenom']]; $prenom = $line[$header['prenom']];
$nom = $line[$header['nom']]; $nom = $line[$header['nom']];
$salarie = Salarie::firstOrNew(['matricule' => $matricule ]); $salarie = Salarie::firstOrNew(['matricule' => $matricule ]);
$salarie->matricule = $matricule; $salarie->matricule = $matricule;
$salarie->nom = $nom; $salarie->nom = $nom;
$salarie->prenom = $prenom; $salarie->prenom = $prenom;
$salarie->code = $salarie->code ?? $this->generateCode(); $salarie->code = $salarie->code ?? $this->generateCode();
$salarie->save(); $salarie->save();
} }
} catch (ErrorException | TypeError | QueryException $e) { } catch (ErrorException | TypeError | QueryException $e) {
@ -90,7 +93,8 @@ class CsvSalariesReader extends CsvJobs
), ),
LogType::critical() LogType::critical()
); );
continue; // ignore the file continue;
// Ignore the file.
} catch (AbortCsvImportException $e) { } catch (AbortCsvImportException $e) {
$this->log( $this->log(
sprintf( sprintf(
@ -101,19 +105,23 @@ class CsvSalariesReader extends CsvJobs
), ),
LogType::error() LogType::error()
); );
continue; // ignore the file continue;
} // Ignore the file.
}//end try
$this->moveToArchives($filename); $this->moveToArchives($filename);
} }//end foreach
// Clear old archives // Clear old archives.
$this->clearOldArchives(); $this->clearOldArchives();
} }
/** /**
* Génère un code d'inscription * Génère un code d'inscription
*
* @return string
*/ */
protected function generateCode() { protected function generateCode()
{
return Str::random(5); return Str::random(5);
} }
} }

View file

@ -38,19 +38,15 @@ class RefreshSiteMap implements ShouldQueue
'/login', '/login',
'/bo', '/bo',
'/activer', '/activer',
// '/deconnexion',
'/reinitialiser-mdp', '/reinitialiser-mdp',
// '/le-club-des-gaulois/la-boutique', // Hack ignore laravel debug bar.
// '/password/confirm', '/_debugbar',
// '/produit/from-menus', // Ignore ignition route.
// '/cote-cuisine/sante-et-nutrition/menu-equilibre-j', '_ignition/health-check',
// '/la-marque/tracabilite/search', // Ignore ignition route.
// '/frame', '_ignition/scripts/{script}',
// '/map', // Ignore ignition route.
'/_debugbar', // Hack ignore laravel debug bar '_ignition/styles/{style}'
'_ignition/health-check', //ignore ignition route
'_ignition/scripts/{script}', //ignore ignition route
'_ignition/styles/{style}' //ignore ignition route
]; ];
/** /**
@ -73,13 +69,12 @@ class RefreshSiteMap implements ShouldQueue
/** /**
* Execute the job. * Execute the job.
* *
*! Ici c'est du sale !!
* TODO: mettre tout ça dans un package pour le rendre plus générique
*
* @return void * @return void
* @phpcs:disable Generic.Metrics.CyclomaticComplexity.TooHigh
*/ */
public function handle() public function handle()
{ {
// @phpcs:enable
$this->assertRouteBinderIsCorrect(); $this->assertRouteBinderIsCorrect();
$siteMap = []; $siteMap = [];
@ -115,20 +110,20 @@ class RefreshSiteMap implements ShouldQueue
/** @var string $pName $parameter name on route uri */ /** @var string $pName $parameter name on route uri */
$pName = ''; $pName = '';
// If the route has parameters and the controller accepts it // If the route has parameters and the controller accepts it.
if (count($pNames) and \array_key_exists($param->getPosition(), $pNames)) { if (count($pNames) and \array_key_exists($param->getPosition(), $pNames)) {
// Get the controller parameter name for the route // Get the controller parameter name for the route.
$pName = $pNames[$param->getPosition()]; $pName = $pNames[$param->getPosition()];
} }
// If We have a custom binder for this route // If We have a custom binder for this route.
if ($this->hasRouteBinderParam($route, $pName)) { if ($this->hasRouteBinderParam($route, $pName)) {
$hasModels = true; $hasModels = true;
$this->processWithRouteBinderParam($rParams, $route, $pName); $this->processWithRouteBinderParam($rParams, $route, $pName);
continue; continue;
} }
// If This route takes a model as param // If This route takes a model as param.
if ($name and $name->isSubclassOf(Model::class)) { if ($name and $name->isSubclassOf(Model::class)) {
$hasModels = true; $hasModels = true;
/** @var \string */ /** @var \string */
@ -136,19 +131,20 @@ class RefreshSiteMap implements ShouldQueue
$this->setParamsForModel($rParams, $modelClassName, $pName); $this->setParamsForModel($rParams, $modelClassName, $pName);
continue; continue;
} }
} }//end foreach
// If the route has no dynamic models as parameters // If the route has no dynamic models as parameters.
if (!count($params) or !$hasModels) { if (!count($params) or !$hasModels) {
$siteMap[] = [ $siteMap[] = [
route($route->getName()), route($route->getName()),
Url::CHANGE_FREQUENCY_MONTHLY, Url::CHANGE_FREQUENCY_MONTHLY,
0.1 0.1
]; ];
} else { // If the route has dynamic models as parameters } else {
// If the route has dynamic models as parameters.
$this->genRoute($route, $siteMap, $rParams); $this->genRoute($route, $siteMap, $rParams);
} }
} }//end foreach
$sm = Sitemap::create(); $sm = Sitemap::create();
foreach ($siteMap as $smRules) { foreach ($siteMap as $smRules) {
@ -163,9 +159,11 @@ class RefreshSiteMap implements ShouldQueue
/** /**
* Process route with binderParam * Process route with binderParam
* *
* @param array $rParams
* @param RoutingRoute $route * @param RoutingRoute $route
* @param string $pName * @param string $pName
* @return void * @return void
* @throws Exception When unhandled class.
*/ */
private function processWithRouteBinderParam(array &$rParams, RoutingRoute $route, string $pName) private function processWithRouteBinderParam(array &$rParams, RoutingRoute $route, string $pName)
{ {
@ -175,7 +173,7 @@ class RefreshSiteMap implements ShouldQueue
$modelClassName = $o[0]; $modelClassName = $o[0];
/** @var \string */ /** @var \string */
$routeParamName = $o[1]; $routeParamName = $o[1];
$rfLCls = (new ReflectionClass($modelClassName)); $rfLCls = (new ReflectionClass($modelClassName));
switch (true) { switch (true) {
case $rfLCls->isSubclassOf(Model::class): case $rfLCls->isSubclassOf(Model::class):
@ -192,7 +190,7 @@ class RefreshSiteMap implements ShouldQueue
/** /**
* Set route param Array for Enums * Set route param Array for Enums
* *
* @param array $rParams * @param array $rParams
* @param string $enumClassName * @param string $enumClassName
* @param string $pName * @param string $pName
* @return void * @return void
@ -210,7 +208,7 @@ class RefreshSiteMap implements ShouldQueue
/** /**
* Set route param Array for Models * Set route param Array for Models
* *
* @param array $rParams * @param array $rParams
* @param string $modelClassName * @param string $modelClassName
* @param string $pName * @param string $pName
* @param string $routeParamName * @param string $routeParamName
@ -222,16 +220,15 @@ class RefreshSiteMap implements ShouldQueue
string $pName, string $pName,
string $routeParamName = null string $routeParamName = null
) { ) {
$i = 0; $i = 0;
$limit = 10; $limit = 10;
$modelTable = (new ReflectionClass($modelClassName))->newInstanceWithoutConstructor()->getTable(); $modelTable = (new ReflectionClass($modelClassName))->newInstanceWithoutConstructor()->getTable();
$q = $modelClassName::query(); $q = $modelClassName::query();
$q = Schema::hasColumn($modelTable, 'status') ? $q->where('status', true) : $q; $q = Schema::hasColumn($modelTable, 'status') ? $q->where('status', true) : $q;
$q = Schema::hasColumn($modelTable, 'ocbStatus') ? $q->where('ocbStatus', EleveurOcbStatus::yes()->value) : $q; $q = Schema::hasColumn($modelTable, 'star_moment') ? $q->where('star_moment', true) : $q;
$q = Schema::hasColumn($modelTable, 'star_moment') ? $q->where('star_moment', true) : $q;
do { do {
$results = $q->offset($i * $limit)->limit($limit)->get(); $results = $q->offset($i * $limit)->limit($limit)->get();
$length = count($results); $length = count($results);
$results->map(function (Model $model) use (&$rParams, $pName, $routeParamName) { $results->map(function (Model $model) use (&$rParams, $pName, $routeParamName) {
if (!array_key_exists($pName, $rParams)) { if (!array_key_exists($pName, $rParams)) {
$rParams[$pName] = []; $rParams[$pName] = [];
@ -250,8 +247,8 @@ class RefreshSiteMap implements ShouldQueue
* Recursively generate routes for all params * Recursively generate routes for all params
* *
* @param RoutingRoute $route * @param RoutingRoute $route
* @param array $siteMap * @param array $siteMap
* @param array $params * @param array $params
* @return void * @return void
*/ */
private function genRoute(RoutingRoute $route, array &$siteMap, array $params) private function genRoute(RoutingRoute $route, array &$siteMap, array $params)
@ -290,7 +287,7 @@ class RefreshSiteMap implements ShouldQueue
* Check if $route exists in routesBinder and has $param * Check if $route exists in routesBinder and has $param
* *
* @param RoutingRoute $route * @param RoutingRoute $route
* @param string $param * @param string $param
* @return boolean * @return boolean
*/ */
private function hasRouteBinderParam(RoutingRoute $route, string $param): bool private function hasRouteBinderParam(RoutingRoute $route, string $param): bool
@ -316,7 +313,7 @@ class RefreshSiteMap implements ShouldQueue
* Get the routeBinder param * Get the routeBinder param
* *
* @param RoutingRoute $route * @param RoutingRoute $route
* @param string $param * @param string $param
* @return array * @return array
*/ */
private function getRouteBinderParam(RoutingRoute $route, string $param): array private function getRouteBinderParam(RoutingRoute $route, string $param): array
@ -327,7 +324,7 @@ class RefreshSiteMap implements ShouldQueue
/** /**
* Assert that routeBinder is correct * Assert that routeBinder is correct
* *
* @throws Exception * @throws Exception When route does not exist | incomplrte parameters | parameter is not a model class.
* @return void * @return void
*/ */
private function assertRouteBinderIsCorrect() private function assertRouteBinderIsCorrect()
@ -367,8 +364,8 @@ class RefreshSiteMap implements ShouldQueue
$p[0] $p[0]
)); ));
} }
} }//end foreach
} }//end foreach
} }
/** /**

View file

@ -3,7 +3,6 @@
namespace App\Jobs; namespace App\Jobs;
use App\Enums\LogType; use App\Enums\LogType;
use Exception;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Filesystem\Filesystem; use Illuminate\Contracts\Filesystem\Filesystem;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
@ -30,6 +29,7 @@ abstract class XArcadiaFlux implements ShouldQueue
/** /**
* This is for Laravel Console usage * This is for Laravel Console usage
* @var \Illuminate\Console\Command|null
*/ */
public $console = null; public $console = null;
@ -53,6 +53,7 @@ abstract class XArcadiaFlux implements ShouldQueue
* Check if the file extension * Check if the file extension
* *
* @param string $filename * @param string $filename
* @param string $extension
* @return boolean * @return boolean
*/ */
protected function checkExtension(string $filename, string $extension): bool protected function checkExtension(string $filename, string $extension): bool
@ -110,7 +111,7 @@ abstract class XArcadiaFlux implements ShouldQueue
*/ */
protected function clearOldArchives(): void protected function clearOldArchives(): void
{ {
$disk = $this->getDisk(); $disk = $this->getDisk();
$archives = $disk->files($this->archiveFolderName); $archives = $disk->files($this->archiveFolderName);
// /** @var File */ // /** @var File */
@ -141,9 +142,10 @@ abstract class XArcadiaFlux implements ShouldQueue
/** /**
* Logs data * Logs data
* *
* @param string $message * @param string $message
* @param LogType $logtype * @param LogType $logtype
* @return void * @return void
* @throws \ErrorException If logtype is not handled.
*/ */
protected function log(string $message, LogType $logtype = null): void protected function log(string $message, LogType $logtype = null): void
{ {
@ -171,17 +173,18 @@ abstract class XArcadiaFlux implements ShouldQueue
Log::critical($message); Log::critical($message);
break; break;
default: default:
throw new Exception(sprintf('%s : unhandled log type %s', get_class($this), $logtype->label)); throw new \ErrorException(sprintf('%s : unhandled log type %s', get_class($this), $logtype->label));
} }//end switch
$this->consolePrint($message, $logtype); $this->consolePrint($message, $logtype);
} }
/** /**
* Prints to the console * Prints to the console
* *
* @param string $message * @param string $message
* @param LogType $logtype * @param LogType $logtype
* @return void * @return void
* @throws \ErrorException If logtype is not handled.
*/ */
protected function consolePrint(string $message, LogType $logtype): void protected function consolePrint(string $message, LogType $logtype): void
{ {
@ -200,7 +203,7 @@ abstract class XArcadiaFlux implements ShouldQueue
$this->console->error($message); $this->console->error($message);
break; break;
default: default:
throw new Exception(sprintf('%s : unhandled log type %s', get_class($this), $logtype->label)); throw new \ErrorException(sprintf('%s : unhandled log type %s', get_class($this), $logtype->label));
} }
} }
} }

View file

@ -8,12 +8,26 @@ use SimpleXMLElement;
class XmlIncoReader extends XmlJobs class XmlIncoReader extends XmlJobs
{ {
/**
* The Laravel disk name
*
* @var string
*/
protected $disk = 'inco'; protected $disk = 'inco';
/**
* Storage path
*
* @var string
*/
protected $imagesPath = 'images'; protected $imagesPath = 'images';
/** /**
* The columns to take from the XML
* subcolumns can be added with a dot
*
* @var array
*
* éléments à la racine : nom du noeud * éléments à la racine : nom du noeud
* sous éléments d'un noeud PARENT : * sous éléments d'un noeud PARENT :
* d'abord: * d'abord:
@ -29,42 +43,47 @@ class XmlIncoReader extends XmlJobs
* 'EXPLOITANT.NOM_SOCIETE' => 'nom_societe', * 'EXPLOITANT.NOM_SOCIETE' => 'nom_societe',
*/ */
protected $takeColumns = [ protected $takeColumns = [
'NO_ART' => 'id', // primary key on model 'NO_ART' => 'id',
// Primary key on model.
//this wil not return anything cf doc above // This wil not return anything cf doc above.
'ID_SOCIETE' => 'id_societe', 'ID_SOCIETE' => 'id_societe',
'NOM_SOCIETE' => 'nom_societe', 'NOM_SOCIETE' => 'nom_societe',
'PROD_SAISON' => 'prod_saison', 'PROD_SAISON' => 'prod_saison',
'NOM' => 'nom', 'NOM' => 'nom',
'NUMERO' => 'numero', 'NUMERO' => 'numero',
'TAILLE_REF' => 'taille_ref', //$poidsRef censé être dans INCO_COMPO (et généralement 100g) 'TAILLE_REF' => 'taille_ref',
// $poidsRef censé être dans INCO_COMPO (et généralement 100g)
'ALLEGATIONS' => 'allegations', 'ALLEGATIONS' => 'allegations',
'CONSEIL_PREPA' => 'conseil_prepa', 'CONSEIL_PREPA' => 'conseil_prepa',
'ASTUCES' => 'astuces', 'ASTUCES' => 'astuces',
'DESCRIPTIF' => 'descriptif', //$descriptif 'DESCRIPTIF' => 'descriptif',
// $descriptif
'ARG_VENTE' => 'arg_vente', 'ARG_VENTE' => 'arg_vente',
'NB_PORTION' => 'nb_portion', 'NB_PORTION' => 'nb_portion',
'TYP_PORTION' => 'typ_portion', 'TYP_PORTION' => 'typ_portion',
'PDS_MOY_THEO' => 'pds_moy_theo', 'PDS_MOY_THEO' => 'pds_moy_theo',
'LIB_CONSO' => 'lib_conso', 'LIB_CONSO' => 'lib_conso',
'LST_ING' => 'lst_ing', //$ingredients 'LST_ING' => 'lst_ing',
// $ingredients
// list alergene // List alergene.
'LST_ALLERGENE' => 'lst_allergene', // Consider this sub array 'LST_ALLERGENE' => 'lst_allergene',
// Consider this sub array.
'LST_ALLERGENE.LIB_ALLERGENE' => 'lib_allergene', 'LST_ALLERGENE.LIB_ALLERGENE' => 'lib_allergene',
// Allegations // Allegations.
'ALLEGAT_SANTE' => 'allegat_sante', 'ALLEGAT_SANTE' => 'allegat_sante',
'ALLEGAT_NUTRIT' => 'allegat_nutrit', 'ALLEGAT_NUTRIT' => 'allegat_nutrit',
'ALLEGAT_AUTRE' => 'allegat_autre', 'ALLEGAT_AUTRE' => 'allegat_autre',
'INCO_COMPO' => 'inco_compo', // Consider this sub array 'INCO_COMPO' => 'inco_compo',
// Consider this sub array.
'INCO_COMPO.NOM' => 'nom', 'INCO_COMPO.NOM' => 'nom',
'INCO_COMPO.TAILLE_REF' => 'taille_ref', 'INCO_COMPO.TAILLE_REF' => 'taille_ref',
'INCO_COMPO.VAL_ENERG_KJ_NUT' => 'val_energ_kj_nut', 'INCO_COMPO.VAL_ENERG_KJ_NUT' => 'val_energ_kj_nut',
'INCO_COMPO.VAL_ENERG_KJ_R' => 'val_energ_kj_r', //_R apports de la taille_ref 'INCO_COMPO.VAL_ENERG_KJ_R' => 'val_energ_kj_r',
// _R apports de la taille_ref
'INCO_COMPO.VAL_ENERG_KCAL_R' => 'val_energ_kcal_r', 'INCO_COMPO.VAL_ENERG_KCAL_R' => 'val_energ_kcal_r',
'INCO_COMPO.VAL_ENERG_KCAL_NUT' => 'val_energ_kcal_nut', 'INCO_COMPO.VAL_ENERG_KCAL_NUT' => 'val_energ_kcal_nut',
'INCO_COMPO.MAT_GRASS_R' => 'mat_grass_r', 'INCO_COMPO.MAT_GRASS_R' => 'mat_grass_r',
@ -85,7 +104,8 @@ class XmlIncoReader extends XmlJobs
'INCO_COMPO.ENER_E14_R' => 'ener_e14_r', 'INCO_COMPO.ENER_E14_R' => 'ener_e14_r',
'INCO_COMPO.FRUITS_R' => 'fruits_r', 'INCO_COMPO.FRUITS_R' => 'fruits_r',
'INCO_COMPO.FRUITS_COQUE_SECH_R' => 'fruits_coque_sech_r', 'INCO_COMPO.FRUITS_COQUE_SECH_R' => 'fruits_coque_sech_r',
'INCO_COMPO.POURCENT_APPORT_REF_E14_R' => 'pourcent_apport_ref_e14_r', //POURCENT_*_P apports journaliers par portion 'INCO_COMPO.POURCENT_APPORT_REF_E14_R' => 'pourcent_apport_ref_e14_r',
// POURCENT_*_P apports journaliers par portion.
'INCO_COMPO.ENER_KJO_R' => 'ener_kjo_r', 'INCO_COMPO.ENER_KJO_R' => 'ener_kjo_r',
'INCO_COMPO.POURCENT_APPORT_REF_KJO_R' => 'pourcent_apport_ref_kjo_r', 'INCO_COMPO.POURCENT_APPORT_REF_KJO_R' => 'pourcent_apport_ref_kjo_r',
'INCO_COMPO.POURCENT_APPORT_REF_FAT_R' => 'pourcent_apport_ref_fat_r', 'INCO_COMPO.POURCENT_APPORT_REF_FAT_R' => 'pourcent_apport_ref_fat_r',
@ -102,8 +122,10 @@ class XmlIncoReader extends XmlJobs
'INCO_COMPO.SALTEQ_R' => 'salteq_r', 'INCO_COMPO.SALTEQ_R' => 'salteq_r',
'INCO_COMPO.POURCENT_APPORT_REF_SALTEQ_R' => 'pourcent_apport_ref_salteq_r', 'INCO_COMPO.POURCENT_APPORT_REF_SALTEQ_R' => 'pourcent_apport_ref_salteq_r',
'INCO_COMPO.APPORT_REF' => 'apport_ref', 'INCO_COMPO.APPORT_REF' => 'apport_ref',
'INCO_COMPO.TAILLE_PORT' => 'taille_port', //$poidsPortion 'INCO_COMPO.TAILLE_PORT' => 'taille_port',
'INCO_COMPO.VAL_ENERG_KJ_P' => 'val_energ_kj_p', //_P apports par portion // $poidsPortion
'INCO_COMPO.VAL_ENERG_KJ_P' => 'val_energ_kj_p',
// _P apports par portion
'INCO_COMPO.VAL_ENERG_KCAL_P' => 'val_energ_kcal_p', 'INCO_COMPO.VAL_ENERG_KCAL_P' => 'val_energ_kcal_p',
'INCO_COMPO.MAT_GRASS_P' => 'mat_grass_p', 'INCO_COMPO.MAT_GRASS_P' => 'mat_grass_p',
'INCO_COMPO.AGS_P' => 'ags_p', 'INCO_COMPO.AGS_P' => 'ags_p',
@ -145,8 +167,10 @@ class XmlIncoReader extends XmlJobs
'INCO_COMPO.COMPOSANTE_N' => 'composante_n', 'INCO_COMPO.COMPOSANTE_N' => 'composante_n',
'INCO_COMPO.COMPOSANTE_P' => 'composante_p', 'INCO_COMPO.COMPOSANTE_P' => 'composante_p',
'INCO_COMPO.POURCENT_FRUITS' => 'pourcent_fruits', 'INCO_COMPO.POURCENT_FRUITS' => 'pourcent_fruits',
'INCO_COMPO.SCORE_NUTRI' => 'score_nutri', //du coup nutriscore ? 'INCO_COMPO.SCORE_NUTRI' => 'score_nutri',
'INCO_COMPO.CLASSEMENT' => 'classement', //$nutriscore mais pas censé être dans INCO_COMPO // Du coup nutriscore ?.
'INCO_COMPO.CLASSEMENT' => 'classement',
// $nutriscore mais pas censé être dans INCO_COMPO
'INCO_COMPO.MAT_GRASS_R_PREC' => 'mat_grass_r_prec', 'INCO_COMPO.MAT_GRASS_R_PREC' => 'mat_grass_r_prec',
'INCO_COMPO.AGS_R_PREC' => 'ags_r_prec', 'INCO_COMPO.AGS_R_PREC' => 'ags_r_prec',
'INCO_COMPO.GLUCIDES_R_PREC' => 'glucides_r_prec', 'INCO_COMPO.GLUCIDES_R_PREC' => 'glucides_r_prec',
@ -159,6 +183,11 @@ class XmlIncoReader extends XmlJobs
'INCO_COMPO.FRUITS_COQUE_SECH_R_PREC' => 'fruits_coque_sech_r_prec', 'INCO_COMPO.FRUITS_COQUE_SECH_R_PREC' => 'fruits_coque_sech_r_prec',
]; ];
/**
* The columns allowed to be null
*
* @var array
*/
protected $nullableFields = [ protected $nullableFields = [
'taille_ref', 'taille_ref',
'conseil_prepa', 'conseil_prepa',
@ -272,8 +301,18 @@ class XmlIncoReader extends XmlJobs
'inco_compo.fruits_coque_sech_r_prec' 'inco_compo.fruits_coque_sech_r_prec'
]; ];
/**
* Unique keys for updating rows
*
* @var array
*/
protected $uniqueKeyField = ['id']; protected $uniqueKeyField = ['id'];
/**
* Columns to merge in
*
* @var array
*/
protected $mergeColumns = [ protected $mergeColumns = [
'allegations' => [ 'allegations' => [
'allegat_sante', 'allegat_sante',
@ -379,15 +418,20 @@ class XmlIncoReader extends XmlJobs
] ]
]; ];
/**
* Execute the job.
*
* @return void
*/
public function handle() public function handle()
{ {
$this->parseData('INCO', XmlInco::class, function (SimpleXMLElement $xmlData, array &$line) { $this->parseData('INCO', XmlInco::class, function (SimpleXMLElement $xmlData, array &$line) {
// merge columns // Merge columns.
foreach ($this->mergeColumns as $key => $values) { foreach ($this->mergeColumns as $key => $values) {
$line[$key] = []; $line[$key] = [];
// merge columns and remove merged columns from line // Merge columns and remove merged columns from line.
array_map(function ($kValue) use (&$line, $key) { array_map(function ($kValue) use (&$line, $key) {
if (array_key_exists($kValue, $line)) { if (array_key_exists($kValue, $line)) {
$line[$key][$kValue] = $line[$kValue]; $line[$key][$kValue] = $line[$kValue];
@ -398,13 +442,9 @@ class XmlIncoReader extends XmlJobs
$line[$key] = implode(',', array_filter($line[$key])); $line[$key] = implode(',', array_filter($line[$key]));
$line[$key] = strlen($line[$key]) ? $line[$key] : null; $line[$key] = strlen($line[$key]) ? $line[$key] : null;
} }
//json column cast into array in model => no need for encode
// if ($key == 'nutritional_values') {
// $line[$key] = json_encode($line[$key], \JSON_FORCE_OBJECT);
// }
} }
// Boolean cast prod_saison // Boolean cast prod_saison.
$line['prod_saison'] = isset($line['prod_saison']) ? $line['prod_saison'] = isset($line['prod_saison']) ?
(strtolower($line['prod_saison']) == 'non' ? false : true) : false; (strtolower($line['prod_saison']) == 'non' ? false : true) : false;
@ -413,52 +453,118 @@ class XmlIncoReader extends XmlJobs
}); });
} }
/**
* Extract Image form XML file
*
* @param SimpleXMLElement $xmlData
* @return array
* @throws AbortXmlImportException When media tag does not contain an image.
*/
private function parseImage(SimpleXMLElement $xmlData) private function parseImage(SimpleXMLElement $xmlData)
{ {
$images = $xmlData->INCO->MEDIA_VISUEL_EAI->MEDIA_VISUEL_EAI; $list_media = $xmlData->INCO->MEDIA_VISUEL_EAI->MEDIA_VISUEL_EAI;
$arImgPaths = array(); $arImgPaths = array();
$index = 1; $index = 1;
foreach ($images as $image) { foreach ($list_media as $media) {
$image = $media->img;
$imageData = trim((string)$image); $imageData = trim((string)$image);
if (strlen($imageData)) { if (strlen($imageData)) {
$imageData = base64_decode($imageData); $imageData = base64_decode($imageData);
$imgName = strval($xmlData->INCO->INCO_COMPO->TBL_INCO_COMPO->ID_INCO); $imgName = strval($xmlData->INCO->INCO_COMPO->TBL_INCO_COMPO->ID_INCO);
if(empty($imgName)) { if (empty($imgName)) {
$imgName = strval($xmlData->INCO->NO_ART); $imgName = strval($xmlData->INCO->NO_ART);
} }
$imgName = $imgName."_".$index; $imgName = $imgName . "_" . $index;
$imgNamePath = sprintf('%s/%s', rtrim($this->imagesPath, '/'), $imgName); $imgNamePath = sprintf('%s/%s', rtrim($this->imagesPath, '/'), $imgName);
$disk = $this->getDisk(); $disk = $this->getDisk();
$info = getimagesizefromstring($imageData); $info = getimagesizefromstring($imageData);
$mime = $info['mime']; if ($info !== false) {
switch ($mime) { $mime = $info['mime'];
case 'image/jpeg': switch ($mime) {
$imgExtension = 'jpg'; case 'image/jpeg':
break; $imgExtension = 'jpg';
case 'image/png': break;
$imgExtension = 'png'; case 'image/png':
break; $imgExtension = 'png';
case 'image/gif': break;
$imgExtension = 'gif'; case 'image/gif':
break; $imgExtension = 'gif';
default: break;
throw new AbortXmlImportException(sprintf('Unknown image type %s', $imgName)); default:
} throw new AbortXmlImportException(sprintf('Unknown image type %s', $imgName));
}
$imgNamePath = sprintf('%s.%s', $imgNamePath, $imgExtension); $imgNamePath = sprintf('%s.%s', $imgNamePath, $imgExtension);
if (!$disk->put($imgNamePath, $imageData)) { if (!$disk->put($imgNamePath, $imageData)) {
throw new AbortXmlImportException(sprintf('The image %s could not be saved', $imgNamePath)); throw new AbortXmlImportException(sprintf('The image %s could not be saved', $imgNamePath));
} }
$arImgPaths[$index] = sprintf('%s/%s', $this->disk, $imgNamePath); $arImgPaths[$index] = sprintf('%s/%s', $this->disk, $imgNamePath);
$index++; $index++;
} }//end if
} }//end if
}//end foreach
return $arImgPaths; return $arImgPaths;
} }
/**
* Recursive extract to array
* introduce sort of Hook to transform
* <TYP_PORTION>
* <code><![CDATA[2]]></code>
* <libelle><![CDATA[Approximatif]]></libelle>
* </TYP_PORTION>
* extracted as "TYP_PORTION" => array:1 [
* 0 => array:2 [
* "code" => "2"
* "libelle" => "Approximatif"
* ]
* ]
* into this
* <TYP_PORTION><![CDATA[Approximatif]]></TYP_PORTION>
* extracted as "TYP_PORTION" => "Approximatif"
*
*
* @param \SimpleXMLElement|false $sxe
* @return array
*/
protected function extract($sxe = null): array
{
if (!$sxe instanceof SimpleXMLElement) {
return array();
}
$extract = array();
foreach ($sxe->children() as $key => $value) {
if ($value->count()) {
$extraction = $this->extract($value);
if (
count($extraction)
&& array_key_exists("code", $extraction)
&& array_key_exists("libelle", $extraction)
) {
$val = strval($extraction['libelle']);
$extract[$key] = strlen($val) ? $val : null;
continue;
}
$extract[$key][] = $extraction;
continue;
}
$value = strval($value);
if (array_key_exists($key, $extract) and is_array($extract[$key])) {
$extract[$key][] = strlen($value) ? $value : null;
} else {
$extract[$key] = strlen($value) ? $value : null;
}
}//end foreach
return $extract;
}
} }

View file

@ -7,7 +7,6 @@ use App\Exceptions\AbortXmlImportException;
use App\Exceptions\InvalidXmlException; use App\Exceptions\InvalidXmlException;
use ErrorException; use ErrorException;
use Illuminate\Contracts\Filesystem\FileNotFoundException; use Illuminate\Contracts\Filesystem\FileNotFoundException;
use Illuminate\Contracts\Filesystem\Filesystem;
use Illuminate\Database\QueryException; use Illuminate\Database\QueryException;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail; use Illuminate\Support\Facades\Mail;
@ -20,7 +19,6 @@ use TypeError;
abstract class XmlJobs extends XArcadiaFlux abstract class XmlJobs extends XArcadiaFlux
{ {
/** /**
* invalid xml folder * invalid xml folder
* *
@ -54,20 +52,24 @@ abstract class XmlJobs extends XArcadiaFlux
/** /**
* Parse Data from the XML and gives it to the callback * Parse Data from the XML and gives it to the callback
* *
* @param string $entityName * @param string $entityName
* @param string $modelClass * @param string $modelClass
* @param callable $callback
* @throws InvalidXmlException When xml is invalid.
* @return void * @return void
*
* @phpcs:disable Generic.Metrics.CyclomaticComplexity.TooHigh
*/ */
// phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh
protected function parseData(string $entityName, string $modelClass, callable $callback = null): void protected function parseData(string $entityName, string $modelClass, callable $callback = null): void
{ {
// @phpcs:enable
/** @var Filesystem */ /** @var Filesystem */
$disk = $this->getDisk(); $disk = $this->getDisk();
$this->log('Démarrage du traitement'); $this->log('Démarrage du traitement');
$files = $disk->files(); $files = $disk->files();
$progress = 1; $progress = 1;
$total = count(array_filter($files, function ($filename) { $total = count(array_filter($files, function ($filename) {
if ($this->fileHasToBeIgnored($filename)) { if ($this->fileHasToBeIgnored($filename)) {
return false; return false;
} }
@ -96,15 +98,10 @@ abstract class XmlJobs extends XArcadiaFlux
if ($xmlContent === false) { if ($xmlContent === false) {
throw new InvalidXmlException('XML is Invalid (simplexml_load_string returned false)'); throw new InvalidXmlException('XML is Invalid (simplexml_load_string returned false)');
// $this->log(
// sprintf('File %s could not be parsed (simplexml_load_string)', $filename),
// LogType::critical()
// );
// continue; // ignore the file
} }
} catch (ErrorException $e) { } catch (ErrorException $e) {
throw new InvalidXmlException('XML is Invalid', 0, $e); throw new InvalidXmlException('XML is Invalid', 0, $e);
} }//end try
$data = $this->extract($xmlContent); $data = $this->extract($xmlContent);
@ -117,7 +114,7 @@ abstract class XmlJobs extends XArcadiaFlux
$lines[] = $line; $lines[] = $line;
} }
// Mise en base des données // Mise en base des données.
foreach ($lines as $line) { foreach ($lines as $line) {
/** @var array Unique Key columns */ /** @var array Unique Key columns */
$uniqueColumnsKey = []; $uniqueColumnsKey = [];
@ -128,7 +125,6 @@ abstract class XmlJobs extends XArcadiaFlux
[$modelClass, 'updateOrCreate'], [$modelClass, 'updateOrCreate'],
[$uniqueColumnsKey, $line] [$uniqueColumnsKey, $line]
); );
// @todo : should we put that method in a interface ?
$savedData->updateLocalProductInfo(); $savedData->updateLocalProductInfo();
} }
} catch (InvalidXmlException $e) { } catch (InvalidXmlException $e) {
@ -159,7 +155,8 @@ abstract class XmlJobs extends XArcadiaFlux
LogType::critical() LogType::critical()
); );
$this->sendErrorParseEmailToServiceWeb($e); $this->sendErrorParseEmailToServiceWeb($e);
continue; // ignore the file continue;
// Ignore the file.
} catch (AbortXmlImportException $e) { } catch (AbortXmlImportException $e) {
$this->log( $this->log(
sprintf( sprintf(
@ -172,9 +169,10 @@ abstract class XmlJobs extends XArcadiaFlux
); );
$this->sendErrorParseEmailToServiceWeb($e); $this->sendErrorParseEmailToServiceWeb($e);
$this->moveToInvalid($filename); $this->moveToInvalid($filename);
continue; // ignore the file continue;
// Ignore the file.
} catch (FileNotFoundException | QueryException $e) { } catch (FileNotFoundException | QueryException $e) {
// This happens because of concurent xml jobs read // This happens because of concurent xml jobs read.
$message = $e->getMessage(); $message = $e->getMessage();
if (get_class($e) === QueryException::class) { if (get_class($e) === QueryException::class) {
$message = implode(' ', $e->errorInfo); $message = implode(' ', $e->errorInfo);
@ -188,12 +186,13 @@ abstract class XmlJobs extends XArcadiaFlux
), ),
LogType::debug() LogType::debug()
); );
continue; // ignore the file continue;
} // Ignore the file.
}//end try
$this->moveToArchives($filename); $this->moveToArchives($filename);
} }//end foreach
// Clear old archives // Clear old archives.
$this->clearOldArchives(); $this->clearOldArchives();
} }
@ -229,7 +228,7 @@ abstract class XmlJobs extends XArcadiaFlux
* *
* @param array $fields * @param array $fields
* @return array * @return array
* @throws AbortXmlImportException * @throws AbortXmlImportException When field should not be null.
*/ */
protected function processFields(array $fields): array protected function processFields(array $fields): array
{ {
@ -242,7 +241,7 @@ abstract class XmlJobs extends XArcadiaFlux
throw new AbortXmlImportException(sprintf('The field %s is not allowed to be null', $key)); throw new AbortXmlImportException(sprintf('The field %s is not allowed to be null', $key));
} }
if (is_array($field)) { if (is_array($field)) {
// Flatten data // Flatten data.
$it = new RecursiveIteratorIterator(new RecursiveArrayIterator($field)); $it = new RecursiveIteratorIterator(new RecursiveArrayIterator($field));
foreach ($it as $k => $f) { foreach ($it as $k => $f) {
$ko = strtolower(sprintf('%s.%s', $key, $k)); $ko = strtolower(sprintf('%s.%s', $key, $k));
@ -261,7 +260,7 @@ abstract class XmlJobs extends XArcadiaFlux
} else { } else {
$result[$key] = $field; $result[$key] = $field;
} }
} }//end foreach
return $result; return $result;
} }
@ -324,6 +323,12 @@ abstract class XmlJobs extends XArcadiaFlux
return $isXml; return $isXml;
} }
/**
* Send Error Mail
*
* @param Throwable $e
* @return void
*/
protected function sendErrorParseEmailToServiceWeb(Throwable $e) protected function sendErrorParseEmailToServiceWeb(Throwable $e)
{ {
Mail::send('emails.exception', [ Mail::send('emails.exception', [
@ -337,6 +342,13 @@ abstract class XmlJobs extends XArcadiaFlux
}); });
} }
/**
* Send Mail Invalid XML
*
* @param string $filename
* @param Throwable $e
* @return void
*/
protected function sendInvalidXmlEmail(string $filename, Throwable $e) protected function sendInvalidXmlEmail(string $filename, Throwable $e)
{ {
$message = $e->getPrevious()->getMessage(); $message = $e->getPrevious()->getMessage();

View file

@ -0,0 +1,190 @@
<?php
namespace App\Lib;
class ExceptionsHelper
{
/**
* Handle sentry event
*
* @param \Sentry\Event $event
* @return null|\Sentry\Event
*/
public static function sentryEventHandler(\Sentry\Event $event): ?\Sentry\Event
{
// Remove unwanted reports.
$event->setModules([]);
$event->setOsContext(null);
/** @var \Sentry\ExceptionDataBag[] */
$exceptionBag = [];
foreach ($event->getExceptions() as $exceptionDataBag) {
$exceptionBag[] = self::getAnonymizedSentryException($exceptionDataBag);
}
$event->setExceptions($exceptionBag);
return $event;
}
/**
* Anonimize Sentry Exception bag
*
* @param \Sentry\ExceptionDataBag $exceptionDataBag
* @return \Sentry\ExceptionDataBag
*/
private static function getAnonymizedSentryException(
\Sentry\ExceptionDataBag $exceptionDataBag
): \Sentry\ExceptionDataBag {
$exceptionDataBag->setValue(self::getAnonymizedMessage($exceptionDataBag->getValue()));
if ($stackTrace = $exceptionDataBag->getStacktrace()) {
$exceptionDataBag->setStacktrace(self::getAnonymizedSentryStackTrace($stackTrace));
}
return $exceptionDataBag;
}
/**
* Anonymise sentry stacktrace
*
* @param \Sentry\Stacktrace $stackTrace
* @return \Sentry\Stacktrace
*/
private static function getAnonymizedSentryStackTrace(\Sentry\Stacktrace $stackTrace): \Sentry\Stacktrace
{
/** @var \Sentry\Frame[] */
$frames = \array_reverse($stackTrace->getFrames(), true);
$i = \count($frames) - 1;
// * Remove all but keep first (index.php).
while ($i-- > 0) {
$stackTrace->removeFrame(count($stackTrace->getFrames()) - 1);
}
foreach ($frames as $index => $frame) {
$frame->setPostContext([]);
$frame->setPreContext([]);
$frame->setContextLine('');
$frame->setVars(self::getAnonymizedSentryParams($frame->getVars()));
$stackTrace->addFrame($frame);
if ($index === 0) {
$stackTrace->removeFrame(count($stackTrace->getFrames()) - 1);
}
}
return $stackTrace;
}
/**
* Get anonymized sentry params
*
* @param mixed[] $params
* @return string[]
*/
private static function getAnonymizedSentryParams(array $params): array
{
foreach ($params as &$param) {
$type = \strtolower(\gettype($param));
if (\is_string($param)) {
$type = \explode(' ', \trim($param))[0] ?? null;
}
switch ($type) {
case 'Lambda':
case 'Object':
continue 2;
case 'array':
$param = sprintf('Array(%d)', \count($param));
continue 2;
default:
if (\is_numeric($param)) {
$param = \ucfirst($type);
continue 2;
}
if (\is_string($param)) {
$param = sprintf('String(%d)', \strlen($param));
continue 2;
}
} //end switch
} //end foreach
return $params;
}
/**
* Anonymize at least Sql queries
*
* @param string $message
* @return string
*/
public static function getAnonymizedMessage(string $message): string
{
$message = \preg_replace('/^(.*)( \(SQL:.*\))$/', '$1', $message) ?? $message;
if ($sqlPos = \strpos($message, 'to use near')) {
$message = \mb_strcut($message, 0, $sqlPos);
}
return $message;
}
/**
* Anonymize stack trace
*
* @param \Throwable $e
* @return string
*/
public static function getAnonymizedStackTrace(\Throwable $e): string
{
$projectPath = \realpath(\sprintf('%s/../', \app_path()));
$traceStack = $e->getTrace();
$traceStr = '';
$maxStackStage = 0;
foreach ($traceStack as $stackStage => $stack) {
$maxStackStage = $stackStage;
$traceStr .= \sprintf(
'#%s %s(%d): ',
$stackStage,
str_replace($projectPath, '', $stack['file'] ?? ''),
$stack['line'] ?? ''
);
if (isset($stack['class'])) {
$traceStr .= "{$stack['class']}->{$stack['function']}(";
if (isset($stack['args'])) {
$traceStr .= self::handleArgs($stack);
}
$traceStr .= ")\n";
} elseif (isset($stack['function'])) {
$traceStr .= "{$stack['function']}(";
if (isset($stack['args'])) {
$traceStr .= self::handleArgs($stack);
}
$traceStr .= ")\n";
}
} //end foreach
$maxStackStage++;
$traceStr .= "#$maxStackStage {main}";
return $traceStr;
}
/**
* Handle Args
*
* @param array $stack
* @return string
*/
public static function handleArgs(array $stack): string
{
$traceArgs = '';
$argsCount = count($stack['args']);
for ($i = 0; $i < $argsCount; $i++) {
$type = \gettype($stack['args'][$i]);
switch ($type) {
case 'object':
$traceArgs .= sprintf('Object(%s)', \get_class($stack['args'][$i]));
break;
case 'array':
$traceArgs .= sprintf('Array(%d)', \count($stack['args'][$i]));
break;
case 'string':
$traceArgs .= sprintf('String(%d)', \strlen($stack['args'][$i]));
break;
default:
$traceArgs .= \gettype($stack['args'][$i]);
}
$traceArgs .= ($i !== ($argsCount - 1) ? ',' : '');
}
return $traceArgs;
}
}

View file

@ -7,13 +7,22 @@ use Gloudemans\Shoppingcart\Contracts\Calculator;
class CartCalculator implements Calculator class CartCalculator implements Calculator
{ {
/**
* All purpose getter
*
* @param string $attribute
* @param CartItem $cartItem
* @return float|void
* @phpcs:disable Generic.Metrics.CyclomaticComplexity.TooHigh
*/
public static function getAttribute(string $attribute, CartItem $cartItem) public static function getAttribute(string $attribute, CartItem $cartItem)
{ {
// @phpcs:enable
$decimals = config('cart.format.decimals', 2); $decimals = config('cart.format.decimals', 2);
switch ($attribute) { switch ($attribute) {
case 'discount': case 'discount':
return round($cartItem->price * ($cartItem->getDiscountRate() / 100)*100)/100; return round($cartItem->price * ($cartItem->getDiscountRate() / 100) * 100) / 100;
case 'tax': case 'tax':
return round($cartItem->priceTarget * ($cartItem->taxRate / 100), $decimals); return round($cartItem->priceTarget * ($cartItem->taxRate / 100), $decimals);
case 'priceTax': case 'priceTax':
@ -27,16 +36,15 @@ class CartCalculator implements Calculator
case 'priceTarget': case 'priceTarget':
return round(($cartItem->priceTotal - $cartItem->discountTotal) / $cartItem->qty, $decimals); return round(($cartItem->priceTotal - $cartItem->discountTotal) / $cartItem->qty, $decimals);
case 'taxTotal': case 'taxTotal':
//taxe pour un item multiplié par la quantité // Taxe pour un item multiplié par la quantité.
$unit_price = max($cartItem->price - $cartItem->discount,0); $unit_price = max($cartItem->price - $cartItem->discount, 0);
$unit_tax = round($unit_price * ($cartItem->taxRate / 100), $decimals); $unit_tax = round($unit_price * ($cartItem->taxRate / 100), $decimals);
$taxTotal = round($unit_tax * $cartItem->qty, $decimals); $taxTotal = round($unit_tax * $cartItem->qty, $decimals);
//return round($cartItem->subtotal * ($cartItem->taxRate / 100), $decimals);
return $taxTotal; return $taxTotal;
case 'total': case 'total':
return round($cartItem->subtotal + $cartItem->taxTotal, $decimals); return round($cartItem->subtotal + $cartItem->taxTotal, $decimals);
default: default:
return; return;
} }//end switch
} }
} }

View file

@ -0,0 +1,47 @@
<?php
namespace App\Mail;
use App\Models\Order;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class OrderCanceledConfirmMail extends Mailable
{
use Queueable;
use SerializesModels;
/**
* The Order
*
* @var \App\Models\Order
*/
private $order;
/**
* Create a new message instance.
*
* @param \App\Models\Order $order
*
* @return void
*/
public function __construct(Order $order)
{
$this->order = $order;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
$order = $this->order;
return $this->subject(
"Commande " . config('theme.site_name') . " n°" . $order->reference . " a été annulée."
)->view('mails.order-canceled-confirm', compact('order'));
}
}

View file

@ -3,23 +3,31 @@
namespace App\Mail; namespace App\Mail;
use App\Models\Magasin; use App\Models\Magasin;
use App\Models\Order;
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; use Illuminate\Queue\SerializesModels;
class OrderConfirmAdminMail extends Mailable class OrderConfirmAdminMail extends Mailable
{ {
use Queueable, SerializesModels; use Queueable;
use SerializesModels;
/**
* The Order
*
* @var \App\Models\Order
*/
private $order; private $order;
/** /**
* Create a new message instance. * Create a new message instance.
* *
* @param \App\Models\Order $order
*
* @return void * @return void
*/ */
public function __construct($order) public function __construct(Order $order)
{ {
$this->order = $order; $this->order = $order;
} }
@ -34,6 +42,8 @@ class OrderConfirmAdminMail extends Mailable
$order = $this->order; $order = $this->order;
$magasin = Magasin::find($order->timeslot->magasin->id); $magasin = Magasin::find($order->timeslot->magasin->id);
return $this->subject("Nouvelle Commande - " . config('theme.site_name'))->view('emails.order-confirm-admin', compact('order', 'magasin')); return $this->subject(
"Nouvelle Commande - " . config('theme.site_name')
)->view('emails.order-confirm-admin', compact('order', 'magasin'));
} }
} }

View file

@ -3,23 +3,31 @@
namespace App\Mail; namespace App\Mail;
use App\Models\Magasin; use App\Models\Magasin;
use App\Models\Order;
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; use Illuminate\Queue\SerializesModels;
class OrderConfirmMail extends Mailable class OrderConfirmMail extends Mailable
{ {
use Queueable, SerializesModels; use Queueable;
use SerializesModels;
/**
* The Order
*
* @var \App\Models\Order
*/
private $order; private $order;
/** /**
* Create a new message instance. * Create a new message instance.
* *
* @param \App\Models\Order $order
*
* @return void * @return void
*/ */
public function __construct($order) public function __construct(Order $order)
{ {
$this->order = $order; $this->order = $order;
} }
@ -34,6 +42,8 @@ class OrderConfirmMail extends Mailable
$order = $this->order; $order = $this->order;
$magasin = Magasin::find($order->timeslot->magasin->id); $magasin = Magasin::find($order->timeslot->magasin->id);
return $this->subject("Votre commande - " . config('theme.site_name'))->view('mails.order-confirm', compact('order', 'magasin')); return $this->subject(
"Votre commande - " . config('theme.site_name')
)->view('mails.order-confirm', compact('order', 'magasin'));
} }
} }

View file

@ -3,23 +3,30 @@
namespace App\Mail; namespace App\Mail;
use App\Models\Magasin; use App\Models\Magasin;
use App\Models\Order;
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; use Illuminate\Queue\SerializesModels;
class OrderStatusMail extends Mailable class OrderStatusMail extends Mailable
{ {
use Queueable, SerializesModels; use Queueable;
use SerializesModels;
/**
* The Order
*
* @var \App\Models\Order
*/
private $order; private $order;
/** /**
* Create a new message instance. * Create a new message instance.
* *
* @param \App\Models\Order $order
* @return void * @return void
*/ */
public function __construct($order) public function __construct(Order $order)
{ {
$this->order = $order; $this->order = $order;
} }
@ -31,9 +38,11 @@ class OrderStatusMail extends Mailable
*/ */
public function build() public function build()
{ {
$order = $this->order; $order = $this->order;
$magasin = Magasin::find($order->timeslot->magasin->id); $magasin = Magasin::find($order->timeslot->magasin->id);
return $this->subject("Votre commande - " . config('theme.site_name'))->view('mails.order-status', compact('order', 'magasin')); return $this->subject(
"Votre commande - " . config('theme.site_name')
)->view('mails.order-status', compact('order', 'magasin'));
} }
} }

View file

@ -2,7 +2,6 @@
namespace App\Mail; namespace App\Mail;
use App\Models\Moments;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable; use Illuminate\Mail\Mailable;
@ -10,16 +9,23 @@ use Illuminate\Queue\SerializesModels;
class PasswordResetMail extends Mailable implements ShouldQueue class PasswordResetMail extends Mailable implements ShouldQueue
{ {
use Queueable, SerializesModels; use Queueable;
use SerializesModels;
/**
* Reset token
*
* @var string
*/
private $token; private $token;
/** /**
* Create a new message instance. * Create a new message instance.
* *
* @param string $token
* @return void * @return void
*/ */
public function __construct($token) public function __construct(string $token)
{ {
$this->token = $token; $this->token = $token;
} }
@ -32,6 +38,8 @@ class PasswordResetMail extends Mailable implements ShouldQueue
public function build() public function build()
{ {
$token = $this->token; $token = $this->token;
return $this->subject("Réinitialiser votre accès - " . config('theme.site_name'))->view('mails.password-reset', compact('token')); return $this->subject(
"Réinitialiser votre accès - " . config('theme.site_name')
)->view('mails.password-reset', compact('token'));
} }
} }

View file

@ -2,6 +2,7 @@
namespace App\Mail; namespace App\Mail;
use App\Models\Customers;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable; use Illuminate\Mail\Mailable;
@ -9,19 +10,34 @@ use Illuminate\Queue\SerializesModels;
class RegisterConfirmMail extends Mailable implements ShouldQueue class RegisterConfirmMail extends Mailable implements ShouldQueue
{ {
use Queueable, SerializesModels; use Queueable;
use SerializesModels;
private $customer, $firstname; /**
* target Customer
*
* @var \App\Models\Customers
*/
private $customer;
/**
* Customer's firstname
*
* @var string
*/
private $firstname;
/** /**
* Create a new message instance. * Create a new message instance.
* *
* @param \App\Models\Customers $customer
* @param string|null $firstname
* @return void * @return void
*/ */
public function __construct($customer, $firstname) public function __construct(Customers $customer, string $firstname = null)
{ {
$this->firstname = $firstname; $this->firstname = $firstname;
$this->customer = $customer; $this->customer = $customer;
} }
/** /**
@ -31,7 +47,7 @@ class RegisterConfirmMail extends Mailable implements ShouldQueue
*/ */
public function build() public function build()
{ {
$customer = $this->customer; $customer = $this->customer;
$firstname = $this->firstname; $firstname = $this->firstname;
return $this->subject("Confirmation d'inscription " . config('theme.site_name')) return $this->subject("Confirmation d'inscription " . config('theme.site_name'))
->view('mails.register-ok', compact('customer', 'firstname')); ->view('mails.register-ok', compact('customer', 'firstname'));

View file

@ -2,8 +2,8 @@
namespace App\Mail; namespace App\Mail;
use App\Http\Requests\ContactFormRequest;
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; use Illuminate\Queue\SerializesModels;
@ -15,6 +15,7 @@ class SendContactMail extends Mailable
/** /**
* The form data. * The form data.
* *
* @var \App\Http\Requests\ContactFormRequest
*/ */
protected $data; protected $data;
@ -29,9 +30,10 @@ class SendContactMail extends Mailable
/** /**
* Create a new message instance. * Create a new message instance.
* *
* @param \App\Http\Requests\ContactFormRequest $data
* @return void * @return void
*/ */
public function __construct($data) public function __construct(ContactFormRequest $data)
{ {
$this->data = $data; $this->data = $data;
} }

View file

@ -10,6 +10,11 @@ class CollecteException extends Model
{ {
use HasFactory; use HasFactory;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = ['date', 'comment', 'magasin_id']; protected $fillable = ['date', 'comment', 'magasin_id'];
/** /**
@ -21,11 +26,22 @@ class CollecteException extends Model
'date' => 'date', 'date' => 'date',
]; ];
/**
* Format a date
*
* @param DateTimeInterface $date
* @return string
*/
protected function serializeDate(DateTimeInterface $date) protected function serializeDate(DateTimeInterface $date)
{ {
return $date->format('Y-m-d'); return $date->format('Y-m-d');
} }
/**
* BelongsTo magasin relation
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function magasin() public function magasin()
{ {
return $this->belongsTo(Magasin::class); return $this->belongsTo(Magasin::class);

View file

@ -8,5 +8,4 @@ use Illuminate\Database\Eloquent\Model;
class Content extends Model class Content extends Model
{ {
use HasFactory; use HasFactory;
} }

View file

@ -27,7 +27,11 @@ class Customers extends Authenticatable
protected $guard = 'customer'; protected $guard = 'customer';
//possible additionnals /**
* hasOne salarie relation
*
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function salarie() public function salarie()
{ {
return $this->hasOne(Salarie::class, 'customer_id'); return $this->hasOne(Salarie::class, 'customer_id');

View file

@ -9,9 +9,20 @@ class DiscountType extends Model
{ {
use HasFactory; use HasFactory;
/**
* Indicates if the model should be timestamped.
*
* @var boolean
*/
public $timestamps = false; public $timestamps = false;
public function promotions() { /**
* hasMany promotions relation
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function promotions()
{
return $this->hasMany(Promotion::class, 'discount_type_id'); return $this->hasMany(Promotion::class, 'discount_type_id');
} }
} }

View file

@ -9,5 +9,10 @@ class Faq extends Model
{ {
use HasFactory; use HasFactory;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = ['question', 'answer']; protected $fillable = ['question', 'answer'];
} }

View file

@ -18,11 +18,23 @@ class FoodProduct extends Model
'product_id', 'product_id',
]; ];
public function product() { /**
* BelongsTo product relation
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function product()
{
return $this->belongsTo(Product::class); return $this->belongsTo(Product::class);
} }
public function xmlInco() { /**
* hasOne product relation
*
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function xmlInco()
{
return $this->hasOne(XmlInco::class, 'id', 'no_art'); return $this->hasOne(XmlInco::class, 'id', 'no_art');
} }
} }

View file

@ -9,21 +9,44 @@ class Magasin extends Model
{ {
use HasFactory; use HasFactory;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [ protected $fillable = [
'name', 'address', 'postcode', 'city', 'phone', 'name', 'email_contact', 'email_confirm', 'address', 'postcode', 'city', 'phone',
'latitude', 'longitude', 'latitude', 'longitude',
'gmaps_placeid', 'gmaps_embed_href', 'gmaps_link_href', 'gmaps_placeid', 'gmaps_embed_href', 'gmaps_link_href',
]; ];
public function timeslotSettings() { /**
* hasMany timeslot settings relation
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function timeslotSettings()
{
return $this->hasMany(TimeslotSetting::class); return $this->hasMany(TimeslotSetting::class);
} }
public function collecteExceptions() { /**
* hasMany collecte exceptions relation
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function collecteExceptions()
{
return $this->hasMany(CollecteException::class); return $this->hasMany(CollecteException::class);
} }
public function timeslots() { /**
* hasMany timeslots relation
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function timeslots()
{
return $this->hasMany(Timeslot::class); return $this->hasMany(Timeslot::class);
} }
} }

View file

@ -9,11 +9,23 @@ class OldSlug extends Model
{ {
use HasFactory; use HasFactory;
public function product() { /**
* BelongsTo product relation
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function product()
{
return $this->belongsTo('App\Model\Product', 'product_id'); return $this->belongsTo('App\Model\Product', 'product_id');
} }
public function range() { /**
* BelongsTo range relation
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function range()
{
return $this->belongsTo('App\Model\Range', 'range_id'); return $this->belongsTo('App\Model\Range', 'range_id');
} }
} }

View file

@ -10,34 +10,66 @@ class Order extends Model
use HasFactory; use HasFactory;
/** /**
* use carefully * BelongsToMany products relation
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/ */
public function products() { public function products()
{
return $this->belongsToMany(Product::class, 'order_lines', 'order_id', 'product_id'); return $this->belongsToMany(Product::class, 'order_lines', 'order_id', 'product_id');
} }
//Relations /**
* hasMany lines relation
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function lines() public function lines()
{ {
return $this->hasMany(OrderLine::class); return $this->hasMany(OrderLine::class);
} }
public function status() { /**
* BelongsTo order_status relation
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function status()
{
return $this->belongsTo('App\Models\OrdersStatus', 'status_id'); return $this->belongsTo('App\Models\OrdersStatus', 'status_id');
} }
public function customer() { /**
* BelongsTo customer relation
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function customer()
{
return $this->belongsTo(Customers::class); return $this->belongsTo(Customers::class);
} }
/**
* hasOne timeslot relation
*
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function timeslot() public function timeslot()
{ {
return $this->hasOne(Timeslot::class); return $this->hasOne(Timeslot::class);
} }
//Formattages /**
* Custom Attribute
*
* @return string
*/
public function getFormattedTotalTtcAttribute() public function getFormattedTotalTtcAttribute()
{ {
return $this->attributes['formattedTotalTtc'] = sprintf('%s €', number_format($this->attributes['total'], 2, ',', ' ')); $this->attributes['formattedTotalTtc'] = sprintf(
'%s €',
number_format($this->attributes['total'], 2, ',', ' ')
);
return $this->attributes['formattedTotalTtc'];
} }
} }

View file

@ -9,20 +9,37 @@ class OrderLine extends Model
{ {
use HasFactory; use HasFactory;
//Relations /**
* BelongsTo order relation
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function order() public function order()
{ {
return $this->belongsTo(Order::class); return $this->belongsTo(Order::class);
} }
/**
* BelongsTo product relation
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function product() public function product()
{ {
return $this->belongsTo(Product::class); return $this->belongsTo(Product::class);
} }
//Formattages /**
* Getter for formattedTotalTtc
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function getFormattedTotalTtcAttribute() public function getFormattedTotalTtcAttribute()
{ {
return $this->attributes['formattedTotalTtc'] = sprintf('%s €', number_format($this->attributes['total_ttc'], 2, ',', ' ')); $this->attributes['formattedTotalTtc'] = sprintf(
'%s €',
number_format($this->attributes['total_ttc'], 2, ',', ' ')
);
return $this->attributes['formattedTotalTtc'];
} }
} }

View file

@ -9,10 +9,27 @@ class OrdersStatus extends Model
{ {
use HasFactory; use HasFactory;
/**
* The table associated with the model
*
* @var string
*/
protected $table = "orders_status"; protected $table = "orders_status";
/**
* Indicates if the model should be timestamped.
*
* @var boolean
*/
public $timestamps = false; public $timestamps = false;
public function orders() { /**
* hasMany orders relation
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function orders()
{
return $this->hasMany('App\Models\Order', 'status_id'); return $this->hasMany('App\Models\Order', 'status_id');
} }
} }

View file

@ -6,6 +6,17 @@ use Illuminate\Database\Eloquent\Model;
class PasswordReset extends Model class PasswordReset extends Model
{ {
/**
* The table associated with the model
*
* @var string
*/
protected $table = "password_resets"; protected $table = "password_resets";
/**
* Indicates if the model should be timestamped.
*
* @var boolean
*/
public $timestamps = false; public $timestamps = false;
} }

View file

@ -13,9 +13,6 @@ use Gloudemans\Shoppingcart\Contracts\Buyable;
use Gloudemans\Shoppingcart\CanBeBought; use Gloudemans\Shoppingcart\CanBeBought;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
/**
* @todo : unité de vente/unité de poids devrait être des énums (via table liée ou package enum)
*/
class Product extends Model implements Buyable class Product extends Model implements Buyable
{ {
use HasFactory; use HasFactory;
@ -36,35 +33,67 @@ class Product extends Model implements Buyable
* Store in protected variables instead of attributes * Store in protected variables instead of attributes
* Because those are not set in attributes, Laravel will not try to save it to database * Because those are not set in attributes, Laravel will not try to save it to database
*/ */
/**
* Base Price
*
* @var float
*/
protected $priceHt; protected $priceHt;
/**
* Base Price after discount
*
* @var float
*/
protected $discountedPriceHt; protected $discountedPriceHt;
/**
* Price VAT included
*
* @var float
*/
protected $priceTtc; protected $priceTtc;
/**
* Price after discount VAT included
*
* @var float
*/
protected $discountedPriceTtc; protected $discountedPriceTtc;
/**
* Discount amount
*
* @var float
*/
protected $discountAmount; protected $discountAmount;
/**
* Dsicount rate
*
* @var float
*/
protected $discountRate; protected $discountRate;
/** /**
* init prices on boot * Bootstrap the model and its traits.
*
* @return void
*/ */
protected static function boot() protected static function boot()
{ {
parent::boot(); parent::boot();
//on data retrived from DB // On data retrived from DB.
static::retrieved(function ($model) { static::retrieved(function ($model) {
$model->priceHt = $model->getPriceHtAttribute(); $model->priceHt = $model->getPriceHtAttribute();
$model->priceTtc = $model->getPriceTtcAttribute(); $model->priceTtc = $model->getPriceTtcAttribute();
$model->discountAmount = $model->getDiscountAmountAttribute(); $model->discountAmount = $model->getDiscountAmountAttribute();
$model->discountRate = $model->getDiscountRateAttribute(); $model->discountRate = $model->getDiscountRateAttribute();
$model->discountedPriceHt = $model->getDiscountedPriceHtAttribute(); $model->discountedPriceHt = $model->getDiscountedPriceHtAttribute();
$model->discountedPriceTtc = $model->getDiscountedPriceTtcAttribute(); $model->discountedPriceTtc = $model->getDiscountedPriceTtcAttribute();
}); });
} }
@ -76,10 +105,13 @@ class Product extends Model implements Buyable
* net discounted proice (prix avec taxe et remises) * net discounted proice (prix avec taxe et remises)
*/ */
//Utility to bring prices as a pseudo relation /**
* Utility to bring prices as a pseudo relation
*
* @return array
*/
public function getCalcPrices() public function getCalcPrices()
{ {
//$prices = new Collection();
$prices = array( $prices = array(
'priceHt' => $this->priceHt, 'priceHt' => $this->priceHt,
'discountAmount' => $this->discountAmount, 'discountAmount' => $this->discountAmount,
@ -88,15 +120,16 @@ class Product extends Model implements Buyable
'priceTtc' => $this->priceTtc, 'priceTtc' => $this->priceTtc,
'discountedPriceTtc' => $this->discountedPriceTtc, 'discountedPriceTtc' => $this->discountedPriceTtc,
); );
//$prices->add($cartextendedItem);
return $prices; return $prices;
} }
//gross price
/** /**
* Mutator method to set priceHt's value * Mutator method to set priceHt's value gross price
*
* @param float $value
* @return void
*/ */
public function setPriceHtAttribute($value) public function setPriceHtAttribute(float $value)
{ {
$this->priceHt = $value; $this->priceHt = $value;
} }
@ -106,93 +139,135 @@ class Product extends Model implements Buyable
* Accessor method for priceHt * Accessor method for priceHt
* *
* @author Olivier Legat <olivier.legat@ldc.fr> * @author Olivier Legat <olivier.legat@ldc.fr>
*
* @return float
*/ */
public function getPriceHtAttribute() public function getPriceHtAttribute()
{ {
if(isset($this->priceHt)) { if (isset($this->priceHt)) {
return $this->priceHt; return $this->priceHt;
} else { } else {
//tenir compte de l'unité de facturation et de l'unité de vente (qui doit être stricte) /** Tenir compte de l'unité de facturation et de l'unité de vente (qui doit être stricte)
//si facturation KG et vente piece * si facturation KG et vente piece
// prendre le poids, convertir en KG => pre-requis l'unité de poids doit être un enum * prendre le poids, convertir en KG => pre-requis l'unité de poids doit être un enum
// multiplier le $this->attributes['price'] par les KG * multiplier le $this->attributes['price'] par les KG
//sinon * sinon
// value => value * value => value
*/
if (config('bosettings.sell_unit_management') == "strict") { if (config('bosettings.sell_unit_management') == "strict") {
$calculate = ($this->invoicing_unit == InvoicingUnit::kgm()->value && $this->sell_unit == SellUnit::pce()->value); $calculate = ($this->invoicing_unit == InvoicingUnit::kgm()->value
&& $this->sell_unit == SellUnit::pce()->value);
} else { } else {
$calculate = false; $calculate = false;
} }
if ($calculate) { if ($calculate) {
//weight converter // Weight converter.
$weighted_price = $this->attributes['price'] * ($this->weight * WeightUnit::convert()[$this->weight_unit]); $weighted_price = $this->attributes['price']
return $this->priceHt = round($weighted_price * 1000) / 1000; * ($this->weight * WeightUnit::convert()[$this->weight_unit]);
$this->priceHt = round($weighted_price * 1000) / 1000;
return $this->priceHt;
} else { } else {
//no calculations, alias of db property // No calculations, alias of db property.
return $this->priceHt = $this->attributes['price']; $this->priceHt = $this->attributes['price'];
return $this->priceHt;
} }
} }//end if
} }
//discounted price /**
public function setDiscountedPriceHtAttribute($value) * setter for dicounted price
*
* @param float $value
* @return void
*/
public function setDiscountedPriceHtAttribute(float $value)
{ {
$this->discountedPriceHt = $value; $this->discountedPriceHt = $value;
} }
/**
* getter for discounted price
*
* @return float
*/
public function getDiscountedPriceHtAttribute() public function getDiscountedPriceHtAttribute()
{ {
if (isset($this->discountedPriceHt)) { if (isset($this->discountedPriceHt)) {
return $this->discountedPriceHt; return $this->discountedPriceHt;
} else { } else {
$discountedPriceHt = $this->priceHt - $this->discountAmount; $discountedPriceHt = $this->priceHt - $this->discountAmount;
$roundingdiscountedPriceHt = round($discountedPriceHt * 1000) / 1000; $roundingdiscountedPriceHt = round($discountedPriceHt * 1000) / 1000;
return $this->discountedPriceHt = $roundingdiscountedPriceHt; $this->discountedPriceHt = $roundingdiscountedPriceHt;
return $this->discountedPriceHt;
} }
} }
//net price /**
public function setPriceTtcAttribute($value) * setter for net price
*
* @param float $value
* @return void
*/
public function setPriceTtcAttribute(float $value)
{ {
$this->priceTtc = $value; $this->priceTtc = $value;
} }
/**
* getter for net price
*
* @return float
*/
public function getPriceTtcAttribute() public function getPriceTtcAttribute()
{ {
if (isset($this->priceTtc)) { if (isset($this->priceTtc)) {
return $this->priceTtc; return $this->priceTtc;
} else { } else {
$priceTtc = $this->priceHt * ( 1 + ( $this->tax->rate / 100)); $priceTtc = $this->priceHt * ( 1 + ( $this->tax->rate / 100));
//on travaille avec des centimes puis on redivise par 100 pour avoir des unités monetaires /**
//on augmente la précision à 3 digits, l'affichage formate les prix sur 2 décimales * On travaille avec des centimes puis on redivise par 100 pour avoir des unités monetaires
* on augmente la précision à 3 digits, l'affichage formate les prix sur 2 décimales
*/
$roundingPriceTtc = round($priceTtc * 1000) / 1000; $roundingPriceTtc = round($priceTtc * 1000) / 1000;
return $this->priceTtc = $roundingPriceTtc; $this->priceTtc = $roundingPriceTtc;
return $this->priceTtc;
} }
} }
//net discounted price /**
public function setDiscountedPriceTtcAttribute($value) * setter for net dscounted price
*
* @param float $value
* @return void
*/
public function setDiscountedPriceTtcAttribute(float $value)
{ {
$this->discountedPriceTtc = $value; $this->discountedPriceTtc = $value;
} }
/**
* getter for net dscounted price
*
* @return float
*/
public function getDiscountedPriceTtcAttribute() public function getDiscountedPriceTtcAttribute()
{ {
if (isset($this->discountedPriceTtc)) { if (isset($this->discountedPriceTtc)) {
$showPrice = $this->discountedPriceTtc; $showPrice = $this->discountedPriceTtc;
} else { } else {
$discountedPriceTtc = $this->discountedPriceHt * ( 1 + ( $this->tax->rate / 100)); $discountedPriceTtc = $this->discountedPriceHt * ( 1 + ( $this->tax->rate / 100));
//on travaille avec des centimes puis on redivise par 100 pour avoir des unités monetaires // On travaille avec des centimes puis on redivise par 100 pour avoir des unités monetaires.
$roundingDiscountedPriceTTC = round($discountedPriceTtc * 1000) / 1000; $roundingDiscountedPriceTTC = round($discountedPriceTtc * 1000) / 1000;
$showPrice = $this->discountedPriceTtc = $roundingDiscountedPriceTTC; $this->discountedPriceTtc = $roundingDiscountedPriceTTC;
$showPrice = $this->discountedPriceTtc;
} }
//prix transmis en fonction du setting show_prices // Prix transmis en fonction du setting show_prices.
if (config('bosettings.show_prices_authenticated') == "authenticated") { if (config('bosettings.show_prices_authenticated') == "authenticated") {
{ {
if (Auth::guard('customer')->check()) { if (Auth::guard('customer')->check()) {
return $showPrice; return $showPrice;
} }
} }
} }
if (config('bosettings.show_prices_guest') == "guest") { if (config('bosettings.show_prices_guest') == "guest") {
@ -202,15 +277,25 @@ class Product extends Model implements Buyable
} }
/** /**
* Discount calc * Discount calculators
*/ */
//montant de remise /**
public function setDiscountAmountAttribute($value) * set discoutn amount
*
* @param float $value
* @return void
*/
public function setDiscountAmountAttribute(float $value)
{ {
$this->discountAmount = $value; $this->discountAmount = $value;
} }
/**
* Getter for discount amount
*
* @return float
*/
public function getDiscountAmountAttribute() public function getDiscountAmountAttribute()
{ {
if (isset($this->discountAmount)) { if (isset($this->discountAmount)) {
@ -222,23 +307,34 @@ class Product extends Model implements Buyable
if ($promo_type == 1) { if ($promo_type == 1) {
$discountAmount = $applicablePromotion->discount_value; $discountAmount = $applicablePromotion->discount_value;
} else { } else {
//on augmente la précision à 3 digits, l'affichage formate les prix sur 2 décimales // On augmente la précision à 3 digits, l'affichage formate les prix sur 2 décimales.
$discountAmount = $this->priceHt * ($applicablePromotion->discount_value / 100); $discountAmount = $this->priceHt * ($applicablePromotion->discount_value / 100);
$discountAmount = round($discountAmount * 1000) / 1000; $discountAmount = round($discountAmount * 1000) / 1000;
} }
} else { } else {
$discountAmount = 0; $discountAmount = 0;
} }
return $this->discountAmount = $discountAmount; $this->discountAmount = $discountAmount;
return $this->discountAmount;
} }
} }
//taux de remise /**
public function setDiscountRateAttribute($value) * set discount rate
*
* @param float $value
* @return void
*/
public function setDiscountRateAttribute(float $value)
{ {
$this->discountRate = $value; $this->discountRate = $value;
} }
/**
* get discount rate
*
* @return float
*/
public function getDiscountRateAttribute() public function getDiscountRateAttribute()
{ {
if (isset($this->discountRate)) { if (isset($this->discountRate)) {
@ -248,7 +344,7 @@ class Product extends Model implements Buyable
if (null !== $applicablePromotion) { if (null !== $applicablePromotion) {
$promo_type = $applicablePromotion->discount_type_id; $promo_type = $applicablePromotion->discount_type_id;
if ($promo_type == 1) { if ($promo_type == 1) {
//on veut un pourcentage // On veut un pourcentage.
$discountRate = ($applicablePromotion->discount_value / $this->priceHt) * 100; $discountRate = ($applicablePromotion->discount_value / $this->priceHt) * 100;
} else { } else {
$discountRate = $applicablePromotion->discount_value; $discountRate = $applicablePromotion->discount_value;
@ -256,61 +352,113 @@ class Product extends Model implements Buyable
} else { } else {
$discountRate = 0; $discountRate = 0;
} }
return $this->discountRate = $discountRate; $this->discountRate = $discountRate;
return $this->discountRate;
} }
} }
// //Buyable interface /**
* buyablePrice attribute alias
*
* @param mixed $options
* @return float
*
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
*/
public function getBuyablePrice($options = null) public function getBuyablePrice($options = null)
{ {
// @phpcs:enable
return $this->priceHt; return $this->priceHt;
} }
//Relations /**
* BelongsTo range relation
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function range() public function range()
{ {
return $this->belongsTo('App\Models\Range', 'range_id'); return $this->belongsTo('App\Models\Range', 'range_id');
} }
public function old_slugs() /**
* hasMany old_slugs relation
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function oldSlugs()
{ {
return $this->hasMany('App\Model\OldSlug', 'product_id'); return $this->hasMany('App\Model\OldSlug', 'product_id');
} }
/**
* hasMany stats relation
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function stats() public function stats()
{ {
return $this->hasMany('App\Models\Stat', 'product_id'); return $this->hasMany('App\Models\Stat', 'product_id');
} }
/**
* belongsToMany orders relation
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function orders() public function orders()
{ {
return $this->belongsToMany('App\Models\Order', 'orders_products', 'product_id', 'order_id') return $this->belongsToMany('App\Models\Order', 'orders_products', 'product_id', 'order_id')
->withPivot('quantity'); ->withPivot('quantity');
} }
//relationship to additionnal product info /**
public function additionnalProductInfo($productType) * Pseudo relationship to additionnal product info
*
* @param string $productType
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function additionnalProductInfo(string $productType)
{ {
return $this->$productType; return $this->$productType;
} }
//possible additionnals /**
* hasOne foodProduct relation
*
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function foodProduct() public function foodProduct()
{ {
return $this->hasOne(FoodProduct::class, 'product_id'); return $this->hasOne(FoodProduct::class, 'product_id');
} }
/**
* hasOne anifoodProduct relation
*
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function anifoodProduct() public function anifoodProduct()
{ {
return $this->hasOne(AnifoodProduct::class, 'product_id'); return $this->hasOne(AnifoodProduct::class, 'product_id');
} }
/**
* hasOne toolProduct relation
*
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function toolProduct() public function toolProduct()
{ {
return $this->hasOne(ToolProduct::class, 'product_id'); return $this->hasOne(ToolProduct::class, 'product_id');
} }
/**
* hasOne garmentProduct relation
*
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function garmentProduct() public function garmentProduct()
{ {
return $this->hasOne(GarmentProduct::class, 'product_id'); return $this->hasOne(GarmentProduct::class, 'product_id');
@ -318,13 +466,21 @@ class Product extends Model implements Buyable
//relationship to associated products /**
* belongsToMany products relation
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function products() public function products()
{ {
return $this->belongsToMany(Product::class, 'products_products', 'product_id', 'associated_id'); return $this->belongsToMany(Product::class, 'products_products', 'product_id', 'associated_id');
} }
//offres speciales /**
* belongsToMany promotions relation
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function promotions() public function promotions()
{ {
$now = Carbon::now(); $now = Carbon::now();
@ -333,13 +489,21 @@ class Product extends Model implements Buyable
->whereDate('date_end', '>=', $now); ->whereDate('date_end', '>=', $now);
} }
//taxe /**
* belongsTo tax relation
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function tax() public function tax()
{ {
return $this->belongsTo(TaxRate::class, 'tax_rate_id'); return $this->belongsTo(TaxRate::class, 'tax_rate_id');
} }
//tags /**
* belongsToMany tags relation
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function tags() public function tags()
{ {
return $this->belongsToMany(Tag::class); return $this->belongsToMany(Tag::class);

View file

@ -18,7 +18,13 @@ class ProductType extends Model
'product_id', 'product_id',
]; ];
public function product() { /**
* BelongsTo product relation
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function product()
{
return $this->belongsTo(Product::class); return $this->belongsTo(Product::class);
} }
} }

View file

@ -8,5 +8,6 @@ use Illuminate\Database\Eloquent\Model;
class ProductsProducts extends Model class ProductsProducts extends Model
{ {
use HasFactory; use HasFactory;
//useless model it seems
// Useless model it seems.
} }

View file

@ -19,11 +19,21 @@ class Promotion extends Model
'date_end' => 'datetime', 'date_end' => 'datetime',
]; ];
/**
* BelongsToMany products relation
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function products() public function products()
{ {
return $this->belongsToMany(Product::class); return $this->belongsToMany(Product::class);
} }
/**
* BelongsTo discountType relation
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function discountType() public function discountType()
{ {
return $this->belongsTo(DiscountType::class, 'discount_type_id'); return $this->belongsTo(DiscountType::class, 'discount_type_id');

View file

@ -9,11 +9,23 @@ class Range extends Model
{ {
use HasFactory; use HasFactory;
public function products() { /**
* hasMany customer relation
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function products()
{
return $this->hasMany('App\Models\Product', 'range_id'); return $this->hasMany('App\Models\Product', 'range_id');
} }
public function old_slugs() { /**
return $this->hasMany('App\Model\OldSlug', 'ranges'); * hasMany old_slugs relation
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function oldSlugs()
{
return $this->hasMany('App\Model\OldSlug', 'range_id');
} }
} }

View file

@ -22,8 +22,13 @@ class Salarie extends Model
'code' 'code'
]; ];
/**
public function customer() { * BelongsTo customer relation
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function customer()
{
return $this->belongsTo(Customers::class); return $this->belongsTo(Customers::class);
} }
} }

View file

@ -19,7 +19,13 @@ class Slide extends Model
'date_end' => 'datetime', 'date_end' => 'datetime',
]; ];
public function slider() { /**
* BelongsTo slider relation
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function slider()
{
return $this->belongsTo(Slider::class); return $this->belongsTo(Slider::class);
} }
} }

View file

@ -10,11 +10,21 @@ class Slider extends Model
{ {
use HasFactory; use HasFactory;
/**
* hasMany slides relation
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function slides() public function slides()
{ {
return $this->hasMany(Slide::class, 'slider_id')->orderBy('order', 'ASC'); return $this->hasMany(Slide::class, 'slider_id')->orderBy('order', 'ASC');
} }
/**
* filtered slides relation by showable date
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function showableSlides() public function showableSlides()
{ {
$now = Carbon::now(); $now = Carbon::now();
@ -26,6 +36,5 @@ class Slider extends Model
$q->whereDate('date_end', '>=', $now) $q->whereDate('date_end', '>=', $now)
->orWhereNull('date_end'); ->orWhereNull('date_end');
}); });
} }
} }

View file

@ -9,7 +9,13 @@ class Stat extends Model
{ {
use HasFactory; use HasFactory;
public function product() { /**
* BelongsTo product relation
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function product()
{
return $this->belongsTo('App\Models\Product', 'product_id'); return $this->belongsTo('App\Models\Product', 'product_id');
} }
} }

View file

@ -9,8 +9,18 @@ class Tag extends Model
{ {
use HasFactory; use HasFactory;
/**
* Indicates if the model should be timestamped.
*
* @var boolean
*/
public $timestamps = false; public $timestamps = false;
/**
* belongsToMany products relation
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function products() public function products()
{ {
return $this->belongsToMany(Product::class); return $this->belongsToMany(Product::class);

View file

@ -9,9 +9,20 @@ class TaxRate extends Model
{ {
use HasFactory; use HasFactory;
/**
* Indicates if the model should be timestamped.
*
* @var boolean
*/
public $timestamps = false; public $timestamps = false;
public function products() { /**
* hasMany products relation
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function products()
{
return $this->hasMany(Product::class, 'tax_rate_id'); return $this->hasMany(Product::class, 'tax_rate_id');
} }
} }

View file

@ -9,15 +9,30 @@ class Timeslot extends Model
{ {
use HasFactory; use HasFactory;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [ protected $fillable = [
'order_id', 'magasin_id' 'order_id', 'magasin_id'
]; ];
/**
* BelongsTo order relation
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function order() public function order()
{ {
return $this->belongsTo(Order::class); return $this->belongsTo(Order::class);
} }
/**
* BelongsTo magasin relation
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function magasin() public function magasin()
{ {
return $this->belongsTo(Magasin::class); return $this->belongsTo(Magasin::class);

View file

@ -9,6 +9,11 @@ class TimeslotSetting extends Model
{ {
use HasFactory; use HasFactory;
/**
* BelongsTo magasin relation
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function magasin() public function magasin()
{ {
return $this->belongsTo(Magasin::class); return $this->belongsTo(Magasin::class);

View file

@ -2,14 +2,14 @@
namespace App\Models; namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable; use Illuminate\Notifications\Notifiable;
class User extends Authenticatable class User extends Authenticatable
{ {
use HasFactory, Notifiable; use HasFactory;
use Notifiable;
/** /**
* The attributes that are mass assignable. * The attributes that are mass assignable.
@ -44,7 +44,13 @@ class User extends Authenticatable
'email_verified_at' => 'datetime', 'email_verified_at' => 'datetime',
]; ];
public function orders() { /**
* hasMany order relation
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function orders()
{
return $this->hasMany('App\Models\Order', 'user_id'); return $this->hasMany('App\Models\Order', 'user_id');
} }
} }

View file

@ -6,13 +6,17 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
use Illuminate\Contracts\Filesystem\Filesystem; use Illuminate\Contracts\Filesystem\Filesystem;
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
class XmlInco extends Model class XmlInco extends Model
{ {
use HasFactory; use HasFactory;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [ protected $fillable = [
'id', 'id',
'no_art', 'no_art',
@ -33,6 +37,11 @@ class XmlInco extends Model
'picture', 'picture',
]; ];
/**
* The attributes that should be cast to native types.
*
* @var array
*/
protected $casts = [ protected $casts = [
'picture' => 'array', 'picture' => 'array',
'nutritional_values' => 'array', 'nutritional_values' => 'array',
@ -45,6 +54,11 @@ class XmlInco extends Model
*/ */
protected $disk = 'inco'; protected $disk = 'inco';
/**
* Storage path
*
* @var string
*/
protected $imagesPath = 'images'; protected $imagesPath = 'images';
/** /**
@ -58,10 +72,13 @@ class XmlInco extends Model
/** /**
* retrieve a collection of medias * retrieve a collection of medias
*
* @return Collection
*/ */
public function getMediasAttribute() { public function getMediasAttribute()
{
/** @var Filesystem */ /** @var Filesystem */
$disk = $this->getDisk(); $disk = $this->getDisk();
$files = $disk->files($this->imagesPath); $files = $disk->files($this->imagesPath);
$collFiles = new Collection(); $collFiles = new Collection();
@ -74,7 +91,7 @@ class XmlInco extends Model
if (!in_array($pi, array($this->id))) { if (!in_array($pi, array($this->id))) {
continue; continue;
} }
$image = base64_encode($disk->get($file)); $image = base64_encode($disk->get($file));
$element = array( $element = array(
"filename" => $pi, "filename" => $pi,
"imgdata" => $image "imgdata" => $image
@ -94,143 +111,183 @@ class XmlInco extends Model
return Storage::disk($this->disk); return Storage::disk($this->disk);
} }
/**
* getter
*
* @return string
*/
public function getNiceStringAttribute() public function getNiceStringAttribute()
{ {
return sprintf('%s - %s', $this->id, $this->descriptif); return sprintf('%s - %s', $this->id, $this->descriptif);
} }
/**
* update local info
*
* @return void
*/
public function updateLocalProductInfo() public function updateLocalProductInfo()
{ {
$foodProduct = FoodProduct::where('no_art', $this->id)->first(); $foodProduct = FoodProduct::where('no_art', $this->id)->first();
if (!empty($foodProduct)) { if (!empty($foodProduct)) {
//info produits à suggerer lors de l'édition /** Info produits à suggerer lors de l'édition
// this->descriptif (doit aller dans la table products) * this->descriptif (doit aller dans la table products)
// $table->text('preparation')->nullable(); => $this->conseil_prepa * $table->text('preparation')->nullable(); => $this->conseil_prepa
// $table->text('selling_argument')->nullable(); => $this->arg_vente * $table->text('selling_argument')->nullable(); => $this->arg_vente
* infos produit maj automatique
//infos produit maj automatique */
$foodProduct->ingredients = $this->lst_ing; $foodProduct->ingredients = $this->lst_ing;
$foodProduct->allergens = $this->lib_allergene; $foodProduct->allergens = $this->lib_allergene;
//$foodProduct->servings = $this->nb_portion; // problem les types de correspondent pas numeric = string (exemple this->nb_portion = '1/2') /** Les types de correspondent pas
* numeric ($foodProduct->servings) = string (exemple this->nb_portion = '1/2').
*/
$nutri_values = $this->nutritional_values; $nutri_values = $this->nutritional_values;
if (!empty($nutri_values)) { if (!empty($nutri_values)) {
//maj des info nutri locales // Maj des info nutri locales.
//pour la ref // Pour la ref.
$foodProduct->nv_ref_weight_g = $nutri_values["taille_ref"]; $foodProduct->nv_ref_weight_g = $nutri_values["taille_ref"];
$foodProduct->nv_kj = $nutri_values["val_energ_kj_r"]; //Energie Kj // Energie Kj.
$foodProduct->nv_kcal = $nutri_values["val_energ_kcal_r"]; //Energie Kcal $foodProduct->nv_kj = $nutri_values["val_energ_kj_r"];
$foodProduct->nv_fat_g = $nutri_values["mat_grass_r"]; //graisses // Energie Kcal.
$foodProduct->nv_sat_fat_g = $nutri_values["ags_r"]; //dont acides gras saturés $foodProduct->nv_kcal = $nutri_values["val_energ_kcal_r"];
$foodProduct->nv_carb_g = $nutri_values["glucides_r"]; //Glucides // Graisses.
$foodProduct->nv_sugar_g = $nutri_values["sucre_r"]; //dont sucres $foodProduct->nv_fat_g = $nutri_values["mat_grass_r"];
$foodProduct->nv_fiber_g = $nutri_values["fib_alim_r"]; //fibres alimentaires // Dont acides gras saturés.
$foodProduct->nv_protein_g = $nutri_values["proteine_r"]; //protéines $foodProduct->nv_sat_fat_g = $nutri_values["ags_r"];
$foodProduct->nv_salt_g = $nutri_values["sel_r"]; //sel // Glucides.
$foodProduct->nv_carb_g = $nutri_values["glucides_r"];
// Dont sucres.
$foodProduct->nv_sugar_g = $nutri_values["sucre_r"];
// Fibres alimentaires.
$foodProduct->nv_fiber_g = $nutri_values["fib_alim_r"];
// Protéines.
$foodProduct->nv_protein_g = $nutri_values["proteine_r"];
// Sel.
$foodProduct->nv_salt_g = $nutri_values["sel_r"];
// $foodProduct-> = $nutri_values["sodium_r"]; /** Autres valeurs dispos
// $foodProduct-> = $nutri_values["ener_e14_r"]; * $nutri_values["sodium_r"];
// $foodProduct-> = $nutri_values["fruits_r"]; * $nutri_values["ener_e14_r"];
// $foodProduct-> = $nutri_values["fruits_coque_sech_r"]; * $nutri_values["fruits_r"];
// $foodProduct-> = $nutri_values["ener_kjo_r"]; * $nutri_values["fruits_coque_sech_r"];
// $foodProduct-> = $nutri_values["fatsat_r"]; * $nutri_values["ener_kjo_r"];
// $foodProduct-> = $nutri_values["choval_r"]; * $nutri_values["fatsat_r"];
// $foodProduct-> = $nutri_values["sugar_r"]; * $nutri_values["choval_r"];
// $foodProduct-> = $nutri_values["fibtg_r"]; * $nutri_values["sugar_r"];
// $foodProduct-> = $nutri_values["pro_r"]; * $nutri_values["fibtg_r"];
// $foodProduct-> = $nutri_values["salteq_r"]; * $nutri_values["pro_r"];
* $nutri_values["salteq_r"];
*/
// Valeurs nutritionnelles par portion.
// Taille portion en grammes.
$foodProduct->nv_serving_size_g = $nutri_values["taille_port"];
// Energie Kj.
$foodProduct->nv_serving_kj = $nutri_values["val_energ_kj_p"];
// Energie Kcal.
$foodProduct->nv_serving_kcal = $nutri_values["val_energ_kcal_p"];
// Graisses.
$foodProduct->nv_serving_fat_g = $nutri_values["mat_grass_p"];
// Dont acides gras saturés.
$foodProduct->nv_serving_sat_fat_g = $nutri_values["ags_p"];
// Glucides.
$foodProduct->nv_serving_carb_g = $nutri_values["glucides_p"];
// Dont sucres.
$foodProduct->nv_serving_sugar_g = $nutri_values["sucre_p"];
// Fibres alimentaires.
$foodProduct->nv_serving_fiber_g = $nutri_values["fib_alim_p"];
// Protéines.
$foodProduct->nv_serving_protein_g = $nutri_values["proteine_p"];
// Sel.
$foodProduct->nv_serving_salt_g = $nutri_values["sel_p"];
/**
* autres valeurs disponibles
* $nutri_values["sodium_p"];
* $nutri_values["fruits_p"];
*/
//valeurs nutritionnelles par portion // Apports journaliers.
$foodProduct->nv_serving_size_g = $nutri_values["taille_port"]; //taille portion en grammes // Energie % recommandé.
$foodProduct->nv_serving_kj = $nutri_values["val_energ_kj_p"]; //Energie Kj $foodProduct->nv_daily_energy = $nutri_values["pourcent_apport_ref_kjo_r"];
$foodProduct->nv_serving_kcal = $nutri_values["val_energ_kcal_p"]; //Energie Kcal // Graisses.
$foodProduct->nv_serving_fat_g = $nutri_values["mat_grass_p"]; //graisses $foodProduct->nv_daily_fat = $nutri_values["pourcent_apport_ref_fat_r"];
$foodProduct->nv_serving_sat_fat_g = $nutri_values["ags_p"]; //dont acides gras saturés // Dont acides gras saturés.
$foodProduct->nv_serving_carb_g = $nutri_values["glucides_p"]; //Glucides $foodProduct->nv_daily_sat_fat = $nutri_values["pourcent_apport_ref_fatsat_r"];
$foodProduct->nv_serving_sugar_g = $nutri_values["sucre_p"]; //dont sucres // Glucides.
$foodProduct->nv_serving_fiber_g = $nutri_values["fib_alim_p"]; //fibres alimentaires $foodProduct->nv_daily_carb = $nutri_values["pourcent_apport_ref_choval_r"];
$foodProduct->nv_serving_protein_g = $nutri_values["proteine_p"]; //protéines // Dont sucres.
$foodProduct->nv_serving_salt_g = $nutri_values["sel_p"]; //sel $foodProduct->nv_daily_sugar = $nutri_values["pourcent_apport_ref_sugar_r"];
// Fibres alimentaires.
$foodProduct->nv_daily_fiber = $nutri_values["pourcent_apport_ref_fibtg_r"];
// Protéines.
$foodProduct->nv_daily_protein = $nutri_values["pourcent_apport_ref_pro_r"];
// Sel.
$foodProduct->nv_daily_salt = $nutri_values["pourcent_apport_ref_salteq_r"];
// $foodProduct-> = $nutri_values["sodium_p"]; // Autre valeur dispo $nutri_values["pourcent_apport_ref_e14_r"] .
// $foodProduct-> = $nutri_values["fruits_p"]; // Nutriscore.
//apports journaliers
$foodProduct->nv_daily_energy = $nutri_values["pourcent_apport_ref_kjo_r"]; //Energie % recommandé
$foodProduct->nv_daily_fat = $nutri_values["pourcent_apport_ref_fat_r"]; //graisses
$foodProduct->nv_daily_sat_fat = $nutri_values["pourcent_apport_ref_fatsat_r"]; //dont acides gras saturés
$foodProduct->nv_daily_carb = $nutri_values["pourcent_apport_ref_choval_r"]; //Glucides
$foodProduct->nv_daily_sugar = $nutri_values["pourcent_apport_ref_sugar_r"]; //dont sucres
$foodProduct->nv_daily_fiber = $nutri_values["pourcent_apport_ref_fibtg_r"]; //fibres alimentaires
$foodProduct->nv_daily_protein = $nutri_values["pourcent_apport_ref_pro_r"]; //protéines
$foodProduct->nv_daily_salt = $nutri_values["pourcent_apport_ref_salteq_r"]; //sel
//$foodProduct-> = $nutri_values["pourcent_apport_ref_e14_r"];
//nutriscore
$foodProduct->nutriscore = $nutri_values["classement"]; $foodProduct->nutriscore = $nutri_values["classement"];
/**
//Infos n'ayant pas de mapping * Infos n'ayant pas de mapping
// $foodProduct-> = $nutri_values["val_energ_kj_nut"]; *
// $foodProduct-> = $nutri_values["val_energ_kcal_nut"]; * $nutri_values["val_energ_kj_nut"];
// $foodProduct-> = $nutri_values["mat_grass_nut"]; * $nutri_values["val_energ_kcal_nut"];
// $foodProduct-> = $nutri_values["ags_nut"]; * $nutri_values["mat_grass_nut"];
// $foodProduct-> = $nutri_values["glucides_nut"]; * $nutri_values["ags_nut"];
// $foodProduct-> = $nutri_values["sucre_nut"]; * $nutri_values["glucides_nut"];
// $foodProduct-> = $nutri_values["sucre_r"]; * $nutri_values["sucre_nut"];
// $foodProduct-> = $nutri_values["fib_alim_nut"]; * $nutri_values["sucre_r"];
// $foodProduct-> = $nutri_values["proteine_nut"]; * $nutri_values["fib_alim_nut"];
// $foodProduct-> = $nutri_values["sel_nut"]; * $nutri_values["proteine_nut"];
// $foodProduct-> = $nutri_values["apport_ref"]; * $nutri_values["sel_nut"];
// $foodProduct-> = $nutri_values["fruits_coque_sech_p"]; * $nutri_values["apport_ref"];
// $foodProduct-> = $nutri_values["ener_e14_p"]; * $nutri_values["fruits_coque_sech_p"];
// $foodProduct-> = $nutri_values["pourcent_apport_ref_e14_p"]; * $nutri_values["ener_e14_p"];
// $foodProduct-> = $nutri_values["ener_kjo_p"]; * $nutri_values["pourcent_apport_ref_e14_p"];
// $foodProduct-> = $nutri_values["pourcent_apport_ref_kjo_p"]; * $nutri_values["ener_kjo_p"];
// $foodProduct-> = $nutri_values["fat_p"]; * $nutri_values["pourcent_apport_ref_kjo_p"];
// $foodProduct-> = $nutri_values["pourcent_apport_ref_fat_p"]; * $nutri_values["fat_p"];
// $foodProduct-> = $nutri_values["fatsat_p"]; * $nutri_values["pourcent_apport_ref_fat_p"];
// $foodProduct-> = $nutri_values["pourcent_apport_ref_fatsat_p"]; * $nutri_values["fatsat_p"];
// $foodProduct-> = $nutri_values["choval_p"]; * $nutri_values["pourcent_apport_ref_fatsat_p"];
// $foodProduct-> = $nutri_values["pourcent_apport_ref_choval_p"]; * $nutri_values["choval_p"];
// $foodProduct-> = $nutri_values["sugar_p"]; * $nutri_values["pourcent_apport_ref_choval_p"];
// $foodProduct-> = $nutri_values["pourcent_apport_ref_sugar_p"]; * $nutri_values["sugar_p"];
// $foodProduct-> = $nutri_values["fibtg_p"]; * $nutri_values["pourcent_apport_ref_sugar_p"];
// $foodProduct-> = $nutri_values["pourcent_apport_ref_fibtg_p"]; * $nutri_values["fibtg_p"];
// $foodProduct-> = $nutri_values["pro_p"]; * $nutri_values["pourcent_apport_ref_fibtg_p"];
// $foodProduct-> = $nutri_values["pourcent_apport_ref_pro_p"]; * $nutri_values["pro_p"];
// $foodProduct-> = $nutri_values["salteq_p"]; * $nutri_values["pourcent_apport_ref_pro_p"];
// $foodProduct-> = $nutri_values["pourcent_apport_ref_salteq_p"]; * $nutri_values["salteq_p"];
// $foodProduct-> = $nutri_values["apport_port"]; * $nutri_values["pourcent_apport_ref_salteq_p"];
// $foodProduct-> = $nutri_values["part_p"]; * $nutri_values["apport_port"];
// $foodProduct-> = $nutri_values["part_g"]; * $nutri_values["part_p"];
// $foodProduct-> = $nutri_values["part_l"]; * $nutri_values["part_g"];
// $foodProduct-> = $nutri_values["p_sur_l"]; * $nutri_values["part_l"];
// $foodProduct-> = $nutri_values["pourcent_ags"]; * $nutri_values["p_sur_l"];
// $foodProduct-> = $nutri_values["pourcent_agi"]; * $nutri_values["pourcent_ags"];
// $foodProduct-> = $nutri_values["pourcent_ss"]; * $nutri_values["pourcent_agi"];
// $foodProduct-> = $nutri_values["pourcent_amidon"]; * $nutri_values["pourcent_ss"];
// $foodProduct-> = $nutri_values["composante_n"]; * $nutri_values["pourcent_amidon"];
// $foodProduct-> = $nutri_values["composante_p"]; * $nutri_values["composante_n"];
// $foodProduct-> = $nutri_values["pourcent_fruits"]; * $nutri_values["composante_p"];
// $foodProduct-> = $nutri_values["mat_grass_r_prec"]; * $nutri_values["pourcent_fruits"];
// $foodProduct-> = $nutri_values["ags_r_prec"]; * $nutri_values["mat_grass_r_prec"];
// $foodProduct-> = $nutri_values["glucides_r_prec"]; * $nutri_values["ags_r_prec"];
// $foodProduct-> = $nutri_values["sucre_r_prec"]; * $nutri_values["glucides_r_prec"];
// $foodProduct-> = $nutri_values["fib_alim_r_prec"]; * $nutri_values["sucre_r_prec"];
// $foodProduct-> = $nutri_values["proteine_r_prec"]; * $nutri_values["fib_alim_r_prec"];
// $foodProduct-> = $nutri_values["sel_r_prec"]; * $nutri_values["proteine_r_prec"];
// $foodProduct-> = $nutri_values["sodium_r_prec"]; * $nutri_values["sel_r_prec"];
// $foodProduct-> = $nutri_values["fruits_r_prec"]; * $nutri_values["sodium_r_prec"];
// $foodProduct-> = $nutri_values["fruits_coque_sech_r_prec"]; * $nutri_values["fruits_r_prec"];
// $foodProduct-> = $nutri_values["score_nutri"]; * $nutri_values["fruits_coque_sech_r_prec"];
} * $nutri_values["score_nutri"];
*/
}//end if
$foodProduct->save(); $foodProduct->save();
} }//end if
} }
} }

View file

@ -2,8 +2,6 @@
namespace App\Policies; namespace App\Policies;
use App\Models\Customers;
use App\Models\User;
use App\Models\Product; use App\Models\Product;
use Illuminate\Auth\Access\HandlesAuthorization; use Illuminate\Auth\Access\HandlesAuthorization;
use Illuminate\Auth\Access\Response; use Illuminate\Auth\Access\Response;
@ -20,18 +18,23 @@ class ProductPolicy
*/ */
public function __construct() public function __construct()
{ {
//
} }
/** /**
* $user is a App\Models\User or a App\Models\Customers * @param App\Models\User|App\Models\Customers $user
* @param \App\Models\Product $product
*
* @return \Illuminate\Auth\Access\Response
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
*/ */
public function addToCart($user = null, Product $product) { public function addToCart($user, Product $product)
{
// phpcs:enable
$now = Carbon::now(); $now = Carbon::now();
if($product->orderable_start === null or $product->orderable_start <= $now) { if ($product->orderable_start === null or $product->orderable_start <= $now) {
//on est entré dans la période commandable ou c'est commandable depuis toujours // On est entré dans la période commandable ou c'est commandable depuis toujours.
if($product->orderable_end === null or $product->orderable_end >= $now) { if ($product->orderable_end === null or $product->orderable_end >= $now) {
//il n'y a pas de limite dans le temps ou elle n'est pas encore passée // Il n'y a pas de limite dans le temps ou elle n'est pas encore passée.
return Response::allow(); return Response::allow();
} }
return Response::deny('Ce produit n\'est pas disponible pour le moment'); return Response::deny('Ce produit n\'est pas disponible pour le moment');

Some files were not shown because too many files have changed in this diff Show more