Compare commits
36 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
972ce0cf6f | ||
|
|
033ce42b42 | ||
|
|
481b39d856 | ||
|
|
262ea2871c | ||
|
|
8ba5feff18 | ||
|
|
a247dba2b2 | ||
|
|
4873cd7fc2 | ||
|
|
69ce45d5cb | ||
|
|
a6d0e1ae2d | ||
|
|
d8464a34ac | ||
|
|
4359c85b8c | ||
|
|
7ba2c3b2fe | ||
|
|
1f235efebe | ||
|
|
6eef17a390 | ||
|
|
5872d670fe | ||
|
|
0c22695c77 | ||
|
|
1aceb54b0e | ||
|
|
e9085b681a | ||
|
|
e8d1669bae | ||
|
|
9e7fad8ebb | ||
|
|
6b3145eb8f | ||
|
|
30e53b81b3 | ||
|
|
1cca69c933 | ||
|
|
11dad23fe2 | ||
|
|
9b5a68c121 | ||
|
|
6f14d1d975 | ||
|
|
039587d1e3 | ||
|
|
825d47797b | ||
|
|
e1820ba1ac | ||
|
|
b72988b20c | ||
|
|
3000e1663f | ||
|
|
d48c9aa99b | ||
|
|
b7c0e12429 | ||
|
|
2d65de573c | ||
|
|
4bbb98e3c8 | ||
|
|
80d426f470 |
633 changed files with 57910 additions and 48983 deletions
|
|
@ -11,8 +11,5 @@ trim_trailing_whitespace = true
|
|||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.vue]
|
||||
indent_size = 2
|
||||
|
||||
[*.{yml,yaml}]
|
||||
indent_size = 2
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ APP_ENV=local
|
|||
APP_KEY=
|
||||
APP_DEBUG=true
|
||||
APP_URL=
|
||||
APP_THEME=basic
|
||||
|
||||
LOG_CHANNEL=daily
|
||||
LOG_LEVEL=debug
|
||||
|
|
@ -32,8 +33,6 @@ MAIL_FROM_NAME="${APP_NAME}"
|
|||
MAIL_LIST_SERVICEWEB=equipe.web@ldc.fr
|
||||
MAIL_LIST_INVALIDINCO=equipe.web@ldc.fr,vincent.pierre@ldc.fr,christelle.manceau@ldc.fr
|
||||
|
||||
# Sentry
|
||||
SENTRY_LARAVEL_DSN=
|
||||
# CRM
|
||||
CRM_ENDPOINT=https://ldcldccrm:K5cJmTsG@dev.ldc-crm.fr
|
||||
# Service boutique
|
||||
|
|
|
|||
|
|
@ -1,41 +0,0 @@
|
|||
{
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es2021": true
|
||||
},
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:vue/vue3-strongly-recommended",
|
||||
"@vue/eslint-config-typescript"
|
||||
],
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts", "*.vue"],
|
||||
"rules": {
|
||||
"no-undef": "off"
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["*.vue"],
|
||||
"rules": {
|
||||
"indent": "off"
|
||||
}
|
||||
}
|
||||
],
|
||||
"parser": "vue-eslint-parser",
|
||||
"parserOptions": {
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"ecmaVersion": "latest",
|
||||
"sourceType": "module"
|
||||
},
|
||||
"plugins": ["vue", "@typescript-eslint"],
|
||||
"ignorePatterns": ["webpack.mix.js", "**/vendor/*.js", "**/vendor/**/*.js"],
|
||||
"rules": {
|
||||
"indent": ["error", 4, { "SwitchCase": 1 }],
|
||||
"linebreak-style": ["error", "unix"],
|
||||
"quotes": ["error", "double"],
|
||||
"semi": ["error", "always"],
|
||||
"vue/script-indent": ["error", 2, { "baseIndent": 0, "switchCase": 1 }],
|
||||
"vue/one-component-per-file": "off"
|
||||
}
|
||||
}
|
||||
21
.gitignore
vendored
21
.gitignore
vendored
|
|
@ -1,29 +1,22 @@
|
|||
/node_modules
|
||||
/public/hot
|
||||
/public/storage
|
||||
/public/assets/*
|
||||
/public/js/*
|
||||
/public/css/*
|
||||
/public/fonts/*
|
||||
/public/content/*
|
||||
/public/images/*
|
||||
/public/cache/*
|
||||
/public/uploads/*
|
||||
mix-manifest.json
|
||||
/public/images/content
|
||||
/public/images/gammes
|
||||
/public/images/produits
|
||||
/public/images/slides
|
||||
/public/b-o/
|
||||
/public/mix-manifest.json
|
||||
/storage/*.key
|
||||
/storage/framework/laravel-excel/*
|
||||
/vendor
|
||||
.env
|
||||
.env.backup
|
||||
.env.dev
|
||||
.env.prod
|
||||
.phpunit.result.cache
|
||||
docker-compose.override.yml
|
||||
Homestead.json
|
||||
Homestead.yaml
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
workspace.code-workspace
|
||||
auth.json
|
||||
.vscode
|
||||
# IGNORE THEME SUBMODULES CHANGES
|
||||
resources/theme
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
image: $CI_REGISTRY/service-web-lab/ldc-web-images-docker/ldcweb-qa:php7.3-1.0
|
||||
|
||||
stages:
|
||||
- Security
|
||||
- CodingStandards
|
||||
- Builds
|
||||
|
||||
composer-security:
|
||||
stage: Security
|
||||
image: $CI_REGISTRY/service-web-lab/ldc-web-images-docker/ldcweb-qa:php7.3-1.0
|
||||
script:
|
||||
- local-php-security-checker --format=json --path=./composer.lock > composer-security-checker-report.json
|
||||
artifacts:
|
||||
|
|
@ -14,13 +14,9 @@ composer-security:
|
|||
paths:
|
||||
- composer-security-checker-report.json
|
||||
allow_failure: true
|
||||
needs: []
|
||||
|
||||
npm-security:
|
||||
stage: Security
|
||||
image: node:17.9.1
|
||||
before_script:
|
||||
- npm install --location=global audit-ci@^6
|
||||
script:
|
||||
- audit-ci -p npm -o json > npm-security-checker-report.json
|
||||
artifacts:
|
||||
|
|
@ -29,14 +25,12 @@ npm-security:
|
|||
paths:
|
||||
- npm-security-checker-report.json
|
||||
allow_failure: true
|
||||
needs: []
|
||||
|
||||
phpcs:
|
||||
stage: CodingStandards
|
||||
image: $CI_REGISTRY/service-web-lab/ldc-web-images-docker/ldcweb-qa:php7.3-1.0
|
||||
before_script:
|
||||
- composer config gitlab-token.gitlab.com $CI_DEPLOY_USER $CI_DEPLOY_PASSWORD
|
||||
- composer install --no-scripts
|
||||
- composer install
|
||||
cache:
|
||||
paths:
|
||||
- vendor/
|
||||
|
|
@ -49,70 +43,4 @@ phpcs:
|
|||
- phpcs-report.xml
|
||||
reports:
|
||||
junit: phpcs-report.xml
|
||||
allow_failure: false
|
||||
needs:
|
||||
- composer-security
|
||||
- npm-security
|
||||
|
||||
eslint:
|
||||
stage: CodingStandards
|
||||
image: node:17.9.1
|
||||
before_script:
|
||||
- npm install
|
||||
cache:
|
||||
paths:
|
||||
- node_modules/
|
||||
script:
|
||||
- npm run eslint-ci --silent 2>/dev/null 1> eslint-report.xml
|
||||
artifacts:
|
||||
when: on_failure
|
||||
expose_as: 'eslint'
|
||||
paths:
|
||||
- eslint-report.xml
|
||||
reports:
|
||||
junit: eslint-report.xml
|
||||
allow_failure: false
|
||||
needs:
|
||||
- composer-security
|
||||
- npm-security
|
||||
|
||||
stylelint:
|
||||
stage: CodingStandards
|
||||
image: node:17.9.1
|
||||
before_script:
|
||||
- npm install
|
||||
cache:
|
||||
paths:
|
||||
- node_modules/
|
||||
script:
|
||||
- npm run stylelint-ci --silent 2>/dev/null 1> stylelint-report.json
|
||||
artifacts:
|
||||
when: on_failure
|
||||
expose_as: 'stylelint'
|
||||
paths:
|
||||
- stylelint-report.json
|
||||
allow_failure: false
|
||||
needs:
|
||||
- composer-security
|
||||
- npm-security
|
||||
|
||||
front-build:
|
||||
stage: Builds
|
||||
image: node:17.9.1
|
||||
before_script:
|
||||
- npm install
|
||||
cache:
|
||||
paths:
|
||||
- node_modules/
|
||||
script:
|
||||
- npm run prod > front-build-report.json
|
||||
artifacts:
|
||||
when: on_failure
|
||||
expose_as: 'front-build-report'
|
||||
paths:
|
||||
- front-build-report.json
|
||||
allow_failure: false
|
||||
needs:
|
||||
- phpcs
|
||||
- eslint
|
||||
- stylelint
|
||||
allow_failure: false
|
||||
3
.gitmodules
vendored
3
.gitmodules
vendored
|
|
@ -1,3 +0,0 @@
|
|||
[submodule "resources/theme"]
|
||||
path = resources/theme
|
||||
url = git@gitlab.com:service-web-lab/boutique-cnc-themes.git
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
{
|
||||
"extends": [
|
||||
"stylelint-config-standard-scss",
|
||||
"stylelint-config-sass-guidelines",
|
||||
"stylelint-config-idiomatic-order"
|
||||
],
|
||||
"plugins": ["stylelint-scss"],
|
||||
"files": ["**/*.css", "**/*.scss"],
|
||||
"ignoreFiles": [
|
||||
"**/vendor/*.css",
|
||||
"**/vendor/**/*.css",
|
||||
"**/vendor/*.scss",
|
||||
"**/vendor/**/*.scss",
|
||||
"**/vendor/*.sass",
|
||||
"**/vendor/**/*.sass",
|
||||
"**/vendor/*.less",
|
||||
"**/vendor/**/*.less"
|
||||
],
|
||||
"customSyntax": "postcss-scss",
|
||||
"rules": {
|
||||
"indentation": 4,
|
||||
"string-quotes": "double",
|
||||
"selector-max-id": null,
|
||||
"color-no-invalid-hex": true,
|
||||
"order/properties-alphabetical-order": null,
|
||||
"max-nesting-depth": 5,
|
||||
"selector-max-compound-selectors": 5,
|
||||
"scss/double-slash-comment-empty-line-before": [
|
||||
"always",
|
||||
{
|
||||
"ignore": [
|
||||
"between-comments",
|
||||
"stylelint-commands",
|
||||
"inside-block"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,3 @@
|
|||
## 2.0.0
|
||||
- Removed Regate stuff
|
||||
- Removed Salaries stuff
|
||||
|
||||
|
||||
## 1.0.1
|
||||
- Change LDC CRM Client repository
|
||||
- composer update
|
||||
|
|
|
|||
|
|
@ -33,12 +33,6 @@ Project root :
|
|||
```
|
||||
npm install && npm run prod
|
||||
```
|
||||
|
||||
## Theme config
|
||||
|
||||
- To reload theme config on engine `php artisan config:sync`
|
||||
- Theme config can be dynamic in `theme.config.php` inserting `MiniCrud`inputs inside, these muste be tested.
|
||||
|
||||
## Back-Office
|
||||
|
||||
Création de compte
|
||||
|
|
|
|||
|
|
@ -1,127 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Auth;
|
||||
|
||||
use App\Models\Customer;
|
||||
use Illuminate\Auth\EloquentUserProvider;
|
||||
use Illuminate\Contracts\Auth\Authenticatable as UserContract;
|
||||
use Illuminate\Contracts\Auth\UserProvider as UserProviderContract;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use LDC\LDCCRM\Enums\ApiError;
|
||||
use LDC\LDCCRM\Exceptions\ApiErrorException;
|
||||
use LDC\LDCCRM\Exceptions\CrmException;
|
||||
|
||||
/**
|
||||
* Crm user provider to integrate nicely with Laravel
|
||||
*/
|
||||
class CrmUserProvider extends EloquentUserProvider implements UserProviderContract
|
||||
{
|
||||
/**
|
||||
* The model to use, specified in auth config guard.
|
||||
* @var string
|
||||
*/
|
||||
private $usedModel = Customer::class;
|
||||
|
||||
/**
|
||||
* Retrieve a user by the given credentials.
|
||||
*
|
||||
* @param array $credentials
|
||||
* @return \Illuminate\Contracts\Auth\Authenticatable|null
|
||||
*/
|
||||
public function retrieveByCredentials(array $credentials)
|
||||
{
|
||||
// * Let laravel find a model
|
||||
$model = parent::retrieveByCredentials($credentials);
|
||||
|
||||
try {
|
||||
/** @var \LDC\LDCCRM\CrmApiV2 */
|
||||
$crm = app('crmAPI');
|
||||
|
||||
// Si pas de compte local.
|
||||
if (!$model) {
|
||||
$crmCustomer = $crm->getCustomer($credentials['email']);
|
||||
|
||||
if (!$crmCustomer) {
|
||||
// * Customer is not found on CRM.
|
||||
return null;
|
||||
}
|
||||
$model = $this->createLocalCustomer($crmCustomer);
|
||||
}
|
||||
|
||||
return $model;
|
||||
} catch (ApiErrorException $e) {
|
||||
// * Customer is not found.
|
||||
if ($e->getApiError()->equals(ApiError::modelNotFound())) {
|
||||
return null;
|
||||
}
|
||||
report($e);
|
||||
Log::error('Unhandled response ', $e->getApiError()->label);
|
||||
} catch (CrmException | \Exception $e) {
|
||||
report($e);
|
||||
// Une erreur critique est survenue avec la CRM.
|
||||
return null;
|
||||
} //end try
|
||||
Log::error(__CLASS__ . '::retrieveByCredentials reached end of possibilities.');
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a user against the given credentials.
|
||||
*
|
||||
* @param UserContract $model
|
||||
* @param array $credentials
|
||||
* @return boolean
|
||||
* @throws \RuntimeException If model provided is not a Customer or connection to server fails.
|
||||
* @throws \LDC\LDCCRM\Exceptions\CrmException On CRM call error.
|
||||
* @throws \Exception On CRM call error.
|
||||
*/
|
||||
public function validateCredentials(UserContract $model, array $credentials)
|
||||
{
|
||||
// FIXME: handle customerNotActivated
|
||||
/** @var \Illuminate\Database\Eloquent\Model $model */
|
||||
if (\get_class($model) !== $this->usedModel) {
|
||||
throw new \RuntimeException('Cannot authenticate any thing else than ' . $this->usedModel);
|
||||
}
|
||||
|
||||
try {
|
||||
/** @var \LDC\LDCCRM\CrmApiV2 */
|
||||
$crm = app('crmAPI');
|
||||
|
||||
// * Ne devrait pas survenir, $crm->login throws ApiError::authFailed()
|
||||
return $crm->login($credentials['email'], $credentials['password']);
|
||||
} catch (ApiErrorException $e) {
|
||||
if ($e->getApiError()->equals(ApiError::authFailed())) {
|
||||
return false;
|
||||
}
|
||||
} catch (CrmException | \Exception $e) {
|
||||
report($e);
|
||||
if (config('app.debug')) {
|
||||
throw $e;
|
||||
}
|
||||
return false;
|
||||
} //end try
|
||||
|
||||
Log::error(__CLASS__ . '::validateCredentials reached end of possibilities.');
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a local customer
|
||||
*
|
||||
* @param \LDC\LDCCRM\Models\Customer $crmCustomer
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
* @throws \Throwable If saving to DB failed.
|
||||
*/
|
||||
private function createLocalCustomer(\LDC\LDCCRM\Models\Customer $crmCustomer): Model
|
||||
{
|
||||
/** @var \Illuminate\Database\Eloquent\Model $model */
|
||||
$model = $this->usedModel::firstOrNew([
|
||||
'email' => $crmCustomer->email
|
||||
]);
|
||||
$model->hashcode = $crmCustomer->hashcode;
|
||||
$model->saveOrFail();
|
||||
|
||||
return $model;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Casts;
|
||||
|
||||
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
|
||||
use Illuminate\Support\Carbon;
|
||||
|
||||
class IntToEpochCast implements CastsAttributes
|
||||
{
|
||||
/**
|
||||
* Cast the given value.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @param array $attributes
|
||||
* @return mixed
|
||||
* @phpcs:disable Squiz.Commenting.FunctionComment.TypeHintMissing
|
||||
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInImplementedInterfaceAfterLastUsed
|
||||
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInImplementedInterfaceBeforeLastUsed
|
||||
*/
|
||||
public function get($model, string $key, $value, array $attributes)
|
||||
{
|
||||
// phpcs:enable
|
||||
if (\is_null($value)) {
|
||||
return null;
|
||||
}
|
||||
$epoch = Carbon::createFromTimestamp(0)->timezone('utc');
|
||||
$time = Carbon::now()->timezone('utc')->parse(\intval($value));
|
||||
$minutesDiff = $time->diffInMinutes($epoch);
|
||||
$hoursDiff = str_pad(floor($minutesDiff / 60), 2, '0', STR_PAD_LEFT);
|
||||
$minutesDiff = str_pad($minutesDiff % 60, 2, '0', STR_PAD_LEFT);
|
||||
return "{$hoursDiff}:{$minutesDiff}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the given value for storage.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @param array $attributes
|
||||
* @return mixed
|
||||
* @phpcs:disable Squiz.Commenting.FunctionComment.TypeHintMissing
|
||||
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInImplementedInterfaceAfterLastUsed
|
||||
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInImplementedInterfaceBeforeLastUsed
|
||||
*/
|
||||
public function set($model, string $key, $value, array $attributes)
|
||||
{
|
||||
// phpcs:enable
|
||||
if (\is_null($value) or !\is_string($value)) {
|
||||
return null;
|
||||
}
|
||||
$time = explode(':', $value);
|
||||
$time = $time ? $time : [];
|
||||
return Carbon::createFromTimestamp(0)->timezone('utc')
|
||||
->setTime($time[0] ?? 0, $time[1] ?? 0)->timestamp;
|
||||
}
|
||||
}
|
||||
|
|
@ -4,8 +4,7 @@ namespace App\Console\Commands;
|
|||
|
||||
use App\Models\User;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
|
||||
class CreateAdmin extends Command
|
||||
{
|
||||
|
|
@ -14,14 +13,14 @@ class CreateAdmin extends Command
|
|||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'user:create';
|
||||
protected $signature = 'create:admin';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Create a backend admin user';
|
||||
protected $description = 'creates an admin user upon password entry';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
|
|
@ -30,71 +29,20 @@ class CreateAdmin extends Command
|
|||
*/
|
||||
public function handle()
|
||||
{
|
||||
$email = null;
|
||||
while (is_null($email)) {
|
||||
try {
|
||||
$tmp = $this->ask('Type the wanted user email', 'equipe.web@ldc.fr');
|
||||
$validator = Validator::make(['email' => $tmp], [
|
||||
'email' => 'required|unique:users,email|email:rfc,dns'
|
||||
]);
|
||||
$validator->validate();
|
||||
$email = $tmp;
|
||||
} catch (ValidationException $e) {
|
||||
$this->error(sprintf(
|
||||
'Please provide a valid email %s',
|
||||
\implode(',', collect($e->errors())->flatten()->all())
|
||||
));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$firstname = null;
|
||||
while (is_null($firstname)) {
|
||||
try {
|
||||
$tmp = $this->ask('Type the wanted user firstname', 'Admin');
|
||||
$validator = Validator::make(['firstname' => $tmp], [
|
||||
'firstname' => 'required|min:5,max:255'
|
||||
]);
|
||||
$validator->validate();
|
||||
$firstname = $tmp;
|
||||
} catch (ValidationException $e) {
|
||||
$this->error(sprintf(
|
||||
'Please provide a valid firstname %s',
|
||||
\implode(',', collect($e->errors())->flatten()->all())
|
||||
));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$lastname = null;
|
||||
while (is_null($lastname)) {
|
||||
try {
|
||||
$tmp = $this->ask('Type the wanted user lastname', 'Saïtama');
|
||||
$validator = Validator::make(['lastname' => $tmp], [
|
||||
'lastname' => 'required|min:5,max:255'
|
||||
]);
|
||||
$validator->validate();
|
||||
$lastname = $tmp;
|
||||
} catch (ValidationException $e) {
|
||||
$this->error(sprintf(
|
||||
'Please provide a valid lastname %s',
|
||||
\implode(',', collect($e->errors())->flatten()->all())
|
||||
));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$password = $this->secret('Type the wanted user password');
|
||||
$firstname = $this->ask('What is the firstname?', 'Equipe');
|
||||
$lastname = $this->ask('What is the lastname?', 'Web');
|
||||
$email = $this->ask('What is the email?', 'equipe.web@ldc.fr');
|
||||
$pwd = $this->secret('What is the password?');
|
||||
|
||||
$user = new User();
|
||||
$user->firstname = $firstname;
|
||||
$user->lastname = $lastname;
|
||||
$user->date_of_birth = now();
|
||||
$user->email = $email;
|
||||
$user->password = $password;
|
||||
$user->password = Hash::make($pwd);
|
||||
$user->email_verified_at = now();
|
||||
// FIXME: Select role, Enum ?
|
||||
$user->role = 1;
|
||||
$user->saveOrFail();
|
||||
$user->role = 1;
|
||||
$user->save();
|
||||
|
||||
$this->info('User created.');
|
||||
}
|
||||
|
|
|
|||
37
app/Console/Commands/ImportSalaries.php
Normal file
37
app/Console/Commands/ImportSalaries.php
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use App\Jobs\CsvSalariesReader as JobCsvSalarieReader;
|
||||
|
||||
class ImportSalaries extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'import:salaries';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Import Salaries, pour provision des clients';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$this->info('Running the Job, this could take some time.');
|
||||
$job = new JobCsvSalarieReader();
|
||||
$job->console = $this;
|
||||
$job->handle();
|
||||
$this->info('Job completed');
|
||||
}
|
||||
}
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Enums\GeneralConfigType;
|
||||
use App\Models\GeneralConfig;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
|
||||
class SyncThemeSettings extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'config:sync_theme';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Synchronize theme config with database.';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
// * Force config clearance.
|
||||
Artisan::call('config:clear');
|
||||
|
||||
// * Force cache to be cleared ( reload GeneralConfigs )
|
||||
Artisan::call('cache:clear');
|
||||
|
||||
// * Fetch or create theme config
|
||||
/** @var \App\Models\GeneralConfig */
|
||||
$config = GeneralConfig::query()->where('type', GeneralConfigType::theme())->firstOrNew();
|
||||
|
||||
// * Fetch Bo Theme Settings.
|
||||
$data = config('theme.bo_theme_settings');
|
||||
|
||||
$config->data = $data;
|
||||
$config->saveOrFail();
|
||||
|
||||
$this->info('Theme config is overrided with the latest theme.config.php content.');
|
||||
}
|
||||
}
|
||||
|
|
@ -2,13 +2,6 @@
|
|||
|
||||
namespace App\Console;
|
||||
|
||||
use App\Jobs\DeleteOlds\DeleteOldCollectionException;
|
||||
use App\Jobs\DeleteOlds\DeleteOldCustomers;
|
||||
use App\Jobs\DeleteOlds\DeleteOldOrders;
|
||||
use App\Jobs\DeleteOlds\DeleteOldTimeslots;
|
||||
use App\Jobs\ProductsOrderableUpdate;
|
||||
use App\Jobs\ProductsStatusUpdate;
|
||||
use App\Jobs\SlidesStatusUpdate;
|
||||
use App\Jobs\XmlIncoReader as JobsXmlIncoReader;
|
||||
use Illuminate\Console\Scheduling\Schedule;
|
||||
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
||||
|
|
@ -31,19 +24,9 @@ class Kernel extends ConsoleKernel
|
|||
*/
|
||||
protected function schedule(Schedule $schedule)
|
||||
{
|
||||
// * Update models planified booleans changes
|
||||
$schedule->job(SlidesStatusUpdate::class)->everyMinute();
|
||||
$schedule->job(ProductsStatusUpdate::class)->everyMinute();
|
||||
$schedule->job(ProductsOrderableUpdate::class)->everyMinute();
|
||||
|
||||
$schedule->command('sitemap:refresh')->dailyAt('16:13');
|
||||
$schedule->command('ldcweb:statuschecker')->everyFifteenMinutes();
|
||||
$schedule->job(JobsXmlIncoReader::class)->name('xml-inco-reader')->onOneServer()->dailyAt('15:00');
|
||||
|
||||
$schedule->job(DeleteOldOrders::class)->dailyAt('23:00');
|
||||
$schedule->job(DeleteOldCustomers::class)->dailyAt('22:50');
|
||||
$schedule->job(DeleteOldCollectionException::class)->dailyAt('10:42');
|
||||
$schedule->job(DeleteOldTimeslots::class)->everyMinute();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,35 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Enums\DeliveryMode;
|
||||
|
||||
use Kwaadpepper\Enum\BaseEnum;
|
||||
|
||||
/**
|
||||
* @method static self inShop()
|
||||
*/
|
||||
final class DeliveryModeEnum extends BaseEnum
|
||||
{
|
||||
/**
|
||||
* Enum values
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function values(): array
|
||||
{
|
||||
return [
|
||||
'inShop' => 1
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Enum labels
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function labels(): array
|
||||
{
|
||||
return [
|
||||
'inShop' => __('À la boutique')
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Enums\Discount;
|
||||
|
||||
use Kwaadpepper\Enum\BaseEnumRoutable;
|
||||
|
||||
/**
|
||||
* @method static self amount()
|
||||
* @method static self percent()
|
||||
*/
|
||||
final class DiscountType extends BaseEnumRoutable
|
||||
{
|
||||
/**
|
||||
* Enum values
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function values(): array
|
||||
{
|
||||
return [
|
||||
'amount' => 0,
|
||||
'percent' => 1,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Enum labels
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function labels(): array
|
||||
{
|
||||
return [
|
||||
'amount' => trans('Montant'),
|
||||
'percent' => trans('Pourcentage'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Enum units
|
||||
*
|
||||
* @return array<float>
|
||||
*/
|
||||
protected static function units(): array
|
||||
{
|
||||
return [
|
||||
'amount' => '€',
|
||||
'percent' => '%'
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Enum steps
|
||||
*
|
||||
* @return array<float>
|
||||
*/
|
||||
protected static function steps(): array
|
||||
{
|
||||
return [
|
||||
'amount' => 0.01,
|
||||
'percent' => 1
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $attribute
|
||||
* @return integer|string
|
||||
*/
|
||||
public function __get(string $attribute)
|
||||
{
|
||||
if ($attribute === 'unit') {
|
||||
return $this->units()[$this->getDefinition()] ?? null;
|
||||
}
|
||||
if ($attribute === 'step') {
|
||||
return $this->steps()[$this->getDefinition()] ?? null;
|
||||
}
|
||||
return parent::__get($attribute);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Enums;
|
||||
|
||||
use Kwaadpepper\Enum\BaseEnumRoutable;
|
||||
|
||||
/**
|
||||
* @method static self global()
|
||||
* @method static self orders()
|
||||
* @method static self theme()
|
||||
*/
|
||||
final class GeneralConfigType extends BaseEnumRoutable
|
||||
{
|
||||
/**
|
||||
* Values
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function values(): array
|
||||
{
|
||||
return [
|
||||
'global' => 1,
|
||||
'orders' => 2,
|
||||
'theme' => 3,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Labels
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function labels(): array
|
||||
{
|
||||
return [
|
||||
'global' => __('Configuration du site'),
|
||||
'orders' => __('Configuration des commandes'),
|
||||
'theme' => __('Configuration du theme'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Enums;
|
||||
|
||||
use Kwaadpepper\Enum\BaseEnumRoutable;
|
||||
|
||||
/**
|
||||
* @method static self boolean()
|
||||
* @method static self image()
|
||||
* @method static self string()
|
||||
* @method static self text()
|
||||
* html autorisé
|
||||
* @method static self url()
|
||||
* @method static self imageArray()
|
||||
* @method static self labelArray()
|
||||
* @method static self dropdownArray()
|
||||
* html autorisé
|
||||
* @method static self miniblocArray()
|
||||
* html autorisé
|
||||
* @method static self videoVimeo()
|
||||
* @method static self number()
|
||||
* @method static self email()
|
||||
*/
|
||||
final class InputType extends BaseEnumRoutable
|
||||
{
|
||||
/**
|
||||
* Values
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function values(): array
|
||||
{
|
||||
return [
|
||||
'boolean' => 0,
|
||||
'image' => 1,
|
||||
'string' => 2,
|
||||
'text' => 3,
|
||||
'url' => 4,
|
||||
'imageArray' => 5,
|
||||
'labelArray' => 6,
|
||||
'dropdownArray' => 7,
|
||||
'miniblocArray' => 8,
|
||||
'videoVimeo' => 9,
|
||||
'number' => 10,
|
||||
'email' => 11
|
||||
];
|
||||
}
|
||||
}
|
||||
50
app/Enums/InvoicingUnit.php
Normal file
50
app/Enums/InvoicingUnit.php
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
namespace App\Enums;
|
||||
|
||||
use Kwaadpepper\Enum\BaseEnum;
|
||||
|
||||
/**
|
||||
* @method static self pce()
|
||||
* @method static self kgm()
|
||||
* @method static self colis()
|
||||
*/
|
||||
final class InvoicingUnit extends BaseEnum
|
||||
{
|
||||
/**
|
||||
* Enum values
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function values(): array
|
||||
{
|
||||
return [
|
||||
'pce' => 'PCE',
|
||||
'kgm' => 'KGM',
|
||||
'colis' => 'COLIS',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Enum labels
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function labels(): array
|
||||
{
|
||||
return [
|
||||
'pce' => __('Pièce'),
|
||||
'kgm' => __('Kg'),
|
||||
'colis' => __('Colis'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the value as a string
|
||||
* @return string
|
||||
*/
|
||||
public function __toString(): string
|
||||
{
|
||||
return (string)$this->label;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Enums\Order;
|
||||
|
||||
use Kwaadpepper\Enum\BaseEnumRoutable;
|
||||
|
||||
/**
|
||||
* @method static self pending()
|
||||
* Aucune action n'a été entreprise.
|
||||
* @method static self preparation()
|
||||
* La commande est en préparation
|
||||
* @method static self ready()
|
||||
* La commande est prête a être récupérée
|
||||
* @method static self recovered()
|
||||
* La commande à été récupérée par le client
|
||||
*/
|
||||
final class DeliveryStatus extends BaseEnumRoutable
|
||||
{
|
||||
/**
|
||||
* Enum values
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function values(): array
|
||||
{
|
||||
return [
|
||||
'pending' => 0,
|
||||
'preparation' => 1,
|
||||
'ready' => 2,
|
||||
'recovered' => 3
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Enum labels
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function labels(): array
|
||||
{
|
||||
return [
|
||||
'pending' => __('À faire'),
|
||||
'preparation' => __('En préparation'),
|
||||
'sent' => __('Envoyé'),
|
||||
'recovered' => __('Récupéré'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Enums\Order;
|
||||
|
||||
use Kwaadpepper\Enum\BaseEnumRoutable;
|
||||
|
||||
/**
|
||||
* @method static self reviewBasket()
|
||||
* @method static self shippment()
|
||||
* @method static self shippingMethod()
|
||||
* @method static self paymentReview()
|
||||
*/
|
||||
final class OrderProcess extends BaseEnumRoutable
|
||||
{
|
||||
/**
|
||||
* Values
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function values(): array
|
||||
{
|
||||
return [
|
||||
'reviewBasket' => 0,
|
||||
'shippingMethod' => 1,
|
||||
'shippment' => 2,
|
||||
'paymentReview' => 3
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Labels
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function labels(): array
|
||||
{
|
||||
return [
|
||||
'reviewBasket' => trans('Panier'),
|
||||
'shippingMethod' => trans('Expédition - mode'),
|
||||
'shippment' => trans('Expédition - détails'),
|
||||
'paymentReview' => trans('Paiement')
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Enums\Order;
|
||||
|
||||
use Kwaadpepper\Enum\BaseEnumRoutable;
|
||||
|
||||
/**
|
||||
* @method static self pending()
|
||||
* Payment en attente
|
||||
* @method static self failed()
|
||||
* Payment à échoué
|
||||
* @method static self payed()
|
||||
* Le règlement à bien été validé
|
||||
*/
|
||||
final class PaymentStatus extends BaseEnumRoutable
|
||||
{
|
||||
/**
|
||||
* Enum values
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function values(): array
|
||||
{
|
||||
return [
|
||||
'pending' => 0,
|
||||
'failed' => 1,
|
||||
'payed' => 3
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Enum labels
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function labels(): array
|
||||
{
|
||||
return [
|
||||
'pending' => __('En attente'),
|
||||
'failed' => __('Échec'),
|
||||
'payed' => __('Réglée')
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Enums\Order;
|
||||
|
||||
use Kwaadpepper\Enum\BaseEnumRoutable;
|
||||
|
||||
/**
|
||||
* @method static self pending()
|
||||
* La commande n'est pas encore évaluée
|
||||
* @method static self cancelled()
|
||||
* La commande est annulée
|
||||
* @method static self validated()
|
||||
* La commande est validée (pour préparation)
|
||||
*/
|
||||
final class ValidationStatus extends BaseEnumRoutable
|
||||
{
|
||||
/**
|
||||
* Enum values
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function values(): array
|
||||
{
|
||||
return [
|
||||
'pending' => 0,
|
||||
'cancelled' => 1,
|
||||
'validated' => 2,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Enum labels
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function labels(): array
|
||||
{
|
||||
return [
|
||||
'pending' => __('En attente de validation'),
|
||||
'cancelled' => __('Annulée'),
|
||||
'validated' => __('Validée'),
|
||||
];
|
||||
}
|
||||
}
|
||||
50
app/Enums/OrderUnit.php
Normal file
50
app/Enums/OrderUnit.php
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
namespace App\Enums;
|
||||
|
||||
use Kwaadpepper\Enum\BaseEnum;
|
||||
|
||||
/**
|
||||
* @method static self pce()
|
||||
* @method static self kgm()
|
||||
* @method static self colis()
|
||||
*/
|
||||
final class OrderUnit extends BaseEnum
|
||||
{
|
||||
/**
|
||||
* Enum values
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function values(): array
|
||||
{
|
||||
return [
|
||||
'pce' => 'PCE',
|
||||
'kgm' => 'KGM',
|
||||
'colis' => 'COLIS',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Enum labels
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function labels(): array
|
||||
{
|
||||
return [
|
||||
'pce' => __('Pièce'),
|
||||
'kgm' => __('Kg'),
|
||||
'colis' => __('Colis'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the value as a string
|
||||
* @return string
|
||||
*/
|
||||
public function __toString(): string
|
||||
{
|
||||
return (string)$this->label;
|
||||
}
|
||||
}
|
||||
|
|
@ -5,10 +5,14 @@ namespace App\Enums;
|
|||
use Kwaadpepper\Enum\BaseEnumRoutable;
|
||||
|
||||
/**
|
||||
* @method static self admin()
|
||||
* @method static self user()
|
||||
* This is an enumeration class,
|
||||
* the following methods are its possible values
|
||||
*
|
||||
* @method static self authenticated()
|
||||
* @method static self guest()
|
||||
*
|
||||
*/
|
||||
final class UserRole extends BaseEnumRoutable
|
||||
class PriceShowingMode extends BaseEnumRoutable
|
||||
{
|
||||
/**
|
||||
* Enum values
|
||||
|
|
@ -18,8 +22,8 @@ final class UserRole extends BaseEnumRoutable
|
|||
protected static function values(): array
|
||||
{
|
||||
return [
|
||||
'admin' => 1,
|
||||
'user' => 0,
|
||||
'authenticated' => 'authenticated',
|
||||
'guest' => 'guest',
|
||||
];
|
||||
}
|
||||
|
||||
|
|
@ -31,8 +35,8 @@ final class UserRole extends BaseEnumRoutable
|
|||
protected static function labels(): array
|
||||
{
|
||||
return [
|
||||
'admin' => trans('Administrateur'),
|
||||
'user' => trans('Utilisateur'),
|
||||
'authenticated' => __('Client Connecté'),
|
||||
'guest' => __('Public'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Enums\Product;
|
||||
|
||||
use App\Enums\InputType;
|
||||
use Kwaadpepper\Enum\BaseEnumRoutable;
|
||||
|
||||
/**
|
||||
* @method static self default()
|
||||
* @method static self inco()
|
||||
*/
|
||||
final class DefaultProductType extends BaseEnumRoutable
|
||||
{
|
||||
/**
|
||||
* Enum labels
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function labels(): array
|
||||
{
|
||||
return [
|
||||
'default' => 'De base',
|
||||
'inco' => 'Alimentaire lié a Inco',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Inco minicrud inputs for specific product type inco
|
||||
* ! Attention toute modification après la mise en
|
||||
* ! production doit faire l'objet d'une migration
|
||||
* ! pour réaligner le contenu du champ data
|
||||
* ! pour chaque type de produit
|
||||
* ! sous peine de de tout casser
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function incoInputs(): array
|
||||
{
|
||||
return [
|
||||
'ingredients' => [
|
||||
'label' => 'Ingrédients',
|
||||
'inputType' => InputType::text(),
|
||||
'text' => '',
|
||||
'validate' => 'nullable|string'
|
||||
],
|
||||
'preparation_advices' => [
|
||||
'label' => 'Conseils de préparation',
|
||||
'inputType' => InputType::text(),
|
||||
'text' => '',
|
||||
'validate' => 'nullable|string'
|
||||
],
|
||||
'allergens' => [
|
||||
'label' => 'Ingrédients allèrgenes',
|
||||
'inputType' => InputType::text(),
|
||||
'text' => '',
|
||||
'validate' => 'nullable|string'
|
||||
],
|
||||
'selling_arguments' => [
|
||||
'label' => 'Arguments de vente',
|
||||
'inputType' => InputType::text(),
|
||||
'text' => '',
|
||||
'validate' => 'nullable|string'
|
||||
],
|
||||
'servings' => [
|
||||
'label' => 'Portions',
|
||||
'inputType' => InputType::number(),
|
||||
'value' => '',
|
||||
'validate' => 'numeric|min:0'
|
||||
],
|
||||
'servings_type' => [
|
||||
'label' => 'Type de portions',
|
||||
'inputType' => InputType::string(),
|
||||
'value' => '',
|
||||
'validate' => 'nullable|string|max:150'
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Enums\Product;
|
||||
|
||||
use Kwaadpepper\Enum\BaseEnumRoutable;
|
||||
|
||||
/**
|
||||
* Calcul par unité de produits
|
||||
*
|
||||
* @method static self twenty()
|
||||
* @method static self ten()
|
||||
* @method static self five()
|
||||
*
|
||||
* @property-read float $rate The TVA rate.
|
||||
*/
|
||||
final class TaxRate extends BaseEnumRoutable
|
||||
{
|
||||
/**
|
||||
* Enum values
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function values(): array
|
||||
{
|
||||
return [
|
||||
'twenty' => 0,
|
||||
'ten' => 1,
|
||||
'five' => 2
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Enum labels
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function labels(): array
|
||||
{
|
||||
return [
|
||||
'twenty' => trans('Taux normal'),
|
||||
'ten' => trans('Taux reduit'),
|
||||
'five' => trans('Taux très reduit')
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Enum rates
|
||||
*
|
||||
* @return array<float>
|
||||
*/
|
||||
protected static function rates(): array
|
||||
{
|
||||
return [
|
||||
'twenty' => 20,
|
||||
'ten' => 10,
|
||||
'five' => 5.5,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $attribute
|
||||
* @return integer|string
|
||||
*/
|
||||
public function __get(string $attribute)
|
||||
{
|
||||
if ($attribute === 'rate') {
|
||||
return $this->rates()[$this->getDefinition()] ?? null;
|
||||
}
|
||||
return parent::__get($attribute);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,104 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Enums\Product;
|
||||
|
||||
use Kwaadpepper\Enum\BaseEnum;
|
||||
|
||||
/**
|
||||
* @method static self g()
|
||||
* @method static self kg()
|
||||
* @method static self ton()
|
||||
*/
|
||||
final class WeightUnit extends BaseEnum
|
||||
{
|
||||
/**
|
||||
* Enum values
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function values(): array
|
||||
{
|
||||
return [
|
||||
'g' => 'G',
|
||||
'kg' => 'KG',
|
||||
'ton' => 'T',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Enum labels
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function labels(): array
|
||||
{
|
||||
return [
|
||||
'g' => __('g'),
|
||||
'kg' => __('kg'),
|
||||
'ton' => __('t'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Enum conversions a partir de gramme
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function conversions(): array
|
||||
{
|
||||
return [
|
||||
'g' => 1,
|
||||
'kg' => 1000,
|
||||
'ton' => 1000000,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $attribute
|
||||
* @return integer|string
|
||||
*/
|
||||
public function __get(string $attribute)
|
||||
{
|
||||
if ($attribute === 'conversion') {
|
||||
return $this->conversions()[$this->getDefinition()] ?? null;
|
||||
}
|
||||
return parent::__get($attribute);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format weight into a displayable unit.
|
||||
* @param integer $weightG The weight in grams.
|
||||
* @param \App\Enums\WeightUnit|null $forceUnit To force specific unit display.
|
||||
* @return string
|
||||
*/
|
||||
public static function getDisplayableWeight(int $weightG, self $forceUnit = null): string
|
||||
{
|
||||
if ($forceUnit) {
|
||||
number_format(round($weightG / $forceUnit->conversion, 2), 2, ',', '') . $forceUnit->label;
|
||||
}
|
||||
$displayable = self::convertWeightToAdequatUnit($weightG);
|
||||
return \number_format($displayable->value, 2, ',', '') . ' ' . $displayable->enum->label;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert value to the adequat unit
|
||||
* @param integer $weightG The weight in grams.
|
||||
* @return object<'enum'|'value',self>
|
||||
*/
|
||||
private function convertWeightToAdequatUnit(int $weightG): object
|
||||
{
|
||||
foreach (self::conversions() as $key => $conversionRate) {
|
||||
$convertedTest = round($weightG / $conversionRate, 2);
|
||||
if ($convertedTest > 0.001 and $convertedTest <= 1000) {
|
||||
return (object)[
|
||||
'enum' => self::make($key),
|
||||
'value' => $convertedTest
|
||||
];
|
||||
}
|
||||
}
|
||||
return (object)[
|
||||
'enum' => \collect(self::toArray())->last(),
|
||||
'value' => $weightG
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace App\Enums\Product;
|
||||
namespace App\Enums;
|
||||
|
||||
use Kwaadpepper\Enum\BaseEnum;
|
||||
|
||||
47
app/Enums/SettingRegisterMode.php
Normal file
47
app/Enums/SettingRegisterMode.php
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
namespace App\Enums;
|
||||
|
||||
use Kwaadpepper\Enum\BaseEnum;
|
||||
|
||||
/**
|
||||
* @method static self public()
|
||||
* @method static self salaries()
|
||||
*/
|
||||
final class SettingRegisterMode extends BaseEnum
|
||||
{
|
||||
/**
|
||||
* Enum values
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function values(): array
|
||||
{
|
||||
return [
|
||||
'public' => 'public',
|
||||
'salaries' => 'salaries',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Enum labels
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function labels(): array
|
||||
{
|
||||
return [
|
||||
'public' => __('Public'),
|
||||
'salaries' => __('Salaries'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the value as a string
|
||||
* @return string
|
||||
*/
|
||||
public function __toString(): string
|
||||
{
|
||||
return (string)$this->label;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Enums;
|
||||
|
||||
use Kwaadpepper\Enum\BaseEnumRoutable;
|
||||
|
||||
/**
|
||||
* @method static self home()
|
||||
* Page d'accueil
|
||||
* @method static self contact()
|
||||
* Page de contact
|
||||
* @method static self legals()
|
||||
* Page mentions légales
|
||||
* @method static self sellconditions()
|
||||
* Page conditions de ventes
|
||||
* @method static self confidentiality()
|
||||
* Page politique de confidentialitée
|
||||
* @method static self faq()
|
||||
* Page faq
|
||||
* @method static self crud()
|
||||
* Page de contenus libre en CRUD.
|
||||
*/
|
||||
final class StaticPageType extends BaseEnumRoutable
|
||||
{
|
||||
/**
|
||||
* Enum values
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function values(): array
|
||||
{
|
||||
return [
|
||||
'home' => 0,
|
||||
'contact' => 1,
|
||||
'legals' => 2,
|
||||
'sellconditions' => 3,
|
||||
'confidentiality' => 4,
|
||||
'faq' => 5,
|
||||
'crud' => 6
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Enum labels
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function labels(): array
|
||||
{
|
||||
return [
|
||||
'home' => trans('Accueil'),
|
||||
'contact' => trans('Contact'),
|
||||
'legals' => trans('Mentions Légales'),
|
||||
'sellconditions' => trans('CGV'),
|
||||
'confidentiality' => trans('Politique de confidentialité'),
|
||||
'faq' => trans('FAQ'),
|
||||
'crud' => trans('Pages libres'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Enums\TimeSlot;
|
||||
|
||||
use Kwaadpepper\Enum\BaseEnum;
|
||||
|
||||
/**
|
||||
* @method static self monday()
|
||||
* @method static self tuesday()
|
||||
* @method static self wednesday()
|
||||
* @method static self thursday()
|
||||
* @method static self friday()
|
||||
* @method static self saturday()
|
||||
* @method static self sunday()
|
||||
*/
|
||||
final class WeekDay extends BaseEnum
|
||||
{
|
||||
/**
|
||||
* Enum values
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function values(): array
|
||||
{
|
||||
return [
|
||||
'monday' => 1,
|
||||
'tuesday' => 2,
|
||||
'wednesday' => 3,
|
||||
'thursday' => 4,
|
||||
'friday' => 5,
|
||||
'saturday' => 6,
|
||||
'sunday' => 7,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Enum labels
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function labels(): array
|
||||
{
|
||||
return [
|
||||
'monday' => trans('Lundi'),
|
||||
'tuesday' => trans('Mardi'),
|
||||
'wednesday' => trans('Mercredi'),
|
||||
'thursday' => trans('Jeudi'),
|
||||
'friday' => trans('Vendredi'),
|
||||
'saturday' => trans('Samedi'),
|
||||
'sunday' => trans('Dimanche')
|
||||
];
|
||||
}
|
||||
}
|
||||
65
app/Enums/WeightUnit.php
Normal file
65
app/Enums/WeightUnit.php
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
|
||||
namespace App\Enums;
|
||||
|
||||
use Kwaadpepper\Enum\BaseEnum;
|
||||
|
||||
/**
|
||||
* @method static self g()
|
||||
* @method static self kg()
|
||||
* @method static self ton()
|
||||
*/
|
||||
final class WeightUnit extends BaseEnum
|
||||
{
|
||||
/**
|
||||
* Enum values
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function values(): array
|
||||
{
|
||||
return [
|
||||
'g' => 'G',
|
||||
'kg' => 'KG',
|
||||
'ton' => 'T',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Enum labels
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function labels(): array
|
||||
{
|
||||
return [
|
||||
'g' => __('Gramme'),
|
||||
'kg' => __('Kg'),
|
||||
'ton' => __('Tonne'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* conversion values
|
||||
* base kg()
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function convert(): array
|
||||
{
|
||||
return [
|
||||
'G' => 0.001,
|
||||
'KG' => 1,
|
||||
'T' => 1000,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the value as a string
|
||||
* @return string
|
||||
*/
|
||||
public function __toString(): string
|
||||
{
|
||||
return (string)$this->label;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use Illuminate\Auth\Events\Verified;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
|
||||
class LogVerifiedUser
|
||||
{
|
||||
/**
|
||||
* Handle the given event.
|
||||
*
|
||||
* @param \Illuminate\Auth\Events\Verified $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle(Verified $event)
|
||||
{
|
||||
/** @var \App\Models\Customer */
|
||||
$customer = $event->user;
|
||||
Auth::guard('frontend')->login($customer);
|
||||
Session::flash('success', trans('Votre compte à bien été validé, vous êtes à présent connecté.'));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use Illuminate\Auth\Events\PasswordReset;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
|
||||
class PasswordHasReset
|
||||
{
|
||||
/**
|
||||
* Handle the given event.
|
||||
*
|
||||
* @param \Illuminate\Auth\Events\PasswordReset $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle(PasswordReset $event)
|
||||
{
|
||||
/** @var \App\Models\Customer */
|
||||
$customer = $event->user;
|
||||
Auth::guard('frontend')->login($customer);
|
||||
Session::flash('success', trans('Votre mot de passe à bien été réinitialisé, vous êtes à présent connecté.'));
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
namespace App\Exceptions;
|
||||
|
||||
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
|
||||
use Illuminate\Auth\AuthenticationException;
|
||||
|
||||
class Handler extends ExceptionHandler
|
||||
{
|
||||
|
|
@ -23,28 +24,6 @@ class Handler extends ExceptionHandler
|
|||
'password_confirmation',
|
||||
];
|
||||
|
||||
/**
|
||||
* Report or log an exception.
|
||||
*
|
||||
* @param \Throwable $e
|
||||
* @return void
|
||||
*
|
||||
* @phpcs:ignore Squiz.Commenting.FunctionComment.EmptyThrows
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function report(\Throwable $e)
|
||||
{
|
||||
// phpcs:enable
|
||||
if (get_class($e) == RedirectTo::class) {
|
||||
abort(redirect($e->url));
|
||||
}
|
||||
|
||||
if ($this->shouldntReport($e)) {
|
||||
return;
|
||||
}
|
||||
parent::report($e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the exception handling callbacks for the application.
|
||||
*
|
||||
|
|
@ -57,5 +36,33 @@ class Handler extends ExceptionHandler
|
|||
app('sentry')->captureException($e);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle unauthenticated as exception
|
||||
*
|
||||
* @param mixed $request
|
||||
* @param AuthenticationException $exception
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
protected function unauthenticated($request, AuthenticationException $exception)
|
||||
{
|
||||
if ($request->expectsJson()) {
|
||||
return response()->json(['error' => 'Unauthenticated.'], 401);
|
||||
}
|
||||
$guard = $exception->guards()[0];
|
||||
switch ($guard) {
|
||||
case 'customer':
|
||||
$login = 'auth.connexion';
|
||||
break;
|
||||
default:
|
||||
$login = 'auth.login';
|
||||
break;
|
||||
}
|
||||
// Cf. issue :
|
||||
// Https://stackoverflow.com/questions/52417438/laravel-unauthenticated-redirect-issue-with-multiple-authentication.
|
||||
// Session::forget('url.intented'); .
|
||||
return redirect()->guest(route($login));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
70
app/Http/Controllers/Auth/LoginController.php
Normal file
70
app/Http/Controllers/Auth/LoginController.php
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
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)
|
||||
{
|
||||
// @phpcs:enable
|
||||
return view('auth.login-bo');
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute login form
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*
|
||||
*/
|
||||
public function login(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'email' => 'required',
|
||||
'password' => 'required'
|
||||
]);
|
||||
|
||||
$credentials = $request->only(['email', 'password']);
|
||||
|
||||
if (Auth::attempt($credentials)) {
|
||||
$user = Auth::user();
|
||||
if ($user->role === 1 || $user->role === 2) {
|
||||
return redirect()->route('bo.dashboard');
|
||||
} else {
|
||||
if ($user->email_verified_at === null) {
|
||||
Auth::logout();
|
||||
return view('auth.login')->withErrors('Compte non activé.');
|
||||
}
|
||||
return redirect()->intended('/');
|
||||
}
|
||||
}
|
||||
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)
|
||||
{
|
||||
// @phpcs:enable
|
||||
Auth::logout();
|
||||
return redirect()->route('home');
|
||||
}
|
||||
}
|
||||
56
app/Http/Controllers/Auth/RegisterController.php
Normal file
56
app/Http/Controllers/Auth/RegisterController.php
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\User;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
|
||||
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)
|
||||
{
|
||||
// @phpcs:enable
|
||||
return view('auth.register');
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute regioster form
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*
|
||||
*/
|
||||
public function register(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'lastname' => 'required|string|max:255',
|
||||
'firstname' => 'required|string|max:255',
|
||||
'date_of_birth' => 'required|date|before_or_equal:' . Carbon::now()->subYears(18)->toDateString(),
|
||||
'email' => 'required|string|email|max:255|unique:users|confirmed',
|
||||
'password' => 'required|string|min:8',
|
||||
]);
|
||||
|
||||
User::create([
|
||||
'firstname' => $request->firstname,
|
||||
'lastname' => $request->lastname,
|
||||
'date_of_birth' => $request->date_of_birth,
|
||||
'email' => $request->email,
|
||||
'password' => Hash::make($request->password),
|
||||
'role' => 3
|
||||
]);
|
||||
|
||||
// Envoi mail activation.
|
||||
return redirect()->route('auth.register')->with('success', 'Mail envoyé pour confirmation');
|
||||
}
|
||||
}
|
||||
23
app/Http/Controllers/Auth/ResetPasswordController.php
Normal file
23
app/Http/Controllers/Auth/ResetPasswordController.php
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
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)
|
||||
{
|
||||
// @phpcs:enable
|
||||
return view('auth.reset-password');
|
||||
}
|
||||
}
|
||||
164
app/Http/Controllers/BasketController.php
Normal file
164
app/Http/Controllers/BasketController.php
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Product;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Collection;
|
||||
use Gloudemans\Shoppingcart\Facades\Cart;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class BasketController extends Controller
|
||||
{
|
||||
/**
|
||||
* ajout de produit au panier
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function addToCart(Request $request)
|
||||
{
|
||||
$instance = $request->instance ?? "panier";
|
||||
$product = Product::find($request->id);
|
||||
Cart::instance($instance);
|
||||
Cart::add($product, $request->qty);
|
||||
return $this->getCart($instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* ajout de plusieurs produits au panier
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function addToCartLot(Request $request)
|
||||
{
|
||||
$instance = $request->instance ?? "panier";
|
||||
Cart::instance($instance);
|
||||
$lot = $request->items;
|
||||
foreach ($lot as $item) {
|
||||
$product = Product::find($item["cartItem"]["id"]);
|
||||
Cart::add($product, $item["cartItem"]["qty"]);
|
||||
}
|
||||
return $this->getCart($instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* suppression de produit du panier
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function removeFromCart(Request $request)
|
||||
{
|
||||
$instance = $request->instance ?? "panier";
|
||||
$rowId = $request->rowId;
|
||||
Cart::instance($instance);
|
||||
Cart::remove($rowId);
|
||||
return $this->getCart($instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* vidage de panier
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function emptyCart(Request $request)
|
||||
{
|
||||
$instance = $request->instance ?? "panier";
|
||||
Cart::instance($instance);
|
||||
Cart::destroy();
|
||||
return $this->getCart($instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* récupération du panier
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getCartRequest(Request $request)
|
||||
{
|
||||
$instance = $request->instance ?? "panier";
|
||||
Cart::instance($instance);
|
||||
return $this->getCart($instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* return cart data array
|
||||
*
|
||||
* @param string $instance
|
||||
* @return array
|
||||
*/
|
||||
public function getCart(string $instance = "panier")
|
||||
{
|
||||
Cart::instance($instance);
|
||||
$dbpanier = new Collection();
|
||||
foreach (Cart::content() as $row) {
|
||||
$product = $row->model;
|
||||
|
||||
$product->calculatedPrices = $product->getCalcPrices();
|
||||
|
||||
$row->setTaxRate($product->tax->rate);
|
||||
$row->setDiscountRate($product->discountRate);
|
||||
|
||||
$cartextendedItem = array(
|
||||
'cartItem' => $row,
|
||||
'product' => $product
|
||||
);
|
||||
$dbpanier->add($cartextendedItem);
|
||||
}
|
||||
|
||||
$cartInfos = array(
|
||||
"totalTTC" => Cart::total(),
|
||||
// Total des taxes.
|
||||
'totalTVA' => Cart::tax(),
|
||||
// Total sans les taxes.
|
||||
'totalHT' => Cart::subtotal(),
|
||||
// Poids total des items.
|
||||
'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(
|
||||
"totalTTC" => "-.--",
|
||||
// Total des taxes.
|
||||
'totalTVA' => "-.--",
|
||||
// Total sans les taxes.
|
||||
'totalHT' => "-.--",
|
||||
// Poids total des items.
|
||||
'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);
|
||||
if (config('bosettings.show_prices_authenticated') == "authenticated") {
|
||||
{
|
||||
if (Auth::guard('customer')->check()) {
|
||||
$cartReturn = array($dbpanier,$cartInfos);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (config('bosettings.show_prices_guest') == "guest") {
|
||||
$cartReturn = array($dbpanier,$cartInfos);
|
||||
}
|
||||
|
||||
return $cartReturn;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Bo\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Foundation\Auth\AuthenticatesUsers;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class LoginController extends Controller
|
||||
{
|
||||
use AuthenticatesUsers;
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('guest:backend')->except('logout');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the guard to be used during authentication.
|
||||
*
|
||||
* @return \Illuminate\Contracts\Auth\StatefulGuard
|
||||
*/
|
||||
protected function guard()
|
||||
{
|
||||
return Auth::guard('backend');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the application's login form.
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function showLoginForm()
|
||||
{
|
||||
return view('back::auth.login');
|
||||
}
|
||||
|
||||
/**
|
||||
* Where to redirect users after login.
|
||||
* @return string
|
||||
*/
|
||||
protected function redirectTo(): string
|
||||
{
|
||||
return \route('bo.dashboard');
|
||||
}
|
||||
}
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Bo\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Foundation\Auth\ResetsPasswords;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class ResetPasswordController extends Controller
|
||||
{
|
||||
use ResetsPasswords;
|
||||
|
||||
/**
|
||||
* Get the guard to be used during authentication.
|
||||
*
|
||||
* @return \Illuminate\Contracts\Auth\StatefulGuard
|
||||
*/
|
||||
protected function guard()
|
||||
{
|
||||
return Auth::guard('backend');
|
||||
}
|
||||
|
||||
/**
|
||||
* Where to redirect users after login.
|
||||
* @return string
|
||||
*/
|
||||
protected function redirectTo(): string
|
||||
{
|
||||
return \route('bo.login');
|
||||
}
|
||||
}
|
||||
|
|
@ -1,92 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Contact;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class ContactMessagesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
/** @var \Illuminate\Database\Eloquent\Builder $contactMessages */
|
||||
$contactMessages = Contact::query();
|
||||
|
||||
if ($request->search) {
|
||||
$this->searchQuery(
|
||||
$contactMessages,
|
||||
$request->search,
|
||||
'order_number',
|
||||
'firstname',
|
||||
'lastname',
|
||||
'subject',
|
||||
'email',
|
||||
);
|
||||
}
|
||||
|
||||
$this->sortQuery($contactMessages);
|
||||
$searchFields = trans('Réf, Nom, Prénom, Objet, E-mail');
|
||||
|
||||
$contactMessages = $contactMessages->orderBy('done', 'ASC')
|
||||
->orderBy('created_at', 'DESC')->paginate();
|
||||
|
||||
return view('back::pages.contacts.index', compact('contactMessages', 'searchFields'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show contact message
|
||||
*
|
||||
* @param Contact $contact
|
||||
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
|
||||
*/
|
||||
public function show(Contact $contact)
|
||||
{
|
||||
return view('back::pages.contacts.show', [
|
||||
'contactMessage' => $contact
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show contact message
|
||||
*
|
||||
* @param Contact $contact
|
||||
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
|
||||
*/
|
||||
public function done(Contact $contact)
|
||||
{
|
||||
$contact->done = true;
|
||||
if ($contact->saveOrFail()) {
|
||||
return response()->redirectToRoute('bo.contacts.index')->with(
|
||||
'success',
|
||||
trans('Le message à été marqué comme traité')
|
||||
);
|
||||
}
|
||||
return back();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \App\Models\Contact $contact
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(Contact $contact)
|
||||
{
|
||||
if ($contact->deleteOrFail()) {
|
||||
return redirect()
|
||||
->route('bo.contacts.index')
|
||||
->with('warning', trans(
|
||||
':model a bien été supprimé',
|
||||
['model' => __('Message de contact')]
|
||||
));
|
||||
}
|
||||
return back();
|
||||
}
|
||||
}
|
||||
56
app/Http/Controllers/Bo/ContentController.php
Normal file
56
app/Http/Controllers/Bo/ContentController.php
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Content;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class ContentController extends Controller
|
||||
{
|
||||
/**
|
||||
* 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();
|
||||
|
||||
if ($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||
$banner = $request->banner;
|
||||
$title = $request->title;
|
||||
$chapeau = $request->chapeau;
|
||||
$maintext = $request->value;
|
||||
|
||||
$request->validate([
|
||||
'banner' => 'image|mimes:jpeg,png,jpg|max:2048|dimensions:max_width=' .
|
||||
config('theme.content_banner_maxwidth') .
|
||||
',max_height=' . config('theme.content_banner_maxheight'),
|
||||
'value' => 'required',
|
||||
]);
|
||||
|
||||
if ($banner !== null) {
|
||||
if ($content->banner !== null && file_exists(public_path('images/content/') . $content->banner)) {
|
||||
unlink(public_path('images/content/') . $content->banner);
|
||||
}
|
||||
$imageName = $content->id . '.' . $banner->extension();
|
||||
$banner->move(public_path('images/content'), $imageName);
|
||||
$content->banner = $imageName;
|
||||
}
|
||||
|
||||
$content->title = $title;
|
||||
$content->chapeau = $chapeau;
|
||||
$content->value = $maintext;
|
||||
$content->save();
|
||||
|
||||
return redirect()->route('bo.content', ['key' => $content->key, 'content' => $content])
|
||||
->with('success', 'Modifications enregistrés !');
|
||||
}//end if
|
||||
|
||||
return view('bo.content.manage', compact('content'));
|
||||
}
|
||||
}
|
||||
80
app/Http/Controllers/Bo/CreneauxController.php
Normal file
80
app/Http/Controllers/Bo/CreneauxController.php
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Magasin;
|
||||
use App\Models\TimeslotSetting;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class CreneauxController extends Controller
|
||||
{
|
||||
/**
|
||||
* 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);
|
||||
$timeslotSettings = $magasin->timeslotSettings;
|
||||
if ($timeslotSettings->count() === 0) {
|
||||
// Aucun settings pour ce magasin.
|
||||
$timeslotSettings = $this->makeCreneauxSettings($id);
|
||||
}
|
||||
|
||||
return view('bo.creneaux.settings', compact('timeslotSettings', 'magasin'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve creneaux settings
|
||||
*
|
||||
* @param integer $id
|
||||
* @return mixed
|
||||
*/
|
||||
public function makeCreneauxSettings(int $id)
|
||||
{
|
||||
for ($i = 0; $i < 7; $i++) {
|
||||
$dayset = new TimeslotSetting();
|
||||
$dayset->magasin_id = $id;
|
||||
$dayset->day_index = '' . $i;
|
||||
$dayset->save();
|
||||
}
|
||||
return Magasin::findOrFail($id)->timeslotSettings;
|
||||
}
|
||||
|
||||
/**
|
||||
* save settings
|
||||
*
|
||||
* @param Request $request
|
||||
* @param integer $id
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function updateSettings(Request $request, int $id)
|
||||
{
|
||||
$plage = $request->plage;
|
||||
$magasin_id = $id;
|
||||
|
||||
foreach ($plage as $index => $day) {
|
||||
$setting = TimeslotSetting::where('day_index', '' . $index)
|
||||
->where('magasin_id', $magasin_id)
|
||||
->firstOrFail();
|
||||
// $setting->magasin_id = $magasin_id; ne doit pas changer
|
||||
$setting->morning_start = $day['morning_start'];
|
||||
$setting->morning_end = $day['morning_end'];
|
||||
$setting->afternoon_start = $day['afternoon_start'];
|
||||
$setting->afternoon_end = $day['afternoon_end'];
|
||||
$setting->interval = $day['interval'];
|
||||
$setting->max_orders_per_interval = $day['max_orders_per_interval'];
|
||||
$setting->min_order_preparation = $day['min_order_preparation'];
|
||||
$setting->save();
|
||||
}
|
||||
|
||||
return redirect()->route('bo.creneaux.settings', $magasin_id)->with('success', 'Modifications enregistrées !');
|
||||
}
|
||||
}
|
||||
|
|
@ -13,6 +13,6 @@ class DashboardController extends Controller
|
|||
*/
|
||||
public function index()
|
||||
{
|
||||
return view('back::pages.dashboard');
|
||||
return view('bo.dashboard');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,72 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Bo\DeliveryMode\UpdateDeliveryModeRequest;
|
||||
use App\Models\DeliveryMode;
|
||||
|
||||
class DeliveryModeController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$deliveryModes = DeliveryMode::paginate();
|
||||
|
||||
return view('back::pages.delivery-modes.index', compact('deliveryModes'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \App\Models\DeliveryMode $deliveryMode
|
||||
* @return \Illuminate\Http\Response
|
||||
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
|
||||
*/
|
||||
public function edit(DeliveryMode $deliveryMode)
|
||||
{
|
||||
$this->authorize('update', DeliveryMode::class);
|
||||
return view('back::pages.delivery-modes.edit', compact(
|
||||
'deliveryMode'
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Bo\UpdateDeliveryModeRequest $request
|
||||
* @param \App\Models\DeliveryMode $deliveryMode
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(UpdateDeliveryModeRequest $request, DeliveryMode $deliveryMode)
|
||||
{
|
||||
$this->authorize('update', DeliveryMode::class);
|
||||
$deliveryMode->fill($request->validated());
|
||||
if ($deliveryMode->saveOrFail()) {
|
||||
return redirect()->back()
|
||||
->with('success', trans(
|
||||
':model a été mis à jour',
|
||||
['model' => trans('Mode de livraison')]
|
||||
));
|
||||
}
|
||||
return back();
|
||||
}
|
||||
|
||||
/**
|
||||
* Change model status
|
||||
*
|
||||
* @param DeliveryMode $model
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function changeStatus(DeliveryMode $model)
|
||||
{
|
||||
$this->authorize('update', DeliveryMode::class);
|
||||
$model->status = !$model->status;
|
||||
$model->saveOrFail();
|
||||
return redirect()->back();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,170 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
use App\Enums\Discount\DiscountType;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Bo\Discounts\StoreDiscountRequest;
|
||||
use App\Http\Requests\Bo\Discounts\UpdateDiscountRequest;
|
||||
use App\Models\Discount;
|
||||
use App\Models\Product;
|
||||
use App\Traits\Controllers\UpdateModelStatus;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class DiscountController extends Controller
|
||||
{
|
||||
use UpdateModelStatus;
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
/** @var \Illuminate\Database\Eloquent\Builder $discounts */
|
||||
$discounts = Discount::query();
|
||||
|
||||
if ($request->search) {
|
||||
$this->searchQuery(
|
||||
$discounts,
|
||||
$request->search,
|
||||
// * Search in ranges
|
||||
function (Builder $q) use ($request) {
|
||||
$types = \collect(DiscountType::toArray())->filter(function (DiscountType $type) use ($request) {
|
||||
$test = Str::contains(
|
||||
Str::lower($type->label),
|
||||
\explode(' ', Str::lower(\trim($request->search)))
|
||||
);
|
||||
return Str::contains(
|
||||
Str::lower($type->label),
|
||||
\explode(' ', Str::lower(\trim($request->search)))
|
||||
);
|
||||
});
|
||||
$q->orWhereIn('type', $types);
|
||||
},
|
||||
'discount_value'
|
||||
);
|
||||
} //end if
|
||||
|
||||
$this->sortQuery($discounts);
|
||||
$searchFields = trans('Type');
|
||||
|
||||
$discounts->orderBy('updated_at', 'DESC');
|
||||
$discounts = $discounts->paginate();
|
||||
|
||||
return view('back::pages.discounts.index', compact('discounts', 'searchFields'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
$existingProds = Product::all();
|
||||
|
||||
return view('back::pages.discounts.create', \compact(
|
||||
'existingProds'
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Bo\Discounts\StoreDiscountRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(StoreDiscountRequest $request)
|
||||
{
|
||||
return DB::transaction(function () use ($request) {
|
||||
$discount = new Discount();
|
||||
|
||||
$discount->fill($request->validated());
|
||||
|
||||
if ($discount->saveOrFail()) {
|
||||
$discount->associateProducts($request->prods);
|
||||
|
||||
$discount->saveOrFail();
|
||||
return redirect()
|
||||
->route('bo.discounts.edit', $discount)
|
||||
->with('success', trans(
|
||||
':model a été créé',
|
||||
['model' => Str::singular(trans('models.classes.discounts'))]
|
||||
));
|
||||
}
|
||||
return back();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \App\Models\Discount $discount
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit(Discount $discount)
|
||||
{
|
||||
/** @var \Illuminate\Database\Eloquent\Collection<mixed,\App\Models\Product> */
|
||||
$selectedProds = $discount->products;
|
||||
/** @var \Illuminate\Database\Eloquent\Collection<mixed,\App\Models\Product> */
|
||||
$existingProds = Product::query()->whereNotIn('id', $selectedProds->pluck('id'))->get();
|
||||
|
||||
return view('back::pages.discounts.edit', [
|
||||
'discountModel' => $discount,
|
||||
'existingProds' => $existingProds,
|
||||
'selectedProds' => $selectedProds
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Bo\Discounts\UpdateDiscountRequest $request
|
||||
* @param \App\Models\Discount $discount
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(UpdateDiscountRequest $request, Discount $discount)
|
||||
{
|
||||
return DB::transaction(function () use ($request, $discount) {
|
||||
// * Minicrud fill
|
||||
$discount->fill($request->validated());
|
||||
|
||||
$discount->associateProducts($request->prods);
|
||||
|
||||
if ($discount->saveOrFail()) {
|
||||
return redirect()
|
||||
->route('bo.discounts.edit', $discount)
|
||||
->with('success', trans(
|
||||
':model a été mis à jour',
|
||||
['model' => Str::singular(trans('models.classes.discounts'))]
|
||||
));
|
||||
} //end if
|
||||
return back();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \App\Models\Discount $discount
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(Discount $discount)
|
||||
{
|
||||
if ($discount->deleteOrFail()) {
|
||||
return redirect()
|
||||
->route('bo.discounts.index')
|
||||
->with('warning', trans(
|
||||
':model a bien été supprimé',
|
||||
['model' => Str::singular(trans('models.classes.discounts'))]
|
||||
));
|
||||
}
|
||||
return back();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
|
||||
class DownloadController extends Controller
|
||||
{
|
||||
/**
|
||||
* Download a file from upload using control access
|
||||
* Must be authenticated.
|
||||
*
|
||||
* @param string $filePath
|
||||
* @return \Symfony\Component\HttpFoundation\BinaryFileResponse
|
||||
*/
|
||||
public function download(string $filePath): StreamedResponse
|
||||
{
|
||||
if (!\auth('backend')->check()) {
|
||||
abort(404);
|
||||
}
|
||||
/** @var \Illuminate\Filesystem\FilesystemAdapter */
|
||||
$disk = Storage::disk('uploads');
|
||||
if (!$disk->exists($filePath)) {
|
||||
abort(404);
|
||||
}
|
||||
return response()->stream(function () use ($disk, $filePath) {
|
||||
$stream = $disk->readStream($filePath);
|
||||
\fpassthru($stream);
|
||||
\fclose($stream);
|
||||
}, 200, [
|
||||
'Content-Type' => File::mimeType($disk->path($filePath)),
|
||||
'Content-Length' => $disk->size($filePath),
|
||||
'Content-Disposition' => 'inline',
|
||||
]);
|
||||
}
|
||||
}
|
||||
70
app/Http/Controllers/Bo/FaqController.php
Normal file
70
app/Http/Controllers/Bo/FaqController.php
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Faq;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class FaqController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$faq = Faq::all();
|
||||
return view('bo.faq.index', compact('faq'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update faq data.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function saveDatas(Request $request)
|
||||
{
|
||||
$faq = $request->faq;
|
||||
|
||||
$looplimit = count($faq);
|
||||
for ($i = 0; $i < $looplimit; $i++) {
|
||||
$faqToInsert = !empty($faq[$i]["question"]) && !empty($faq[$i]["answer"]);
|
||||
if (isset($faq[$i]["id"]) && $faq[$i]["id"] !== null && $faqToInsert) {
|
||||
$f = Faq::findOrFail($faq[$i]["id"]);
|
||||
$f->question = $faq[$i]["question"];
|
||||
$f->answer = $faq[$i]["answer"];
|
||||
$f->save();
|
||||
} else {
|
||||
if ($faqToInsert) {
|
||||
$c = Faq::updateOrCreate([
|
||||
'question' => $faq[$i]["question"],
|
||||
'answer' => $faq[$i]["answer"]
|
||||
]);
|
||||
$faq[$i]["id"] = $c->id;
|
||||
} else {
|
||||
unset($faq[$i]);
|
||||
$i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $faq;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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->delete();
|
||||
|
||||
return "Suppression terminée !";
|
||||
}
|
||||
}
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Bo\UpdateGeneralConfigRequest;
|
||||
use App\Models\GeneralConfig;
|
||||
|
||||
class GeneralConfigController extends Controller
|
||||
{
|
||||
/**
|
||||
* General config index
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
/** @var \Illuminate\Pagination\LengthAwarePaginator $configList */
|
||||
$configList = GeneralConfig::query()->where('data', '!=', '[]')->paginate();
|
||||
return view('back::pages.general-configs.index', compact('configList'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit general config
|
||||
*
|
||||
* @param \App\Models\GeneralConfig $config
|
||||
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factor
|
||||
*/
|
||||
public function edit(GeneralConfig $config)
|
||||
{
|
||||
return view('back::pages.general-configs.edit', ['config' => $config]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update General
|
||||
*
|
||||
* @param \App\Http\Requests\UpdateGeneralConfigRequest $request
|
||||
* @param \App\Models\GeneralConfig $config
|
||||
* @return voi\Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function update(UpdateGeneralConfigRequest $request, GeneralConfig $config)
|
||||
{
|
||||
$config->fill(array_replace_recursive(
|
||||
\json_decode(\json_encode($config->toArray()), true),
|
||||
$request->validated()
|
||||
));
|
||||
$config->saveOrFail();
|
||||
return redirect()->route('bo.general_configs.edit', $config)
|
||||
->with('success', 'Enregistré !');
|
||||
}
|
||||
}
|
||||
208
app/Http/Controllers/Bo/MagasinsController.php
Normal file
208
app/Http/Controllers/Bo/MagasinsController.php
Normal file
|
|
@ -0,0 +1,208 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Magasin;
|
||||
use App\Models\CollecteException;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class MagasinsController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$magasins = Magasin::all();
|
||||
return view('bo.magasins.index', compact('magasins'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
return view('bo.magasins.create');
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'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',
|
||||
'postcode' => 'required',
|
||||
'city' => 'required|string|max:255',
|
||||
]);
|
||||
|
||||
$shop = Magasin::create($request->except('_token'));
|
||||
return redirect()->route('bo.magasins.edit', $shop->id)->with('success', 'Nouveau Magasin enregistré !');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param integer $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit(int $id)
|
||||
{
|
||||
$magasin = Magasin::findOrFail($id);
|
||||
$exceptionsCollecte = $magasin->collecteExceptions()->orderBy('date')->get();
|
||||
return view('bo.magasins.edit', compact('magasin', 'exceptionsCollecte'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
$request->validate([
|
||||
'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',
|
||||
'postcode' => 'required',
|
||||
'city' => 'required|string|max:255',
|
||||
]);
|
||||
|
||||
$shop = Magasin::findOrFail($id);
|
||||
$shop->fill($request->except('_token'))->save();
|
||||
return redirect()->route('bo.magasins.edit', $shop->id)->with('success', 'Modifications enregistrés !');
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param integer $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(int $id)
|
||||
{
|
||||
$shop = Magasin::findOrFail($id);
|
||||
|
||||
$count = Magasin::count();
|
||||
|
||||
if ($count === 1) {
|
||||
return redirect()->back()
|
||||
->withErrors("Suppression impossible : Vous devez conserver au moins 1 point de retrait.");
|
||||
}
|
||||
$shop->delete();
|
||||
return redirect()->route('bo.magasins.index');
|
||||
}
|
||||
|
||||
/**
|
||||
* bo
|
||||
* ajx : affichage d'infos sur un magasin
|
||||
*
|
||||
* @param integer $id
|
||||
* @param string|null $mode
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function getMagasinInfo(int $id, string $mode = null)
|
||||
{
|
||||
$magasin = Magasin::findOrFail($id);
|
||||
if (!is_null($mode)) {
|
||||
if ($mode == "tippy") {
|
||||
return view('bo.magasins.tippy-card', compact('magasin'));
|
||||
}
|
||||
if ($mode == "json") {
|
||||
return $magasin;
|
||||
}
|
||||
return view('bo.magasins.info-card', compact('magasin'));
|
||||
}
|
||||
return view('bo.magasins.info-popup', compact('magasin'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Save collect exceptions
|
||||
*
|
||||
* @param Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function saveExceptions(Request $request)
|
||||
{
|
||||
$collecteException = $request->collecte_exception;
|
||||
|
||||
$looplimit = count($collecteException);
|
||||
for ($i = 0; $i < $looplimit; $i++) {
|
||||
$collecteExceptionToInsert = !empty($collecteException[$i]["date"]);
|
||||
if (
|
||||
isset($collecteException[$i]["id"]) &&
|
||||
$collecteException[$i]["id"] !== null &&
|
||||
$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->save();
|
||||
} else {
|
||||
if ($collecteExceptionToInsert) {
|
||||
$ce = CollecteException::updateOrCreate([
|
||||
'date' => $collecteException[$i]["date"],
|
||||
'comment' => $collecteException[$i]["comment"],
|
||||
'magasin_id' => $collecteException[$i]["magasin_id"]
|
||||
]);
|
||||
$collecteException[$i]["id"] = $ce->id;
|
||||
} else {
|
||||
unset($collecteException[$i]);
|
||||
$i--;
|
||||
}
|
||||
}
|
||||
}//end for
|
||||
|
||||
// Remet dans l'ordre avant de renvoyer.
|
||||
$this->arraySortByColumn($collecteException, "date");
|
||||
return $collecteException;
|
||||
}
|
||||
|
||||
/**
|
||||
* helper function
|
||||
*
|
||||
* @param array $array
|
||||
* @param string $column
|
||||
* @param integer $direction
|
||||
* @return void
|
||||
*/
|
||||
public function arraySortByColumn(array &$array, string $column, int $direction = SORT_ASC)
|
||||
{
|
||||
$reference_array = array();
|
||||
|
||||
foreach ($array as $key => $row) {
|
||||
$reference_array[$key] = $row[$column];
|
||||
}
|
||||
|
||||
array_multisort($reference_array, $direction, $array);
|
||||
}
|
||||
|
||||
/**
|
||||
* delete collecte exception
|
||||
*
|
||||
* @param Request $request
|
||||
* @return string
|
||||
*/
|
||||
public function destroyExceptions(Request $request)
|
||||
{
|
||||
$collecteException = CollecteException::findOrFail($request->id);
|
||||
$collecteException->delete();
|
||||
|
||||
return "Suppression terminée !";
|
||||
}
|
||||
}
|
||||
|
|
@ -1,110 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
use App\Enums\Order\ValidationStatus;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Bo\Orders\ChangeOrderValidationStatusRequest;
|
||||
use App\Models\Order;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class OrderController extends Controller
|
||||
{
|
||||
/**
|
||||
* If true the index action will only display today orders
|
||||
* @var false
|
||||
*/
|
||||
private $indexModeTodayOnly = false;
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
/** @var \Illuminate\Database\Eloquent\Builder $orders */
|
||||
$orders = Order::query();
|
||||
|
||||
if ($request->search) {
|
||||
$this->searchQuery(
|
||||
$orders,
|
||||
$request->search,
|
||||
null,
|
||||
'label'
|
||||
);
|
||||
}
|
||||
|
||||
$this->sortQuery($orders);
|
||||
$searchFields = trans('Réference');
|
||||
|
||||
if ($this->indexModeTodayOnly) {
|
||||
$orders->whereHas('timeslot', function (Builder $q) {
|
||||
$q->whereDate('slot', \now()->today());
|
||||
});
|
||||
}
|
||||
|
||||
$orders->orderBy('updated_at', 'DESC');
|
||||
$orders = $orders->paginate(10);
|
||||
|
||||
return view('back::pages.orders.index', compact('orders', 'searchFields'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
|
||||
*/
|
||||
public function indexToday(Request $request)
|
||||
{
|
||||
$this->indexModeTodayOnly = true;
|
||||
return $this->callAction('index', ['request' => $request]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param \App\Models\Order $order
|
||||
* @return \Illuminate\Http\Response
|
||||
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
|
||||
*/
|
||||
public function show(Order $order)
|
||||
{
|
||||
// phpcs:enable
|
||||
return view('back::pages.orders.show', compact('order'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Mettre a jour le status de validation d'une commande
|
||||
*
|
||||
* @param \App\Http\Requests\Bo\Orders\ChangeOrderValidationStatusRequest $request
|
||||
* @param \App\Models\Order $order
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function changeValidationStatus(ChangeOrderValidationStatusRequest $request, Order $order)
|
||||
{
|
||||
return DB::transaction(function () use ($request, $order) {
|
||||
$order->validation_status = $request->validation_status;
|
||||
switch ($request->validation_status) {
|
||||
case ValidationStatus::validated()->value:
|
||||
$order->saveOrFail();
|
||||
return \back()->with('success', \trans(
|
||||
'La commande vient d\'être validée, le client recevra une notification.'
|
||||
));
|
||||
case ValidationStatus::cancelled()->value:
|
||||
$order->saveOrFail();
|
||||
return \back()->with('warning', \trans(
|
||||
'La commande à été annulée, le client recevra une notification.'
|
||||
));
|
||||
case ValidationStatus::pending()->value:
|
||||
return \back()->with('errors', \trans('Il faut choisir un statut pour cette commande.'));
|
||||
default:
|
||||
throw new \RuntimeException("Unhandled status `{$request->validation_status}`");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
650
app/Http/Controllers/Bo/OrdersController.php
Normal file
650
app/Http/Controllers/Bo/OrdersController.php
Normal file
|
|
@ -0,0 +1,650 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Order;
|
||||
use App\Models\OrderLine;
|
||||
use App\Models\OrdersProducts;
|
||||
use App\Models\Product;
|
||||
use App\Models\Timeslot;
|
||||
use App\Models\Magasin;
|
||||
use App\Http\Requests\SortOrders;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use App\Mail\OrderStatusMail;
|
||||
use App\Mail\OrderConfirmMail;
|
||||
use App\Mail\OrderConfirmAdminMail;
|
||||
use App\Jobs\CsvOrderWrite;
|
||||
use App\Models\Customers;
|
||||
use App\Models\OrdersStatus;
|
||||
use App\Models\Setting;
|
||||
use Carbon\Carbon;
|
||||
use Carbon\CarbonImmutable;
|
||||
use Carbon\CarbonInterval;
|
||||
use Gloudemans\Shoppingcart\Facades\Cart;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
|
||||
class OrdersController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param \App\Http\Requests\SortOrders $request
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function index(SortOrders $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);
|
||||
|
||||
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)
|
||||
{
|
||||
$orders = $this->filterOrders($request);
|
||||
|
||||
// Filter today.
|
||||
$today = CarbonImmutable::now()->startOfDay();
|
||||
$orders = $orders->whereHas('timeslot', function ($q) use ($today) {
|
||||
$q->where('day', '=', $today->format('d/m/Y'));
|
||||
});
|
||||
|
||||
|
||||
$orders = $orders->get();
|
||||
return view('bo.orders.index', compact('orders', 'today'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter orders
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
protected function filterOrders(Request $request)
|
||||
{
|
||||
$orders = Order::query();
|
||||
|
||||
if ($request->rst) {
|
||||
Session::remove('orders.sort_col');
|
||||
Session::remove('orders.sort_way');
|
||||
}
|
||||
if ($request->sort_col) {
|
||||
Session::put('orders.sort_col', $request->sort_col);
|
||||
Session::save();
|
||||
}
|
||||
if ($request->sort_way) {
|
||||
Session::put('orders.sort_way', $request->sort_way);
|
||||
Session::save();
|
||||
}
|
||||
|
||||
if (Session::has('orders.sort_col') and Session::has('orders.sort_way')) {
|
||||
switch (Session::get('orders.sort_col')) {
|
||||
case 'date':
|
||||
$orders = $orders->orderBy('date', Session::get('orders.sort_way'));
|
||||
break;
|
||||
case 'status_id':
|
||||
$orders = $orders->orderBy('status_id', Session::get('orders.sort_way'));
|
||||
break;
|
||||
case 'magasin_id':
|
||||
$orders = $orders->select('orders.*');
|
||||
$orders = $orders->leftJoin('timeslots', 'timeslots.order_id', '=', 'orders.id');
|
||||
$orders = $orders->leftJoin('magasins', 'timeslots.magasin_id', '=', 'magasins.id');
|
||||
$orders = $orders->orderBy('magasins.id', Session::get('orders.sort_way'));
|
||||
break;
|
||||
case 'date_retrait':
|
||||
$orders = $orders->select('orders.*');
|
||||
$orders = $orders->leftJoin('timeslots', 'timeslots.order_id', '=', 'orders.id');
|
||||
$orders = $orders->orderBy('timeslots.day', Session::get('orders.sort_way'));
|
||||
$orders = $orders->orderBy('timeslots.time', Session::get('orders.sort_way'));
|
||||
break;
|
||||
case 'customer_id':
|
||||
$orders = $orders->orderBy('customer_id', Session::get('orders.sort_way'));
|
||||
break;
|
||||
} //end switch
|
||||
} else {
|
||||
$orders->orderByDesc('date');
|
||||
}//end if
|
||||
|
||||
return $orders;
|
||||
}
|
||||
|
||||
/**
|
||||
* action de changement de statut vers l'avant
|
||||
* envoi de mails transctionnels
|
||||
*
|
||||
* @param string $reference Reference de la commande.
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function changeStatus(string $reference)
|
||||
{
|
||||
$order = Order::where('reference', $reference)->first();
|
||||
$order->status_id = $order->status_id + 1;
|
||||
$order->save();
|
||||
|
||||
// Send confirm mail.
|
||||
Mail::to($order->customer->email)->send(new OrderStatusMail($order));
|
||||
|
||||
return back()->with('success', "Changement de status enregistré pour la commande " . $order->reference . ".");
|
||||
}
|
||||
|
||||
/**
|
||||
* mise au statut annulé d'une commande
|
||||
*
|
||||
* @param string $reference
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function cancelOrder(string $reference)
|
||||
{
|
||||
$order = Order::where('reference', $reference)->first();
|
||||
$order->status_id = 7;
|
||||
$order->save();
|
||||
|
||||
return back()->with('success', "La commande " . $order->reference . " à été annulée.");
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Supprimer cette méthode qui repose sur un modèle de donnée osolète.
|
||||
* ajout de produits à la commande
|
||||
*
|
||||
* @param string $orderReference
|
||||
* @param integer $productId
|
||||
* @param integer $quantity
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function addProduct(string $orderReference, int $productId, int $quantity)
|
||||
{
|
||||
$product = Product::findOrFail($productId);
|
||||
$order = Order::where('reference', $orderReference)->first();
|
||||
|
||||
$order->total = $order->total + (($product->price - $product->price_buy) * $quantity);
|
||||
$orderProduct = new OrdersProducts();
|
||||
$orderProduct->product_id = $product->id;
|
||||
$orderProduct->order_id = $order->id;
|
||||
$orderProduct->quantity = $quantity;
|
||||
$orderProduct->save();
|
||||
|
||||
|
||||
return redirect()->route('bo.orders')->with('success', "Le produit à été ajouté.");
|
||||
}
|
||||
|
||||
/**
|
||||
* front
|
||||
* récap panier du tunnel de commande
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function recapOrder()
|
||||
{
|
||||
$activestep = 2;
|
||||
Cart::instance('panier');
|
||||
$cart = Cart::content();
|
||||
|
||||
$cartInfos = array(
|
||||
"totalTTC" => Cart::total(),
|
||||
// Total des taxes.
|
||||
'totalTVA' => Cart::tax(),
|
||||
// Total sans les taxes.
|
||||
'totalHT' => Cart::subtotal(),
|
||||
// Poids total des items.
|
||||
'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'));
|
||||
}
|
||||
|
||||
/**
|
||||
* front
|
||||
* Storing order from sales tunnel
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function store()
|
||||
{
|
||||
// Save.
|
||||
Cart::instance('panier');
|
||||
$order = new Order();
|
||||
// Generate order ref.
|
||||
$order->reference = $this->generateOrderRef();
|
||||
$order->date = Carbon::now();
|
||||
$order->status_id = 1;
|
||||
$order->total = str_replace(',', '.', str_replace(' ', '', Cart::total()));
|
||||
$order->customer_id = Auth::user()->id;
|
||||
|
||||
$order->save();
|
||||
|
||||
// Order_id.
|
||||
Cart::instance('panier');
|
||||
$cart = Cart::content();
|
||||
foreach ($cart as $cartItem) {
|
||||
$order_line = new OrderLine();
|
||||
$order_line->order_id = $order->id;
|
||||
$order_line->product_id = $cartItem->model->id;
|
||||
$order_line->quantity = $cartItem->qty;
|
||||
// Gross unit price.
|
||||
$order_line->unit_price = $cartItem->model->priceHt;
|
||||
// Discount per unit.
|
||||
$order_line->unit_discount = $cartItem->model->discountAmount;
|
||||
// Tax rate for this line.
|
||||
$order_line->tax_rate = $cartItem->taxRate;
|
||||
// Tax amount par unit.
|
||||
$order_line->unit_tax = round(
|
||||
(($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;
|
||||
// Gross amount for the line.
|
||||
$order_line->total_ht = ($order_line->unit_price - $order_line->unit_discount) * $order_line->quantity;
|
||||
// Tax amount for the line.
|
||||
$order_line->total_tax = $order_line->unit_tax * $order_line->quantity;
|
||||
// Total TTC avec remises de la ligne.
|
||||
$order_line->total_ttc = $order_line->total_ht + $order_line->total_tax;
|
||||
|
||||
$order_line->save();
|
||||
}//end foreach
|
||||
|
||||
// Empty cart.
|
||||
Cart::destroy();
|
||||
// Then redirect.
|
||||
return redirect()->route('sales.pick-slot', ['reference' => $order->reference]);
|
||||
}
|
||||
|
||||
/**
|
||||
* generate order Reference
|
||||
* for a new order
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function generateOrderRef()
|
||||
{
|
||||
|
||||
// Format : YYYYMMDDHHMM000.
|
||||
$now = Carbon::now();
|
||||
// Count todays orders.
|
||||
$countorders = Order::whereDate('created_at', Carbon::today())->count();
|
||||
// Add one.
|
||||
$countorders++;
|
||||
$ref = $now->isoFormat('YYYYMMDDHHmm') . str_pad($countorders, 3, "0", STR_PAD_LEFT);
|
||||
return $ref;
|
||||
}
|
||||
|
||||
/**
|
||||
* front tunnel de commande étape 3 : choix de créneau
|
||||
*
|
||||
* @param string $reference
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function timeSlotPick(string $reference)
|
||||
{
|
||||
$activestep = 3;
|
||||
if (config('theme.multi_relay')) {
|
||||
$magasin = Magasin::all();
|
||||
} else {
|
||||
$magasin = Magasin::first();
|
||||
}
|
||||
|
||||
$availCreneaux = array();
|
||||
$order = Order::where('reference', '=', $reference)->firstOrFail();
|
||||
|
||||
return view('sales.pick-slot', compact('activestep', 'availCreneaux', 'order', 'magasin'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
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.
|
||||
$plage_days = Setting::where('key', 'order_withdrawal_period')->firstOrFail()->value;
|
||||
|
||||
$magasin = Magasin::findOrFail($id);
|
||||
$timeslotSettings = $magasin->timeslotSettings;
|
||||
// $timeslotSettings = TimeslotSetting::all();
|
||||
// Fabriquons un tableau recap.
|
||||
$plage = array();
|
||||
foreach ($timeslotSettings as $day) {
|
||||
$plage[$day->day_index] = array(
|
||||
'morning_start' => $day->morning_start,
|
||||
'morning_end' => $day->morning_end,
|
||||
'afternoon_start' => $day->afternoon_start,
|
||||
'afternoon_end' => $day->afternoon_end,
|
||||
'interval' => $day->interval,
|
||||
'min_order_preparation' => $day->min_order_preparation,
|
||||
'max_orders_per_interval' => $day->max_orders_per_interval
|
||||
);
|
||||
}
|
||||
|
||||
// Génération des plages.
|
||||
// Start today.
|
||||
$today = CarbonImmutable::now()->startOfDay();
|
||||
$weekDay = $today->weekday();
|
||||
// Final boundary (permet de limiter la liste des jours d'exception).
|
||||
$finalday = $today->add($plage_days, 'day');
|
||||
$now = CarbonImmutable::now();
|
||||
// Jours exceptions.
|
||||
$noCollectDays = $magasin->collecteExceptions()
|
||||
->whereDate('date', '>', $now)
|
||||
->whereDate('date', '<=', $finalday)
|
||||
->orderBy('date')->get();
|
||||
|
||||
$delaiPrepa = CarbonInterval::createFromFormat('h:i', $plage[$weekDay]['min_order_preparation'] ?? '01:00');
|
||||
|
||||
$availCreneaux = array();
|
||||
|
||||
for ($i = 0; $i < $plage_days; $i++) {
|
||||
$current = $today->add($i, 'day');
|
||||
$weekDay = $current->weekday();
|
||||
$interval = CarbonInterval::createFromFormat('h:i', $plage[$weekDay]['interval'] ?? '00:15');
|
||||
|
||||
// Si c'est un jour exception skip.
|
||||
$skip = false;
|
||||
foreach ($noCollectDays as $not_today) {
|
||||
if ($current->isSameDay($not_today->date)) {
|
||||
$skip = true;
|
||||
}
|
||||
}
|
||||
if ($skip) {
|
||||
continue;
|
||||
}
|
||||
$availCreneaux[$current->format('d/m/Y')] = array();
|
||||
// Matinée.
|
||||
if (!empty($plage[$weekDay]['morning_start'])) {
|
||||
$currentTime = Carbon::createFromTimeString($plage[$weekDay]['morning_start']);
|
||||
$endTime = Carbon::createFromTimeString($plage[$weekDay]['morning_end']);
|
||||
|
||||
$morningCreneaux = $this->addCreneaux(
|
||||
$plage,
|
||||
$weekDay,
|
||||
$current,
|
||||
$magasin,
|
||||
$now,
|
||||
$today,
|
||||
$delaiPrepa,
|
||||
$interval,
|
||||
$currentTime,
|
||||
$endTime
|
||||
);
|
||||
|
||||
$availCreneaux[$current->format('d/m/Y')] = array_merge(
|
||||
$availCreneaux[$current->format('d/m/Y')],
|
||||
$morningCreneaux
|
||||
);
|
||||
} //end if
|
||||
// Aprem.
|
||||
if (!empty($plage[$weekDay]['afternoon_start'])) {
|
||||
$currentTime = Carbon::createFromTimeString($plage[$weekDay]['afternoon_start']);
|
||||
$endTime = Carbon::createFromTimeString($plage[$weekDay]['afternoon_end']);
|
||||
|
||||
$afternoonCreneaux = $this->addCreneaux(
|
||||
$plage,
|
||||
$weekDay,
|
||||
$current,
|
||||
$magasin,
|
||||
$now,
|
||||
$today,
|
||||
$delaiPrepa,
|
||||
$interval,
|
||||
$currentTime,
|
||||
$endTime
|
||||
);
|
||||
|
||||
$availCreneaux[$current->format('d/m/Y')] = array_merge(
|
||||
$availCreneaux[$current->format('d/m/Y')],
|
||||
$afternoonCreneaux
|
||||
);
|
||||
} //end if
|
||||
}//end for
|
||||
return $availCreneaux;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call ajax pour le composant vue de timeslots.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function getAvailableCreneaux(Request $request)
|
||||
{
|
||||
return $this->getAvailableCreneauxByShop($request->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* front
|
||||
* enregistrement du créneau de collect
|
||||
* et validation de la commande
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \RuntimeException If email missing.
|
||||
*/
|
||||
public function setTimeSlot(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'selectedmagasin' => 'required',
|
||||
'selectedcreneau' => 'required',
|
||||
'ok_cgv' => 'accepted',
|
||||
]);
|
||||
|
||||
$tsday = explode('-', $request->selectedcreneau)[0];
|
||||
$tstime = explode('-', $request->selectedcreneau)[1];
|
||||
$magasin_id = $request->selectedmagasin;
|
||||
$reference = $request->order_ref;
|
||||
$order = Order::where('reference', '=', $reference)->firstOrFail();
|
||||
|
||||
if ($order->status_id == 1) {
|
||||
// On ne traite l'enregistrement que pour les commandes en attente venant de l'étape de récap.
|
||||
// Save timeslot.
|
||||
$timeslot = Timeslot::firstOrNew(['order_id' => $order->id]);
|
||||
$timeslot->order_id = $order->id;
|
||||
$timeslot->magasin_id = $magasin_id;
|
||||
$timeslot->day = $tsday;
|
||||
$timeslot->time = $tstime;
|
||||
$timeslot->save();
|
||||
|
||||
// Save order status.
|
||||
$order->status_id = 3;
|
||||
$order->save();
|
||||
|
||||
// Send confirm mail.
|
||||
Mail::to($order->customer->email)->queue(new OrderConfirmMail($order));
|
||||
|
||||
// Envoi du mail de confirmation aux admins site.
|
||||
/** @var \App\Model\Magasin|null */
|
||||
$shop = Magasin::where('id', $magasin_id)->first();
|
||||
|
||||
if ($shop and $shop->email_confirm) {
|
||||
/** @var string */
|
||||
$toMail = $shop->email_confirm;
|
||||
} else {
|
||||
/** @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 OrderConfirmAdminMail($order));
|
||||
|
||||
// Export commande.
|
||||
if (config('bosettings.regate_orders')) {
|
||||
CsvOrderWrite::dispatch($order);
|
||||
}
|
||||
}//end if
|
||||
|
||||
// Redirect to final confirmation.
|
||||
return redirect()->route('sales.confirm', ['reference' => $order->reference]);
|
||||
}
|
||||
|
||||
/**
|
||||
* generate Order
|
||||
* Test method
|
||||
*
|
||||
* @param string $reference
|
||||
* @return void
|
||||
*/
|
||||
public function generateOrder(string $reference)
|
||||
{
|
||||
$order = Order::where('reference', '=', $reference)->with('lines')->firstOrFail();
|
||||
$job = new CsvOrderWrite($order);
|
||||
$job->handle();
|
||||
dd('end');
|
||||
}
|
||||
|
||||
/**
|
||||
* front
|
||||
* page de confirmation de commande
|
||||
*
|
||||
* @param string $reference
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function confirmOrder(string $reference)
|
||||
{
|
||||
$activestep = 4;
|
||||
|
||||
$idcommande = Session::get('idcommande');
|
||||
$order = Order::where('reference', '=', $reference)->firstOrFail();
|
||||
|
||||
// 1 seul magasin en base pour le moment
|
||||
$magasin = Magasin::find($order->timeslot->magasin->id);
|
||||
|
||||
return view('sales.confirm', compact('activestep', 'order', 'magasin'));
|
||||
}
|
||||
|
||||
/**
|
||||
* bo
|
||||
* ajx : affichage d'infos sur un client
|
||||
*
|
||||
* @param integer $id
|
||||
* @param string|null $mode
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function getCustomerInfo(int $id, string $mode = null)
|
||||
{
|
||||
$cust = Customers::findOrFail($id);
|
||||
if (!is_null($mode)) {
|
||||
if ($mode == "tippy") {
|
||||
return view('bo.customer.tippy-card', compact('cust'));
|
||||
}
|
||||
if ($mode == "json") {
|
||||
return $cust->apiData;
|
||||
}
|
||||
return view('bo.customer.info-card', compact('cust'));
|
||||
}
|
||||
return view('bo.customer.info-popup', compact('cust'));
|
||||
}
|
||||
|
||||
/**
|
||||
* bo : page détail commande
|
||||
*
|
||||
* @param string $reference
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function orderDetail(string $reference)
|
||||
{
|
||||
$order = Order::where('reference', '=', $reference)->firstOrFail();
|
||||
return view('bo.orders.detail', compact('order'));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,381 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
use App\Enums\Product\DefaultProductType;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Bo\Products\CreateProductRequest;
|
||||
use App\Http\Requests\Bo\Products\StoreProductRequest;
|
||||
use App\Http\Requests\Bo\Products\UpdateProductRequest;
|
||||
use App\Models\Product;
|
||||
use App\Models\Range;
|
||||
use App\Models\Tag;
|
||||
use App\Models\XmlInco;
|
||||
use App\Traits\Controllers\UpdateModelStatus;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
use Kwaadpepper\ImageResizer\ImageResizer;
|
||||
|
||||
class ProductController extends Controller
|
||||
{
|
||||
use UpdateModelStatus;
|
||||
|
||||
/**
|
||||
* If true the index action will only display starred products
|
||||
* @var false
|
||||
*/
|
||||
private $indexModeStarredOnly = false;
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
/** @var \Illuminate\Database\Eloquent\Builder $products */
|
||||
$products = Product::query();
|
||||
|
||||
if ($request->search) {
|
||||
$this->searchQuery(
|
||||
$products,
|
||||
$request->search,
|
||||
null,
|
||||
'name',
|
||||
'description',
|
||||
'reference'
|
||||
);
|
||||
} //end if
|
||||
|
||||
if ($request->range) {
|
||||
$products->whereHas('range', function (Builder $q) use ($request) {
|
||||
$q->where('id', $request->range);
|
||||
});
|
||||
}
|
||||
|
||||
if ($request->type) {
|
||||
$products->where('type', $request->type);
|
||||
}
|
||||
|
||||
if ($this->indexModeStarredOnly) {
|
||||
$products->where('star', true);
|
||||
}
|
||||
|
||||
if ($request->orderable) {
|
||||
$products->where('orderable', true);
|
||||
}
|
||||
if ($request->star) {
|
||||
$products->where('star', true);
|
||||
}
|
||||
|
||||
$this->sortQuery($products);
|
||||
$searchFields = trans('Nom, Description, Réf');
|
||||
|
||||
$products->orderBy('updated_at', 'DESC');
|
||||
$products = $products->paginate();
|
||||
|
||||
$ranges = Range::all();
|
||||
|
||||
$productTypes = Product::fetchTypes();
|
||||
|
||||
return view('back::pages.products.index', compact(
|
||||
'products',
|
||||
'ranges',
|
||||
'searchFields',
|
||||
'productTypes'
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* * Index des produits mis en avant
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function starred(Request $request)
|
||||
{
|
||||
$this->indexModeStarredOnly = true;
|
||||
return $this->callAction('index', [$request]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @param \App\Http\Requests\Bo\Products\CreateProductRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function create(CreateProductRequest $request)
|
||||
{
|
||||
/** @var array product type Minicrud config */
|
||||
$minicrudData = Product::fetchTypesInputs()[$request->get('type')];
|
||||
|
||||
$ranges = Range::all();
|
||||
$tags = Tag::all();
|
||||
$existingProds = Product::all();
|
||||
|
||||
$productTypes = Product::fetchTypes();
|
||||
|
||||
return view('back::pages.products.create', \compact(
|
||||
'minicrudData',
|
||||
'productTypes',
|
||||
'existingProds',
|
||||
'ranges',
|
||||
'tags'
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Bo\Products\StoreProductRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(StoreProductRequest $request)
|
||||
{
|
||||
return DB::transaction(function () use ($request) {
|
||||
$product = new Product();
|
||||
|
||||
// * Minicrud fill
|
||||
/** @var array product type Minicrud config */
|
||||
$minicrudData = Product::fetchTypesInputs()[$request->type];
|
||||
|
||||
$product->fill(array_replace_recursive(
|
||||
\json_decode(\json_encode((object)[
|
||||
'data' => $minicrudData
|
||||
]), true),
|
||||
$request->validated()
|
||||
));
|
||||
|
||||
if ($product->saveOrFail()) {
|
||||
$product->associatedProducts()->sync($request->prods);
|
||||
$product->saveOrFail();
|
||||
return redirect()
|
||||
->route('bo.products.edit', $product)
|
||||
->with('success', trans(
|
||||
':model a été créé',
|
||||
['model' => Str::singular(trans('models.classes.products'))]
|
||||
));
|
||||
}
|
||||
return back();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \App\Models\Product $product
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit(Product $product)
|
||||
{
|
||||
$ranges = Range::all();
|
||||
$tags = Tag::all();
|
||||
|
||||
/** @var \Illuminate\Database\Eloquent\Collection<mixed,\App\Models\Product> */
|
||||
$selectedProds = $product->associatedProducts;
|
||||
/** @var \Illuminate\Database\Eloquent\Collection<mixed,\App\Models\Product> */
|
||||
$existingProds = Product::query()->whereNotIn('id', $selectedProds->pluck('id'))->get();
|
||||
|
||||
$productTypes = Product::fetchTypes();
|
||||
|
||||
return view('back::pages.products.edit', [
|
||||
'productModel' => $product,
|
||||
'ranges' => $ranges,
|
||||
'tags' => $tags,
|
||||
'productTypes' => $productTypes,
|
||||
'existingProds' => $existingProds,
|
||||
'selectedProds' => $selectedProds
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Bo\Products\UpdateProductRequest $request
|
||||
* @param \App\Models\Product $product
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(UpdateProductRequest $request, Product $product)
|
||||
{
|
||||
return DB::transaction(function () use ($request, $product) {
|
||||
// * Minicrud fill
|
||||
$product->fill(array_replace_recursive(
|
||||
\json_decode(\json_encode($product->toArray()), true),
|
||||
$request->validated()
|
||||
));
|
||||
|
||||
$product->tags()->sync($request->tag_list);
|
||||
$product->associatedProducts()->sync($request->prods);
|
||||
|
||||
if ($product->saveOrFail()) {
|
||||
return redirect()
|
||||
->route('bo.products.edit', $product)
|
||||
->with('success', trans(
|
||||
':model a été mis à jour',
|
||||
['model' => Str::singular(trans('models.classes.products'))]
|
||||
));
|
||||
} //end if
|
||||
return back();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \App\Models\Product $product
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(Product $product)
|
||||
{
|
||||
if ($product->deleteOrFail()) {
|
||||
return redirect()
|
||||
->route('bo.products.index')
|
||||
->with('warning', trans(
|
||||
':model a bien été supprimé',
|
||||
['model' => Str::singular(trans('models.classes.products'))]
|
||||
));
|
||||
}
|
||||
return back();
|
||||
}
|
||||
|
||||
/**
|
||||
* Associate XmlInco with product
|
||||
*
|
||||
* @param \App\Models\Product $product
|
||||
* @param \App\Models\XmlInco $xml_inco
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function associateXmlInco(Product $product, XmlInco $xml_inco)
|
||||
{
|
||||
// * Allow if auth, request post and product type is inco
|
||||
Gate::allowIf(function ($user) use ($product) {
|
||||
return $user and request()->isMethod('post') and
|
||||
$product->type->value === DefaultProductType::inco()->value;
|
||||
});
|
||||
|
||||
$product->xmlInco()->associate($xml_inco);
|
||||
$product->saveOrFail();
|
||||
return redirect()->route('bo.products.edit', $product)
|
||||
->with('success', trans(
|
||||
':model est associé avec fiche inco \':incoId\' \':descriptif\'',
|
||||
[
|
||||
'model' => Str::singular(trans('models.classes.slides')),
|
||||
'incoId' => $xml_inco->id,
|
||||
'descriptif' => Str::limit($xml_inco->descriptif)
|
||||
]
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Resize an inco picture and save to to the concerned product
|
||||
*
|
||||
* @param \App\Models\Product $product
|
||||
* @param \App\Models\XmlInco $xml_inco
|
||||
* @param integer $picture_index
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \RuntimeException If anthing goes wrong managing disks files.
|
||||
* @throws \Kwaadpepper\ImageResizer\Exceptions\ImageResizerException If resizing the picture fails.
|
||||
* @phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
|
||||
*/
|
||||
public function copyXmlIncoPicture(Product $product, XmlInco $xml_inco, int $picture_index): RedirectResponse
|
||||
{
|
||||
// * Check product is associated.
|
||||
if (!$product->xmlInco) {
|
||||
redirect()->route('bo.products.edit', $product)
|
||||
->withErrors(['xmlInco' => 'Vous devez d\'abord associer une fiche Inco']);
|
||||
}
|
||||
// * Check product inco is the same as requested.
|
||||
if ($product->xmlInco->id !== $xml_inco->id) {
|
||||
redirect()->route('bo.products.edit', $product)
|
||||
->withErrors(['xmlInco' => 'La fiche inco associé ne correspond pas à l\'image']);
|
||||
}
|
||||
|
||||
// * Allow if auth, request post and product type is inco and product has inco media on wanted index.
|
||||
Gate::allowIf(function ($user) use ($product, $xml_inco, $picture_index) {
|
||||
return $user and request()->isMethod('post') and
|
||||
$product->hasAndIsInco() and $xml_inco->mediaList->has($picture_index);
|
||||
});
|
||||
|
||||
/** @var array<string,string> Indexes are filename and imgdata */
|
||||
$picture = $xml_inco->mediaList->get($picture_index);
|
||||
|
||||
/** @var \Illuminate\Filesystem\FilesystemAdapter */
|
||||
$storagePublicDisk = Storage::disk('public');
|
||||
$pictureBaseName = $picture['filename'];
|
||||
$pictureExtension = \pathinfo($picture['filename'], \PATHINFO_EXTENSION);
|
||||
|
||||
/**
|
||||
* We create one file in tmp to be resized
|
||||
* then use resize image to get cached file that we will copy.
|
||||
*/
|
||||
// * Make sys tmp file.
|
||||
if (!($file = tmpfile())) {
|
||||
throw new \RuntimeException('Failed to create tmp file handle');
|
||||
}
|
||||
|
||||
// * Wrap in try catch to always close tmp file
|
||||
try {
|
||||
// * Write picutre on tmp file.
|
||||
$path = stream_get_meta_data($file)['uri'];
|
||||
if (!File::put($path, $picture['imgdata'])) {
|
||||
throw new \RuntimeException('Failed to write content on tmp file');
|
||||
}
|
||||
|
||||
// * Assert theme config is present.
|
||||
if (
|
||||
!config()->has('theme.models.product.picture_maxheight') or
|
||||
!config()->has('theme.models.product.picture_maxwidth')
|
||||
) {
|
||||
throw new \RuntimeException('config theme.models.product needs picture_maxheight and picture_maxwidth');
|
||||
}
|
||||
|
||||
// * Dynamic push config.
|
||||
\config()->set('image-resizer.templates.incoPictureResizeForProduct', [
|
||||
'height' => config()->get('theme.models.product.picture_maxheight', 235),
|
||||
'width' => config()->get('theme.models.product.picture_maxwidth', 235),
|
||||
'format' => $pictureExtension,
|
||||
'inCanvas' => true,
|
||||
'resize' => true,
|
||||
'keepRatio' => true
|
||||
]);
|
||||
|
||||
// * Resize picture using kwaadpepper/image-resizer.
|
||||
$resizedPath = ImageResizer::resizeImageOrIgnore(
|
||||
$path,
|
||||
'incoPictureResizeForProduct'
|
||||
);
|
||||
if (!$storagePublicDisk->has($resizedPath)) {
|
||||
throw new \RuntimeException("Resized picture '$resizedPath' does not exists on 'public' disk");
|
||||
}
|
||||
|
||||
// * Append unique prefix to File original basename
|
||||
$pictureBaseNewName = Str::uuid() . '__' . $pictureBaseName;
|
||||
|
||||
// * Rename picture.
|
||||
$newPathName = \pathinfo($resizedPath, \PATHINFO_DIRNAME) . "/{$pictureBaseNewName}";
|
||||
if (!$storagePublicDisk->move($resizedPath, $newPathName)) {
|
||||
throw new \RuntimeException("Failed to rename '$resizedPath' into '$newPathName'");
|
||||
}
|
||||
|
||||
$product->picture = new \SplFileInfo($storagePublicDisk->path($newPathName));
|
||||
$product->saveOrFail();
|
||||
|
||||
// * remove tmp cached file.
|
||||
$storagePublicDisk->delete($newPathName);
|
||||
} finally {
|
||||
fclose($file);
|
||||
} //end try
|
||||
|
||||
return redirect()->route('bo.products.edit', $product);
|
||||
}
|
||||
}
|
||||
838
app/Http/Controllers/Bo/ProductsController.php
Normal file
838
app/Http/Controllers/Bo/ProductsController.php
Normal file
|
|
@ -0,0 +1,838 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\ProductRequest;
|
||||
use App\Models\OldSlug;
|
||||
use App\Models\FoodProduct;
|
||||
use App\Models\ToolProduct;
|
||||
use App\Models\AnifoodProduct;
|
||||
use App\Models\GarmentProduct;
|
||||
use App\Models\Product;
|
||||
use App\Models\Range;
|
||||
use App\Models\Tag;
|
||||
use App\Models\TaxRate;
|
||||
use App\Models\XmlInco;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Support\Facades\File;
|
||||
|
||||
class ProductsController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$ranges = Range::all();
|
||||
|
||||
$filter_range = $request->query('filter_range');
|
||||
$filter_name = $request->query('filter_name');
|
||||
|
||||
$products = new Product();
|
||||
|
||||
if (!empty($filter_name)) {
|
||||
$products = $products->where('name', 'like', '%' . $filter_name . '%');
|
||||
}
|
||||
if (!empty($filter_range)) {
|
||||
$products = $products->where('range_id', $filter_range);
|
||||
}
|
||||
$products = $products->paginate(10);
|
||||
|
||||
// Ici récupération des infos additionnelles pour affichage dans la liste.
|
||||
foreach ($products as &$product) {
|
||||
if (!empty($product->product_type)) {
|
||||
$product->additionnalProductInfo = $product->additionnalProductInfo($product->product_type);
|
||||
if ($product->additionnalProductInfo === null) {
|
||||
// N'existe pas on renseigne un vide.
|
||||
$product_type = $product->product_type;
|
||||
$modelClass = 'App\Models\\' . ucfirst($product_type);
|
||||
$product->$product_type = new $modelClass();
|
||||
}
|
||||
}
|
||||
}
|
||||
unset($product);
|
||||
return view('bo.products.index', compact('products', 'ranges', 'filter_name', 'filter_range'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
* @param string $product_type
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function create(string $product_type = null)
|
||||
{
|
||||
if (!empty($product_type) && !array_key_exists($product_type, config('theme.enum_product_types'))) {
|
||||
abort(404, "Cette page n'existe pas.");
|
||||
}
|
||||
$modelClass = 'App\Models\\' . ucfirst($product_type);
|
||||
$product = new Product();
|
||||
if (!empty($product_type)) {
|
||||
$product->$product_type = new $modelClass();
|
||||
}
|
||||
$ranges = Range::all();
|
||||
$taxes = TaxRate::all();
|
||||
return view('bo.products.create', compact('product_type', 'product', 'ranges', 'taxes'));
|
||||
}
|
||||
|
||||
/**
|
||||
* store a new product
|
||||
*
|
||||
* @param ProductRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(ProductRequest $request)
|
||||
{
|
||||
// Products fields.
|
||||
$name = $request->name;
|
||||
$description = $request->description;
|
||||
$picture = $request->picture;
|
||||
$picture_large = $request->picture_large;
|
||||
$price = $request->price;
|
||||
$invoicing_unit = $request->invoicing_unit;
|
||||
$priceBuy = $request->price_buy;
|
||||
$order_unit = $request->order_unit;
|
||||
$stock = $request->stock;
|
||||
$reference = $request->reference;
|
||||
$sell_unit = $request->sell_unit;
|
||||
$weight = $request->weight;
|
||||
$weight_unit = $request->weight_unit;
|
||||
$status = $request->status === null ? 0 : 1;
|
||||
$orderable_start = $request->orderable_start_date === null ? null
|
||||
: $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;
|
||||
$slug = Str::slug($name);
|
||||
$rangeId = $request->range_id;
|
||||
$taxRateId = $request->tax_rate_id;
|
||||
|
||||
|
||||
// Check si le slug existe déjà dans cette gamme de produits.
|
||||
$slugExist = Product::where([
|
||||
['range_id', $rangeId],
|
||||
['slug', $slug]
|
||||
])->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.");
|
||||
}
|
||||
|
||||
$product = new Product();
|
||||
$product->name = $name;
|
||||
$product->description = $description;
|
||||
$product->price = $price;
|
||||
$product->invoicing_unit = $invoicing_unit;
|
||||
$product->price_buy = $priceBuy;
|
||||
$product->order_unit = $order_unit;
|
||||
$product->stock = $stock;
|
||||
$product->reference = $reference;
|
||||
$product->sell_unit = $sell_unit;
|
||||
$product->weight = $weight;
|
||||
$product->weight_unit = $weight_unit;
|
||||
$product->slug = $slug;
|
||||
$product->status = $status;
|
||||
$product->orderable_start = $orderable_start;
|
||||
$product->orderable_end = $orderable_end;
|
||||
$product->star = $star;
|
||||
$product->range_id = $rangeId;
|
||||
$product->tax_rate_id = $taxRateId;
|
||||
$product->save();
|
||||
|
||||
// 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();
|
||||
if ($oldSlug && $oldSlug->product_id !== $product->id) {
|
||||
$oldSlug->product_id = $product->id;
|
||||
$oldSlug->save();
|
||||
}
|
||||
|
||||
$str_random = Str::random(5);
|
||||
|
||||
if ($picture !== null) {
|
||||
$imageName = $product->id . '_' . $str_random . '.' . $picture->extension();
|
||||
$picture->move(public_path('images/produits'), $imageName);
|
||||
$product->picture = $imageName;
|
||||
$product->save();
|
||||
}
|
||||
|
||||
if ($picture_large !== null) {
|
||||
$imageName = $product->id . '_' . $str_random . '_large.' . $picture_large->extension();
|
||||
$picture_large->move(public_path('images/produits'), $imageName);
|
||||
$product->picture_large = $imageName;
|
||||
$product->save();
|
||||
}
|
||||
|
||||
// Ajout des infos additionnelles.
|
||||
$product_type = $request->product_type;
|
||||
|
||||
if ($product_type !== null) {
|
||||
$product->product_type = $product_type;
|
||||
$product->save();
|
||||
$methodName = "save" . ucfirst($product_type);
|
||||
$this->$methodName($request, $product->id);
|
||||
}
|
||||
|
||||
|
||||
// Additionnal product info (foodProduct).
|
||||
return redirect()->route('bo.products.index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param integer $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit(int $id)
|
||||
{
|
||||
$product = Product::findOrFail($id);
|
||||
if (!empty($product->product_type)) {
|
||||
$product->additionnalProductInfo = $product->additionnalProductInfo($product->product_type);
|
||||
/**
|
||||
* Above lines equivalent to
|
||||
* $product = Product::with('additionnalProductInfo')->findOrFail($id);
|
||||
*/
|
||||
if ($product->additionnalProductInfo === null) {
|
||||
// N'existe pas on renseigne un vide.
|
||||
$product_type = $product->product_type;
|
||||
$modelClass = 'App\Models\\' . ucfirst($product_type);
|
||||
$product->$product_type = new $modelClass();
|
||||
}
|
||||
}
|
||||
|
||||
$ranges = Range::all();
|
||||
$taxes = TaxRate::all();
|
||||
$existingTags = Tag::all();
|
||||
$selectedtags = $product->tags;
|
||||
|
||||
$existingProds = Product::all();
|
||||
$selectedProds = $product->products;
|
||||
$existingProds = $existingProds->diff($selectedProds);
|
||||
|
||||
return view('bo.products.edit', compact(
|
||||
'product',
|
||||
'ranges',
|
||||
'taxes',
|
||||
'existingTags',
|
||||
'selectedtags',
|
||||
'existingProds',
|
||||
'selectedProds'
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource.
|
||||
*
|
||||
* @param \App\Models\Product $product
|
||||
* @param ProductRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(Product $product, ProductRequest $request)
|
||||
{
|
||||
$orderable_end_time = $request->orderable_end_time === null ? "23:59" : $request->orderable_end_time;
|
||||
|
||||
$name = $request->name;
|
||||
$description = $request->description;
|
||||
$price = $request->price;
|
||||
$invoicing_unit = $request->invoicing_unit;
|
||||
$priceBuy = $request->price_buy;
|
||||
$order_unit = $request->order_unit;
|
||||
$stock = $request->stock;
|
||||
$reference = $request->reference;
|
||||
$sell_unit = $request->sell_unit;
|
||||
$weight = $request->weight;
|
||||
$weight_unit = $request->weight_unit;
|
||||
$status = $request->status === null ? 0 : 1;
|
||||
$orderable_start = $request->orderable_start_date === null ? null
|
||||
: $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;
|
||||
$slug = Str::slug($name);
|
||||
$rangeId = $request->range_id;
|
||||
$taxRateId = $request->tax_rate_id;
|
||||
|
||||
$this->checkSlugExistsWithinRange($request, $rangeId, $slug, $product->id);
|
||||
|
||||
$this->manageProductImages($request->picture, $product, $request->picture_large);
|
||||
|
||||
$product->name = $name;
|
||||
|
||||
$this->saveNewSlugForProduct($product, $slug);
|
||||
|
||||
$product->description = $description;
|
||||
$product->price = $price;
|
||||
$product->invoicing_unit = $invoicing_unit;
|
||||
$product->price_buy = $priceBuy;
|
||||
$product->order_unit = $order_unit;
|
||||
$product->stock = $stock;
|
||||
$product->reference = $reference;
|
||||
$product->sell_unit = $sell_unit;
|
||||
$product->weight = $weight;
|
||||
$product->weight_unit = $weight_unit;
|
||||
$product->slug = $slug;
|
||||
$product->status = $status;
|
||||
$product->orderable_start = $orderable_start;
|
||||
$product->orderable_end = $orderable_end;
|
||||
$product->star = $star;
|
||||
$product->range_id = $rangeId;
|
||||
$product->tax_rate_id = $taxRateId;
|
||||
$product->save();
|
||||
|
||||
// Check si le slug existe dans la table old_slug, auquel cas il est attribué a ce nouveau produit.
|
||||
$this->cleanOldSlug($slug);
|
||||
|
||||
// Ajout des infos additionnelles.
|
||||
$product_type = $request->product_type;
|
||||
|
||||
// Save additionnal.
|
||||
if ($product_type !== null) {
|
||||
$methodName = "save" . ucfirst($product_type);
|
||||
$this->$methodName($request, $product->id);
|
||||
}
|
||||
|
||||
// Tags associés.
|
||||
$this->syncTags($request->tags, $product);
|
||||
|
||||
// Produits associés.
|
||||
$this->syncProduitsAssocies($request->prods, $product);
|
||||
|
||||
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
|
||||
* Otherwise retreive an existing tag to associate its id
|
||||
*
|
||||
* @param \App\Models\Tag $oTag
|
||||
* @return integer
|
||||
*/
|
||||
public function storeTag(Tag $oTag)
|
||||
{
|
||||
$slug = Str::slug($oTag->label);
|
||||
$tag = Tag::where('slug', $slug)->first();
|
||||
if ($tag === null) {
|
||||
// Si on pas encore ce tag on le crée.
|
||||
$tag = new Tag();
|
||||
$tag->label = $oTag->label;
|
||||
$tag->slug = Str::slug($oTag->label);
|
||||
// A new tag is published by default.
|
||||
$tag->status = 1;
|
||||
$tag->order = TagsController::getLastOrder();
|
||||
$tag->save();
|
||||
}
|
||||
return $tag->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* destroy a product (soft delete)
|
||||
*
|
||||
* @param integer $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(int $id)
|
||||
{
|
||||
$product = Product::findOrFail($id);
|
||||
|
||||
if ($product->picture !== null && file_exists(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)
|
||||
) {
|
||||
unlink(public_path('images/produits/') . $product->picture_large);
|
||||
}
|
||||
|
||||
OldSlug::where('product_id', $product->id)->delete();
|
||||
|
||||
$product->delete();
|
||||
return redirect()->route('bo.products.index');
|
||||
}
|
||||
|
||||
/**
|
||||
* check if inco data exists
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return mixed
|
||||
*/
|
||||
public function checkIncoData(Request $request)
|
||||
{
|
||||
$id = $request->id;
|
||||
$xmlInco = XmlInco::find($id);
|
||||
|
||||
if (!empty($xmlInco)) {
|
||||
// We have data.
|
||||
$hasInco = __("Des données Inco sont disponibles, souhaitez vous les associer à ce produit ?");
|
||||
$preparedImages = $this->prepareIncoImages($xmlInco->picture);
|
||||
return view('bo.products.load-inco', compact('hasInco', 'xmlInco', 'preparedImages'));
|
||||
} else {
|
||||
return array("data" => array());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show prepared images
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function getPrepareIncoImages(Request $request)
|
||||
{
|
||||
$picture = $request->picture;
|
||||
$preparedImages = $this->prepareIncoImages($picture);
|
||||
return view('bo.products.inco-images', compact('preparedImages'));
|
||||
}
|
||||
|
||||
/**
|
||||
* prepared images
|
||||
*
|
||||
* @param array $picture
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function prepareIncoImages(array $picture)
|
||||
{
|
||||
$preparedImages = array();
|
||||
|
||||
foreach ($picture as $incoImage) {
|
||||
// Charge.
|
||||
if (File::exists(storage_path($incoImage))) {
|
||||
$imagePath = storage_path($incoImage);
|
||||
// Redimensionne.
|
||||
// Create mask.
|
||||
// Resize original image into mask.
|
||||
$this->resizeImg(
|
||||
$imagePath,
|
||||
config('theme.product_image_large_maxwidth'),
|
||||
config('theme.product_image_large_maxheight'),
|
||||
File::name($incoImage) . "_large.png"
|
||||
);
|
||||
|
||||
$this->resizeImg(
|
||||
$imagePath,
|
||||
config('theme.product_image_maxwidth'),
|
||||
config('theme.product_image_maxheight'),
|
||||
File::name($incoImage) . "_small.png"
|
||||
);
|
||||
|
||||
|
||||
$preparedImages[] = "inco/images/" . File::name($incoImage) . "_large.png";
|
||||
}//end if
|
||||
}//end foreach
|
||||
return $preparedImages;
|
||||
}
|
||||
|
||||
/**
|
||||
* redimensionne une image dans un masque
|
||||
*/
|
||||
/**
|
||||
* 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
|
||||
$mask = imagecreatetruecolor($maskWidth, $maskHeight);
|
||||
imagesavealpha($mask, true);
|
||||
$color = imagecolorallocatealpha($mask, 0, 0, 0, 127);
|
||||
imagefill($mask, 0, 0, $color);
|
||||
|
||||
// ---- Récupère le mime type de l'image
|
||||
$info = getimagesize($imagePath);
|
||||
$mime = $info['mime'];
|
||||
|
||||
// ---- Défini les fonctions à appeler selon le type de fichier
|
||||
switch ($mime) {
|
||||
case 'image/jpeg':
|
||||
$image_create_func = 'imagecreatefromjpeg';
|
||||
break;
|
||||
|
||||
case 'image/png':
|
||||
$image_create_func = 'imagecreatefrompng';
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
// ---- Chargement de l'image source
|
||||
$img = $image_create_func($imagePath);
|
||||
list($imgWidth, $imgHeight) = getimagesize($imagePath);
|
||||
|
||||
// ---- Calcul les nouvelles dimensions de l'image
|
||||
if ($imgWidth > $imgHeight) {
|
||||
$finalWidth = $maskWidth;
|
||||
$finalHeight = ($finalWidth * $imgHeight) / $imgWidth;
|
||||
} else {
|
||||
$finalHeight = $maskHeight;
|
||||
$finalWidth = ($finalHeight * $imgWidth) / $imgHeight;
|
||||
}
|
||||
|
||||
// ---- Redimensionne l'image source
|
||||
$resizeImg = imagecreatetruecolor($finalWidth, $finalHeight);
|
||||
imagealphablending($resizeImg, false);
|
||||
imagesavealpha($resizeImg, true);
|
||||
imagecopyresampled($resizeImg, $img, 0, 0, 0, 0, $finalWidth, $finalHeight, $imgWidth, $imgHeight);
|
||||
|
||||
// Copie l'image redimensionnée dans le mask.
|
||||
imagecopy(
|
||||
$mask,
|
||||
$resizeImg,
|
||||
($maskWidth - $finalWidth) / 2,
|
||||
($maskHeight - $finalHeight) / 2,
|
||||
0,
|
||||
0,
|
||||
imagesx($resizeImg),
|
||||
imagesy($resizeImg)
|
||||
);
|
||||
imagealphablending($mask, false);
|
||||
imagesavealpha($mask, true);
|
||||
|
||||
// Ecrit dans storage/app/public.
|
||||
// Créer le fichier final.
|
||||
imagepng($mask, storage_path('app/public/inco/images/' . $resizedName), 5);
|
||||
|
||||
// Libère la mémoire associée aux images manipulées.
|
||||
imagedestroy($img);
|
||||
imagedestroy($resizeImg);
|
||||
imagedestroy($mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
$imagePath = $request->picture;
|
||||
|
||||
$imagePath = storage_path("app/public/" . $imagePath);
|
||||
|
||||
$product_id = $request->product;
|
||||
$product = Product::findOrFail($product_id);
|
||||
|
||||
$str_random = Str::random(5);
|
||||
// Default is large image.
|
||||
$finalImageName = $product->id . '_' . $str_random . '_large.' . File::extension($imagePath);
|
||||
|
||||
$productimagespath = public_path('images/produits');
|
||||
|
||||
if (!File::isDirectory($productimagespath)) {
|
||||
File::makeDirectory($productimagespath, 0644, true);
|
||||
}
|
||||
|
||||
File::copy($imagePath, $productimagespath . "/" . $finalImageName);
|
||||
|
||||
// Suppression de l'ancien fichier.
|
||||
if (
|
||||
$product->picture_large !== null &&
|
||||
file_exists(public_path('images/produits/') . $product->picture_large)
|
||||
) {
|
||||
unlink(public_path('images/produits/') . $product->picture_large);
|
||||
}
|
||||
|
||||
$product->picture_large = $finalImageName;
|
||||
|
||||
|
||||
// Now set small image.
|
||||
$imagePath = str_replace("_large", "_small", $imagePath);
|
||||
$finalImageName = $product->id . '_' . $str_random . '.' . File::extension($imagePath);
|
||||
File::copy($imagePath, $productimagespath . "/" . $finalImageName);
|
||||
|
||||
// Suppression de l'ancien fichier.
|
||||
if ($product->picture !== null && file_exists(public_path('images/produits/') . $product->picture)) {
|
||||
unlink(public_path('images/produits/') . $product->picture);
|
||||
}
|
||||
|
||||
$product->picture = $finalImageName;
|
||||
|
||||
$product->save();
|
||||
|
||||
return $product;
|
||||
}
|
||||
|
||||
/**
|
||||
* helper method to update additionnal product info
|
||||
*
|
||||
* @param Request $request
|
||||
* @param integer $product_id
|
||||
* @return void
|
||||
*/
|
||||
public function saveFoodProduct(Request $request, int $product_id)
|
||||
{
|
||||
$foodProduct = FoodProduct::firstOrNew([
|
||||
'product_id' => $product_id,
|
||||
]);
|
||||
|
||||
if (!empty($request->no_art)) {
|
||||
$foodProduct->no_art = $request->no_art;
|
||||
}
|
||||
$foodProduct->ingredients = $request->ingredients;
|
||||
$foodProduct->preparation = $request->preparation;
|
||||
$foodProduct->servings = $request->servings;
|
||||
$foodProduct->allergens = $request->allergens;
|
||||
$foodProduct->selling_argument = $request->selling_argument;
|
||||
$foodProduct->nv_ref_weight_g = $request->nv_ref_weight_g;
|
||||
$foodProduct->nv_kj = $request->nv_kj;
|
||||
$foodProduct->nv_kcal = $request->nv_kcal;
|
||||
$foodProduct->nv_fat_g = $request->nv_fat_g;
|
||||
$foodProduct->nv_sat_fat_g = $request->nv_sat_fat_g;
|
||||
$foodProduct->nv_carb_g = $request->nv_carb_g;
|
||||
$foodProduct->nv_sugar_g = $request->nv_sugar_g;
|
||||
$foodProduct->nv_fiber_g = $request->nv_fiber_g;
|
||||
$foodProduct->nv_protein_g = $request->nv_protein_g;
|
||||
$foodProduct->nv_salt_g = $request->nv_salt_g;
|
||||
$foodProduct->nv_serving_size_g = $request->nv_serving_size_g;
|
||||
$foodProduct->nv_serving_kj = $request->nv_serving_kj;
|
||||
$foodProduct->nv_serving_kcal = $request->nv_serving_kcal;
|
||||
$foodProduct->nv_serving_fat_g = $request->nv_serving_fat_g;
|
||||
$foodProduct->nv_serving_sat_fat_g = $request->nv_serving_sat_fat_g;
|
||||
$foodProduct->nv_serving_carb_g = $request->nv_serving_carb_g;
|
||||
$foodProduct->nv_serving_sugar_g = $request->nv_serving_sugar_g;
|
||||
$foodProduct->nv_serving_fiber_g = $request->nv_serving_fiber_g;
|
||||
$foodProduct->nv_serving_protein_g = $request->nv_serving_protein_g;
|
||||
$foodProduct->nv_serving_salt_g = $request->nv_serving_salt_g;
|
||||
$foodProduct->nv_daily_energy = $request->nv_daily_energy;
|
||||
$foodProduct->nv_daily_fat = $request->nv_daily_fat;
|
||||
$foodProduct->nv_daily_sat_fat = $request->nv_daily_sat_fat;
|
||||
$foodProduct->nv_daily_carb = $request->nv_daily_carb;
|
||||
$foodProduct->nv_daily_sugar = $request->nv_daily_sugar;
|
||||
$foodProduct->nv_daily_fiber = $request->nv_daily_fiber;
|
||||
$foodProduct->nv_daily_protein = $request->nv_daily_protein;
|
||||
$foodProduct->nv_daily_salt = $request->nv_daily_salt;
|
||||
$foodProduct->nutriscore = $request->nutriscore;
|
||||
$foodProduct->nutriscore_args = $request->nutriscore_args;
|
||||
|
||||
$foodProduct->product_id = $product_id;
|
||||
|
||||
|
||||
$foodProduct->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* helper method to update toolproduct info
|
||||
*
|
||||
* @param Request $request
|
||||
* @param integer $product_id
|
||||
* @return void
|
||||
*
|
||||
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
|
||||
*/
|
||||
public function saveToolProduct(Request $request, int $product_id)
|
||||
{
|
||||
// phpcs:enable
|
||||
$toolProduct = ToolProduct::firstOrNew([
|
||||
'product_id' => $product_id,
|
||||
]);
|
||||
|
||||
$toolProduct->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* helper method to update anifoodProduct info
|
||||
*
|
||||
* @param Request $request
|
||||
* @param integer $product_id
|
||||
* @return void
|
||||
*/
|
||||
public function saveAnifoodProduct(Request $request, int $product_id)
|
||||
{
|
||||
$anifoodProduct = AnifoodProduct::firstOrNew([
|
||||
'product_id' => $product_id,
|
||||
]);
|
||||
|
||||
$anifoodProduct->composition = $request->composition;
|
||||
$anifoodProduct->servings = $request->servings;
|
||||
$anifoodProduct->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* helper method to update garmentProduct info
|
||||
*
|
||||
* @param Request $request
|
||||
* @param integer $product_id
|
||||
* @return void
|
||||
*/
|
||||
public function saveGarmentProduct(Request $request, int $product_id)
|
||||
{
|
||||
$garmentProduct = GarmentProduct::firstOrNew([
|
||||
'product_id' => $product_id,
|
||||
]);
|
||||
|
||||
$garmentProduct->size = $request->size;
|
||||
$garmentProduct->color = $request->color;
|
||||
$garmentProduct->material = $request->material;
|
||||
$garmentProduct->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* index des produits mis en avant
|
||||
*
|
||||
* @return * @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function starred()
|
||||
{
|
||||
$products = Product::where('star', 1)->paginate(10);
|
||||
return view('bo.products.starred', compact('products'));
|
||||
}
|
||||
}
|
||||
139
app/Http/Controllers/Bo/PromotionsController.php
Normal file
139
app/Http/Controllers/Bo/PromotionsController.php
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\DiscountType;
|
||||
use App\Models\Promotion;
|
||||
use App\Models\Product;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class PromotionsController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$promotions = Promotion::all();
|
||||
return view('bo.promotions.index', compact('promotions'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
$discTypes = DiscountType::all();
|
||||
|
||||
$existingProds = Product::all();
|
||||
$promotion = new Promotion();
|
||||
$selectedProds = $promotion->products;
|
||||
return view('bo.promotions.create', compact('discTypes', 'existingProds', 'selectedProds'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
|
||||
$request->validate([
|
||||
'product_id' => 'required',
|
||||
]);
|
||||
|
||||
$productIds = explode(",", $request->product_id);
|
||||
$discType = $request->discount_type_id;
|
||||
$value = $request->discount_value;
|
||||
$date_start = $request->date_start_date . " " . $request->date_start_time;
|
||||
$date_end = $request->date_end_date . " " . $request->date_end_time;
|
||||
|
||||
$promotion = new Promotion();
|
||||
$promotion->discount_type_id = $discType;
|
||||
$promotion->discount_value = $value;
|
||||
$promotion->date_start = $date_start;
|
||||
$promotion->date_end = $date_end;
|
||||
$promotion->save();
|
||||
|
||||
// Prise en charge de la liaison avec les produits.
|
||||
$promotion->products()->sync($productIds);
|
||||
|
||||
return redirect()->route('bo.promotions.index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param integer $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit(int $id)
|
||||
{
|
||||
$promotion = Promotion::findOrFail($id);
|
||||
$discTypes = DiscountType::all();
|
||||
|
||||
$existingProds = Product::all();
|
||||
$selectedProds = $promotion->products;
|
||||
$existingProds = $existingProds->diff($selectedProds);
|
||||
|
||||
return view('bo.promotions.edit', compact('promotion', 'discTypes', 'existingProds', 'selectedProds'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
$promotion = Promotion::findOrFail($id);
|
||||
|
||||
$request->validate([
|
||||
'product_id' => 'required',
|
||||
]);
|
||||
|
||||
$productIds = explode(",", $request->product_id);
|
||||
$discType = $request->discount_type_id;
|
||||
$value = $request->discount_value;
|
||||
$date_start = $request->date_start_date . " " . $request->date_start_time;
|
||||
$date_end = $request->date_end_date . " " . $request->date_end_time;
|
||||
|
||||
$promotion->discount_type_id = $discType;
|
||||
$promotion->discount_value = $value;
|
||||
$promotion->date_start = $date_start;
|
||||
$promotion->date_end = $date_end;
|
||||
$promotion->save();
|
||||
|
||||
// Prise en charge de la liaison avec les produits.
|
||||
$promotion->products()->sync($productIds);
|
||||
|
||||
return redirect()->route('bo.promotions.edit', $promotion->id)->with('success', 'Modifications enregistrés !');
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param integer $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(int $id)
|
||||
{
|
||||
$p = Promotion::findOrFail($id);
|
||||
|
||||
// Prise en charge de la liaison avec les produits.
|
||||
$p->products()->detach();
|
||||
|
||||
$p->delete();
|
||||
|
||||
return redirect()->route('bo.promotions.index');
|
||||
}
|
||||
}
|
||||
|
|
@ -1,141 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Bo\Ranges\StoreRangeRequest;
|
||||
use App\Http\Requests\Bo\Ranges\UpdateRangeRequest;
|
||||
use App\Models\Range;
|
||||
use App\Traits\Controllers\UpdateModelStatus;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class RangeController extends Controller
|
||||
{
|
||||
use UpdateModelStatus;
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
/** @var \Illuminate\Database\Eloquent\Builder $ranges */
|
||||
$ranges = Range::query();
|
||||
|
||||
if ($request->search) {
|
||||
$this->searchQuery(
|
||||
$ranges,
|
||||
$request->search,
|
||||
null,
|
||||
'name',
|
||||
'description'
|
||||
);
|
||||
}
|
||||
|
||||
$this->sortQuery($ranges);
|
||||
$searchFields = trans('Nom, Description');
|
||||
|
||||
$ranges->orderBy('updated_at', 'DESC');
|
||||
$ranges = $ranges->paginate();
|
||||
|
||||
return view('back::pages.ranges.index', compact('ranges', 'searchFields'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
return view('back::pages.ranges.create');
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Bo\Ranges\StoreRangeRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(StoreRangeRequest $request)
|
||||
{
|
||||
return DB::transaction(function () use ($request) {
|
||||
$range = new Range();
|
||||
$range->fill($request->validated());
|
||||
|
||||
if ($range->saveOrFail()) {
|
||||
return redirect()
|
||||
->route('bo.ranges.edit', $range)
|
||||
->with('success', trans(
|
||||
':model a été créé',
|
||||
['model' => Str::singular(trans('models.classes.ranges'))]
|
||||
));
|
||||
}
|
||||
return back();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \App\Models\Range $range
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit(Range $range)
|
||||
{
|
||||
return view('back::pages.ranges.edit', [
|
||||
'rangeModel' => $range
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Bo\Ranges\UpdateRangeRequest $request
|
||||
* @param \App\Models\Range $range
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(UpdateRangeRequest $request, Range $range)
|
||||
{
|
||||
return DB::transaction(function () use ($request, $range) {
|
||||
$range->fill($request->validated());
|
||||
if ($range->saveOrFail()) {
|
||||
return redirect()
|
||||
->route('bo.ranges.edit', $range)
|
||||
->with('success', trans(
|
||||
':model a été mis à jour',
|
||||
['model' => Str::singular(trans('models.classes.ranges'))]
|
||||
));
|
||||
} //end if
|
||||
return back();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \App\Models\Range $range
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(Range $range)
|
||||
{
|
||||
if ($range->products()->count() > 0) {
|
||||
return redirect()->back()
|
||||
->withErrors("Suppression impossible : {$range->id} {$range->name} contient encore des produits.");
|
||||
}
|
||||
|
||||
if ($range->deleteOrFail()) {
|
||||
return redirect()
|
||||
->route('bo.ranges.index')
|
||||
->with('warning', trans(
|
||||
':model a bien été supprimé',
|
||||
['model' => Str::singular(trans('models.classes.ranges'))]
|
||||
));
|
||||
}
|
||||
return back();
|
||||
}
|
||||
}
|
||||
169
app/Http/Controllers/Bo/RangesController.php
Normal file
169
app/Http/Controllers/Bo/RangesController.php
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\OldSlug;
|
||||
use App\Models\Product;
|
||||
use App\Models\Range;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class RangesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$ranges = Range::all();
|
||||
return view('bo.ranges.index', compact('ranges'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function 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)
|
||||
{
|
||||
$name = $request->name;
|
||||
$slug = Str::slug($name);
|
||||
$description = $request->description;
|
||||
$picture = $request->picture;
|
||||
$status = $request->status === null ? 0 : 1;
|
||||
|
||||
$request->validate([
|
||||
'name' => 'required|string|max:255',
|
||||
'description' => 'required',
|
||||
'picture' => 'image|mimes:jpeg,png,jpg|max:2048|dimensions:max-width=' .
|
||||
config('theme.range_image_maxwidth') . ',max-height=' .
|
||||
config('theme.range_image_maxheight'),
|
||||
]);
|
||||
|
||||
$range = new Range();
|
||||
$range->name = $name;
|
||||
$range->slug = $slug;
|
||||
$range->description = $description;
|
||||
$range->status = $status;
|
||||
$range->save();
|
||||
|
||||
if ($picture !== null) {
|
||||
$imageName = $range->id . '_' . $slug . '_' . Str::random(5) . '.' . $picture->extension();
|
||||
$picture->move(public_path('images/gammes'), $imageName);
|
||||
$range->picture = $imageName;
|
||||
$range->save();
|
||||
}
|
||||
|
||||
return redirect()->route('bo.ranges.index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param integer $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit(int $id)
|
||||
{
|
||||
$range = Range::findOrFail($id);
|
||||
return view('bo.ranges.edit', compact('range'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
$slug = Str::slug($name);
|
||||
$description = $request->description;
|
||||
$picture = $request->picture;
|
||||
$status = $request->status === null ? 0 : 1;
|
||||
|
||||
$request->validate([
|
||||
'name' => 'required|string|max:255',
|
||||
'description' => 'required',
|
||||
'picture' => 'image|mimes:jpeg,png,jpg|max:2048|dimensions:max-width=' .
|
||||
config('theme.range_image_maxwidth') . ',max-height=' .
|
||||
config('theme.range_image_maxheight'),
|
||||
]);
|
||||
|
||||
$range = Range::findOrFail($id);
|
||||
|
||||
if ($picture !== null) {
|
||||
if ($range->picture !== null && file_exists(public_path('images/gammes/') . $range->picture)) {
|
||||
unlink(public_path('images/gammes/') . $range->picture);
|
||||
}
|
||||
$imageName = $range->id . '_' . $slug . '_' . Str::random(5) . '.' . $picture->extension();
|
||||
$picture->move(public_path('images/gammes'), $imageName);
|
||||
}
|
||||
|
||||
$range->name = $name;
|
||||
|
||||
if ($range->slug != $slug) {
|
||||
$exist = OldSlug::where('slug', $range->slug)->first();
|
||||
if ($exist === null) {
|
||||
$oldSlug = new OldSlug();
|
||||
$oldSlug->range_id = $range->id;
|
||||
$oldSlug->slug = $range->slug;
|
||||
$oldSlug->save();
|
||||
}
|
||||
}
|
||||
|
||||
$range->slug = $slug;
|
||||
$range->description = $description;
|
||||
if ($picture !== null) {
|
||||
$range->picture = $imageName;
|
||||
}
|
||||
$range->status = $status;
|
||||
$range->save();
|
||||
|
||||
return redirect()->route('bo.ranges.edit', $range->id)->with('success', 'Modifications enregistrés !');
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param integer $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(int $id)
|
||||
{
|
||||
$range = Range::findOrFail($id);
|
||||
|
||||
$product = Product::where('range_id', $range->id)->count();
|
||||
if ($product !== 0) {
|
||||
return redirect()->back()
|
||||
->withErrors("Suppression impossible : \"" . $range->name . "\" contient encore des produits.");
|
||||
}
|
||||
|
||||
if ($range->picture !== null) {
|
||||
if (file_exists(public_path('images/gammes/') . $range->picture)) {
|
||||
unlink(public_path('images/gammes/') . $range->picture);
|
||||
}
|
||||
}
|
||||
|
||||
OldSlug::where('range_id', $range->id)->delete();
|
||||
|
||||
$range->delete();
|
||||
return redirect()->route('bo.ranges.index');
|
||||
}
|
||||
}
|
||||
112
app/Http/Controllers/Bo/SettingsController.php
Normal file
112
app/Http/Controllers/Bo/SettingsController.php
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Setting;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Support\Facades\Config;
|
||||
|
||||
class SettingsController extends Controller
|
||||
{
|
||||
/**
|
||||
* Manage settings page
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*
|
||||
*/
|
||||
public function manage(Request $request)
|
||||
{
|
||||
$settings = Setting::all();
|
||||
$settingsToPrint = [];
|
||||
foreach ($settings as $setting) {
|
||||
$settingsToPrint[$setting->key] = $setting->value;
|
||||
}
|
||||
|
||||
if ($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||
$input = $request->all();
|
||||
|
||||
// Comparer les settingsToPrint (en base) avec les inputs (pour trouver un nouveau).
|
||||
foreach ($input as $key => $value) {
|
||||
if (
|
||||
!isset($settingsToPrint[$key])
|
||||
&& $key != "_method"
|
||||
&& $key != "_token"
|
||||
) {
|
||||
// New setting.
|
||||
$setting = new Setting();
|
||||
$setting->key = $key;
|
||||
$setting->value = $value ?? 0;
|
||||
$setting->save();
|
||||
}
|
||||
}
|
||||
|
||||
$looplimit = count($settings);
|
||||
for ($i = 0; $i < $looplimit; $i++) {
|
||||
if (is_array($request->input($settings[$i]->key))) {
|
||||
$settings[$i]->value = implode(',', $request->input($settings[$i]->key));
|
||||
} else {
|
||||
$settings[$i]->value = $request->input($settings[$i]->key) === null ? 0
|
||||
: $request->input($settings[$i]->key);
|
||||
}
|
||||
$settings[$i]->save();
|
||||
}
|
||||
|
||||
// Store redirector to keep flash message from being wipe pby artisan call below.
|
||||
$redirector = redirect()->route('bo.settings')->with('success', 'Modifications enregistrés !');
|
||||
|
||||
// All settings saved : cache routes.
|
||||
Artisan::call('route:clear');
|
||||
// Programmer un php artisan optimize ? (une fois par jour la nuit par exemple).
|
||||
return $redirector;
|
||||
}//end if
|
||||
|
||||
return view('bo.settings', compact('settingsToPrint'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Manage Theme settings page
|
||||
* Management des settings dont la clé est préfixée theme_
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*
|
||||
*/
|
||||
public function manageTheme(Request $request)
|
||||
{
|
||||
$settings = Setting::where('key', 'LIKE', 'theme_%')->get();
|
||||
$settingsToPrint = [];
|
||||
foreach ($settings as $setting) {
|
||||
$settingsToPrint[$setting->key] = $setting->value;
|
||||
}
|
||||
|
||||
$config_settings = Config::get(('theme.bo_theme_settings'));
|
||||
|
||||
// Check if, for each of the theme defined settings we have a database setting.
|
||||
foreach ($config_settings as $onekey => $params) {
|
||||
if (!isset($settingsToPrint['theme_' . $onekey])) {
|
||||
$dbsetting = new Setting();
|
||||
$dbsetting->key = 'theme_' . $onekey;
|
||||
$dbsetting->value = $params['default_value'];
|
||||
$dbsetting->save();
|
||||
// Injection dans settings to print.
|
||||
$settingsToPrint[$dbsetting->key] = $dbsetting->value;
|
||||
}
|
||||
}
|
||||
|
||||
if ($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||
$looplimit = count($settings);
|
||||
for ($i = 0; $i < $looplimit; $i++) {
|
||||
// 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();
|
||||
}
|
||||
return redirect()->route('bo.themesettings')->with('success', 'Modifications enregistrés !');
|
||||
}
|
||||
|
||||
return view('bo.settings.theme', compact('settingsToPrint', 'config_settings'));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,197 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Bo\Ajax\TimeslotExceptions\DeleteTimeslotExceptionsRequest;
|
||||
use App\Http\Requests\Bo\Ajax\TimeslotExceptions\SaveTimeslotExceptionsRequest;
|
||||
use App\Http\Requests\Bo\Shops\StoreShopRequest;
|
||||
use App\Http\Requests\Bo\Shops\UpdateShopRequest;
|
||||
use App\Models\CollectionException;
|
||||
use App\Models\Shop;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class ShopController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
/** @var \Illuminate\Database\Eloquent\Builder $shops */
|
||||
$shops = Shop::query();
|
||||
|
||||
if ($request->search) {
|
||||
$this->searchQuery(
|
||||
$shops,
|
||||
$request->search,
|
||||
null,
|
||||
'name',
|
||||
'address',
|
||||
'city',
|
||||
'postal_code'
|
||||
);
|
||||
}
|
||||
|
||||
$this->sortQuery($shops);
|
||||
$searchFields = trans('Nom, adresse, ville, cp');
|
||||
|
||||
$shops->orderBy('updated_at', 'DESC');
|
||||
$shops = $shops->paginate();
|
||||
|
||||
return view('back::pages.shops.index', compact('shops', 'searchFields'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
return view('back::pages.shops.create');
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Bo\Shops \StoreShopRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(StoreShopRequest $request)
|
||||
{
|
||||
return DB::transaction(function () use ($request) {
|
||||
$shop = new Shop();
|
||||
$shop->fill($request->validated());
|
||||
|
||||
if ($shop->saveOrFail()) {
|
||||
return redirect()
|
||||
->route('bo.shops.edit', $shop)
|
||||
->with('success', trans(
|
||||
':model a été créé',
|
||||
['model' => Str::singular(trans('models.classes.shops'))]
|
||||
));
|
||||
}
|
||||
return back();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \App\Models\Shop $shop
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit(Shop $shop)
|
||||
{
|
||||
$exceptionsCollecte = $shop->collectionExceptions()->orderBy('date')->get();
|
||||
return view('back::pages.shops.edit', [
|
||||
'shopModel' => $shop,
|
||||
'exceptionsCollecte' => $exceptionsCollecte
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Bo\Shops\UpdateShopRequest $request
|
||||
* @param \App\Models\Shop $shop
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(UpdateShopRequest $request, Shop $shop)
|
||||
{
|
||||
return DB::transaction(function () use ($request, $shop) {
|
||||
$shop->fill($request->validated());
|
||||
if ($shop->saveOrFail()) {
|
||||
return redirect()
|
||||
->route('bo.shops.edit', $shop)
|
||||
->with('success', trans(
|
||||
':model a été mis à jour',
|
||||
['model' => Str::singular(trans('models.classes.shops'))]
|
||||
));
|
||||
} //end if
|
||||
return back();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \App\Models\Shop $shop
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(Shop $shop)
|
||||
{
|
||||
if (Shop::count() <= 1) {
|
||||
return redirect()->back()
|
||||
->withErrors('Suppression impossible : Vous devez conserver au moins 1 point de retrait.');
|
||||
}
|
||||
if ($shop->deleteOrFail()) {
|
||||
return redirect()
|
||||
->route('bo.shops.index')
|
||||
->with('warning', trans(
|
||||
':model a bien été supprimé',
|
||||
['model' => Str::singular(trans('models.classes.shops'))]
|
||||
));
|
||||
}
|
||||
return back();
|
||||
}
|
||||
|
||||
/**
|
||||
* Save collect exceptions
|
||||
*
|
||||
* @param \App\Http\Requests\Bo\Ajax\TimeslotExceptions\SaveTimeslotExceptionsRequest $request
|
||||
* @param \App\Models\Shop $shop
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function saveExceptions(SaveTimeslotExceptionsRequest $request, Shop $shop): JsonResponse
|
||||
{
|
||||
return DB::transaction(function () use ($request, $shop) {
|
||||
$collecteExceptionDates = \collect($request->dates)->keyBy('date');
|
||||
|
||||
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\CollectionException> */
|
||||
$collectionExceptions = $shop->collectionExceptions
|
||||
->filter(function (CollectionException $collectionException) use ($collecteExceptionDates) {
|
||||
if (!$collecteExceptionDates->has($collectionException->date->format('Y-m-d'))) {
|
||||
$collectionException->deleteOrFail();
|
||||
return false;
|
||||
}
|
||||
$collecteExceptionDates->pull($collectionException->date->format('Y-m-d'));
|
||||
return true;
|
||||
});
|
||||
$collecteExceptionDates->map(function (array $ajaxCollectionexception) use ($shop, $collectionExceptions) {
|
||||
$collectionException = new CollectionException($ajaxCollectionexception);
|
||||
$collectionException->shop()->associate($shop);
|
||||
$collectionException->saveOrFail();
|
||||
$collectionException->refresh();
|
||||
$collectionExceptions->push($collectionException);
|
||||
});
|
||||
return \response()->json($collectionExceptions);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* delete collecte exception
|
||||
*
|
||||
* @param \App\Http\Requests\Bo\Ajax\TimeslotExceptions\DeleteTimeslotExceptionsRequest $request
|
||||
* @param \App\Models\Shop $shop
|
||||
* @return string
|
||||
*/
|
||||
public function destroyExceptions(DeleteTimeslotExceptionsRequest $request, Shop $shop): JsonResponse
|
||||
{
|
||||
return DB::transaction(function () use ($request, $shop) {
|
||||
CollectionException::whereHas('shop', function (Builder $q) use ($shop) {
|
||||
$q->where('id', $shop->id);
|
||||
})->whereId($request->id)->firstOrFail()->deleteOrFail();
|
||||
|
||||
return \response()->json($shop->collectionExceptions);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -1,180 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Bo\Slides\StoreSlideRequest;
|
||||
use App\Http\Requests\Bo\Slides\UpdateSlideRequest;
|
||||
use App\Models\Slide;
|
||||
use App\Models\Slider;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class SlideController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
/** @var \Illuminate\Database\Eloquent\Builder $slides */
|
||||
$slides = Slide::query();
|
||||
|
||||
if ($request->search) {
|
||||
$this->searchQuery(
|
||||
$slides,
|
||||
$request->search,
|
||||
null,
|
||||
'label'
|
||||
);
|
||||
}
|
||||
|
||||
$this->sortQuery($slides);
|
||||
$searchFields = trans('Label');
|
||||
|
||||
$slides->orderBy('updated_at', 'DESC');
|
||||
$slides = $slides->paginate();
|
||||
|
||||
return view('back::pages.slides.index', compact('slides', 'searchFields'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
$sliders = Slider::all();
|
||||
return view('back::pages.slides.create', compact('sliders'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Bo\Slides\StoreSlideRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(StoreSlideRequest $request)
|
||||
{
|
||||
return DB::transaction(function () use ($request) {
|
||||
$slide = new Slide();
|
||||
$slide->fill($request->validated());
|
||||
$slide->order = $this->getLastOrder();
|
||||
|
||||
if ($slide->saveOrFail()) {
|
||||
return redirect()
|
||||
->route('bo.slides.edit', $slide)
|
||||
->with('success', trans(
|
||||
':model a été créé',
|
||||
['model' => Str::singular(trans('models.classes.slides'))]
|
||||
));
|
||||
}
|
||||
return back();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \App\Models\Slide $slide
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit(Slide $slide)
|
||||
{
|
||||
$sliders = Slider::all();
|
||||
return view('back::pages.slides.edit', [
|
||||
'slideModel' => $slide, 'sliders' => $sliders
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Bo\Slides\UpdateSlideRequest $request
|
||||
* @param \App\Models\Slide $slide
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(UpdateSlideRequest $request, Slide $slide)
|
||||
{
|
||||
return DB::transaction(function () use ($request, $slide) {
|
||||
$slide->fill($request->validated());
|
||||
if ($slide->saveOrFail()) {
|
||||
return redirect()
|
||||
->route('bo.slides.edit', $slide)
|
||||
->with('success', trans(
|
||||
':model a été mis à jour',
|
||||
['model' => Str::singular(trans('models.classes.slides'))]
|
||||
));
|
||||
} //end if
|
||||
return back();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \App\Models\Slide $slide
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(Slide $slide)
|
||||
{
|
||||
if ($slide->deleteOrFail()) {
|
||||
return redirect()
|
||||
->route('bo.slides.index')
|
||||
->with('warning', trans(
|
||||
':model a bien été supprimé',
|
||||
['model' => Str::singular(trans('models.classes.slides'))]
|
||||
));
|
||||
}
|
||||
return back();
|
||||
}
|
||||
|
||||
/**
|
||||
* Change slide order
|
||||
*
|
||||
* @param \App\Models\Slide $slide
|
||||
* @param string $action
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function changeOrder(Slide $slide, string $action)
|
||||
{
|
||||
if ($action === 'up') {
|
||||
$tmp = Slide::where([
|
||||
['order', '<', $slide->order],
|
||||
])->orderBy('order', 'DESC')->first();
|
||||
} else {
|
||||
$tmp = Slide::where([
|
||||
['order', '>', $slide->order],
|
||||
])->orderBy('order', 'ASC')->first();
|
||||
}
|
||||
$newOrder = $tmp->order;
|
||||
$tmp->order = $slide->order;
|
||||
$slide->order = $newOrder;
|
||||
DB::transaction(function () use ($tmp, $slide) {
|
||||
$tmp->saveOrFail();
|
||||
$slide->saveOrFail();
|
||||
});
|
||||
|
||||
return redirect()->back();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Last order
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
private function getLastOrder(): int
|
||||
{
|
||||
$order = Slide::select('order')
|
||||
->orderBy('order', 'DESC')->first();
|
||||
if ($order === null) {
|
||||
return 1;
|
||||
}
|
||||
return $order->order + 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,133 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Bo\Sliders\StoreSliderRequest;
|
||||
use App\Http\Requests\Bo\Sliders\UpdateSliderRequest;
|
||||
use App\Models\Slider;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class SliderController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
/** @var \Illuminate\Database\Eloquent\Builder $sliders */
|
||||
$sliders = Slider::query();
|
||||
|
||||
if ($request->search) {
|
||||
$this->searchQuery(
|
||||
$sliders,
|
||||
$request->search,
|
||||
null,
|
||||
'label'
|
||||
);
|
||||
}
|
||||
|
||||
$this->sortQuery($sliders);
|
||||
$searchFields = trans('Label');
|
||||
|
||||
$sliders->orderBy('updated_at', 'DESC');
|
||||
$sliders = $sliders->paginate();
|
||||
|
||||
return view('back::pages.sliders.index', compact('sliders', 'searchFields'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
return view('back::pages.sliders.create');
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Bo\Sliders\StoreSliderRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(StoreSliderRequest $request)
|
||||
{
|
||||
return DB::transaction(function () use ($request) {
|
||||
$slider = new Slider();
|
||||
$slider->fill($request->validated());
|
||||
|
||||
if ($slider->saveOrFail()) {
|
||||
return redirect()
|
||||
->route('bo.sliders.edit', $slider)
|
||||
->with('success', trans(
|
||||
':model a été créé',
|
||||
['model' => Str::singular(trans('models.classes.sliders'))]
|
||||
));
|
||||
}
|
||||
return back();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \App\Models\Slider $slider
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit(Slider $slider)
|
||||
{
|
||||
return view('back::pages.sliders.edit', ['sliderModel' => $slider]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Bo\Sliders\UpdateSliderRequest $request
|
||||
* @param \App\Models\Slider $slider
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(UpdateSliderRequest $request, Slider $slider)
|
||||
{
|
||||
return DB::transaction(function () use ($request, $slider) {
|
||||
$slider->fill($request->validated());
|
||||
if ($slider->saveOrFail()) {
|
||||
return redirect()
|
||||
->route('bo.sliders.edit', $slider)
|
||||
->with('success', trans(
|
||||
':model a été mis à jour',
|
||||
['model' => Str::singular(trans('models.classes.sliders'))]
|
||||
));
|
||||
} //end if
|
||||
return back();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \App\Models\Slider $slider
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(Slider $slider)
|
||||
{
|
||||
if (Slider::count() <= 1) {
|
||||
return redirect()->back()->withErrors("Suppression impossible : Vous devez conserver au moins 1 Slider");
|
||||
}
|
||||
if ($slider->deleteOrFail()) {
|
||||
return redirect()
|
||||
->route('bo.sliders.index')
|
||||
->with('warning', trans(
|
||||
':model a bien été supprimé',
|
||||
['model' => Str::singular(trans('models.classes.sliders'))]
|
||||
));
|
||||
}
|
||||
return back();
|
||||
}
|
||||
}
|
||||
120
app/Http/Controllers/Bo/SlidersController.php
Normal file
120
app/Http/Controllers/Bo/SlidersController.php
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Slider;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class SlidersController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$sliders = Slider::all();
|
||||
return view('bo.sliders.index', compact('sliders'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
return view('bo.sliders.create');
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$label = $request->label;
|
||||
$slug = $request->slug;
|
||||
if (empty($slug)) {
|
||||
$slug = Str::slug($label);
|
||||
}
|
||||
$commentaire = $request->commentaire;
|
||||
|
||||
|
||||
$request->validate([
|
||||
'label' => 'required|string|max:255',
|
||||
'slug' => 'sometimes|unique:sliders',
|
||||
]);
|
||||
|
||||
$slider = new Slider();
|
||||
$slider->label = $label;
|
||||
$slider->slug = $slug;
|
||||
$slider->commentaire = $commentaire;
|
||||
$slider->save();
|
||||
return redirect()->route('bo.sliders.edit', $slider->id)->with('success', 'Slider créé !');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param integer $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit(int $id)
|
||||
{
|
||||
$slider = Slider::findOrFail($id);
|
||||
return view('bo.sliders.edit', compact('slider'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
$slider = Slider::findOrFail($id);
|
||||
$label = $request->label;
|
||||
$slug = $request->slug;
|
||||
$commentaire = $request->commentaire;
|
||||
|
||||
|
||||
$request->validate([
|
||||
'label' => 'required|string|max:255',
|
||||
'slug' => 'required|unique:sliders,slug,' . $slider->id,
|
||||
]);
|
||||
|
||||
$slider->label = $label;
|
||||
$slider->slug = $slug;
|
||||
$slider->commentaire = $commentaire;
|
||||
$slider->save();
|
||||
|
||||
return redirect()->route('bo.sliders.edit', $slider->id)->with('success', 'Modifications enregistrées !');
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param integer $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(int $id)
|
||||
{
|
||||
$slider = Slider::findOrFail($id);
|
||||
|
||||
$count = Slider::count();
|
||||
|
||||
if ($count === 1) {
|
||||
return redirect()->back()->withErrors("Suppression impossible : Vous devez conserver au moins 1 Slider");
|
||||
}
|
||||
$slider->delete();
|
||||
return redirect()->route('bo.sliders.index');
|
||||
}
|
||||
}
|
||||
241
app/Http/Controllers/Bo/SlidesController.php
Normal file
241
app/Http/Controllers/Bo/SlidesController.php
Normal file
|
|
@ -0,0 +1,241 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Slide;
|
||||
use App\Models\Slider;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class SlidesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$slides = Slide::orderBy('order', 'ASC')->get();
|
||||
return view('bo.slides.index', compact('slides'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
$sliders = Slider::all();
|
||||
return view('bo.slides.create', compact('sliders'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$title = $request->title;
|
||||
$picture = $request->picture;
|
||||
$text = $request->text;
|
||||
$linkLabel = $request->link_label;
|
||||
$link = $request->link;
|
||||
$newTab = $request->link_new_tab === null ? 0 : 1;
|
||||
$sliderId = $request->slider_id;
|
||||
|
||||
if (empty($request->date_start_date)) {
|
||||
$date_start = null;
|
||||
} else {
|
||||
if (empty($request->date_start_time)) {
|
||||
$date_start = $request->date_start_date . " 00:00";
|
||||
} else {
|
||||
$date_start = $request->date_start_date . " " . $request->date_start_time;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($request->date_end_date)) {
|
||||
$date_end = null;
|
||||
} else {
|
||||
if (empty($request->date_end_time)) {
|
||||
$date_end = $request->date_end_date . " 23:59";
|
||||
} else {
|
||||
$date_end = $request->date_end_date . " " . $request->date_end_time;
|
||||
}
|
||||
}
|
||||
|
||||
$request->validate([
|
||||
'title' => 'required|max:255',
|
||||
'picture' => 'image|mimes:jpeg,png,jpg|max:2048|dimensions:max-width=' .
|
||||
config('theme.slide_image_maxwidth') . ',max-height=' .
|
||||
config('theme.slide_image_maxheight'),
|
||||
'link_label' => 'sometimes|max:255',
|
||||
'link' => 'sometimes|max:255',
|
||||
]);
|
||||
|
||||
$slide = new Slide();
|
||||
$slide->title = $title;
|
||||
$slide->text = $text;
|
||||
$slide->link_label = $linkLabel;
|
||||
$slide->link = $link;
|
||||
$slide->link_new_tab = $newTab;
|
||||
$slide->date_start = $date_start;
|
||||
$slide->date_end = $date_end;
|
||||
$slide->slider_id = $sliderId;
|
||||
$slide->order = $this->getLastOrder();
|
||||
$slide->save();
|
||||
|
||||
if ($picture !== null) {
|
||||
$imageName = $slide->id . '_' . Str::random(5) . '.' . $picture->extension();
|
||||
$picture->move(public_path('images/slides'), $imageName);
|
||||
$slide->picture = $imageName;
|
||||
$slide->save();
|
||||
}
|
||||
|
||||
return redirect()->route('bo.slides.edit', $slide->id)->with('success', 'Slide créé !');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param integer $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit(int $id)
|
||||
{
|
||||
$slide = Slide::findOrFail($id);
|
||||
$sliders = Slider::all();
|
||||
return view('bo.slides.edit', compact('slide', 'sliders'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
$title = $request->title;
|
||||
$picture = $request->picture;
|
||||
$text = $request->text;
|
||||
$linkLabel = $request->link_label;
|
||||
$link = $request->link;
|
||||
$newTab = $request->link_new_tab === null ? 0 : 1;
|
||||
$sliderId = $request->slider_id;
|
||||
|
||||
if (empty($request->date_start_date)) {
|
||||
$date_start = null;
|
||||
} else {
|
||||
if (empty($request->date_start_time)) {
|
||||
$date_start = $request->date_start_date . " 00:00";
|
||||
} else {
|
||||
$date_start = $request->date_start_date . " " . $request->date_start_time;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($request->date_end_date)) {
|
||||
$date_end = null;
|
||||
} else {
|
||||
if (empty($request->date_end_time)) {
|
||||
$date_end = $request->date_end_date . " 23:59";
|
||||
} else {
|
||||
$date_end = $request->date_end_date . " " . $request->date_end_time;
|
||||
}
|
||||
}
|
||||
|
||||
$request->validate([
|
||||
'title' => 'required|max:255',
|
||||
'picture' => 'image|mimes:jpeg,png,jpg|max:2048|dimensions:max-width=' .
|
||||
config('theme.slide_image_maxwidth') . ',max-height=' .
|
||||
config('theme.slide_image_maxheight'),
|
||||
'link_label' => 'sometimes|max:255',
|
||||
'link' => 'sometimes|max:255',
|
||||
]);
|
||||
|
||||
$slide = Slide::findOrFail($id);
|
||||
$slide->title = $title;
|
||||
$slide->text = $text;
|
||||
$slide->link_label = $linkLabel;
|
||||
$slide->link = $link;
|
||||
$slide->link_new_tab = $newTab;
|
||||
$slide->date_start = $date_start;
|
||||
$slide->date_end = $date_end;
|
||||
$slide->slider_id = $sliderId;
|
||||
$slide->save();
|
||||
|
||||
if ($picture !== null) {
|
||||
if (file_exists(public_path() . 'images/slides/' . $slide->picture)) {
|
||||
unlink(public_path() . 'images/slides/' . $slide->picture);
|
||||
}
|
||||
$imageName = $slide->id . '_' . Str::random(5) . '.' . $picture->extension();
|
||||
$picture->move(public_path('images/slides'), $imageName);
|
||||
$slide->picture = $imageName;
|
||||
$slide->save();
|
||||
}
|
||||
|
||||
return redirect()->route('bo.slides.edit', $slide->id)->with('success', 'Modifications enregistrées !');
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param integer $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(int $id)
|
||||
{
|
||||
$s = Slide::findOrFail($id);
|
||||
|
||||
$s->delete();
|
||||
|
||||
return redirect()->route('bo.slides.index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Change Slide Order
|
||||
*
|
||||
* @param integer $id
|
||||
* @param string $action
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function changeOrder(int $id, string $action)
|
||||
{
|
||||
$current = Slide::findOrFail($id);
|
||||
|
||||
if ($action === 'up') {
|
||||
$tmp = Slide::where('order', '<', $current->order)->orderBy('order', 'DESC')->first();
|
||||
$newOrder = $tmp->order;
|
||||
$tmp->order = $current->order;
|
||||
$current->order = $newOrder;
|
||||
} else {
|
||||
$tmp = Slide::where('order', '>', $current->order)->orderBy('order', 'ASC')->first();
|
||||
$newOrder = $tmp->order;
|
||||
$tmp->order = $current->order;
|
||||
$current->order = $newOrder;
|
||||
}
|
||||
$tmp->save();
|
||||
$current->save();
|
||||
|
||||
return back();
|
||||
}
|
||||
|
||||
/**
|
||||
* retreive order position to put a new slide to
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
private function getLastOrder()
|
||||
{
|
||||
$order = Slide::select('order')->orderBy('order', 'DESC')->first();
|
||||
if ($order === null) {
|
||||
return 1;
|
||||
}
|
||||
return $order->order + 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,149 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
use App\Enums\StaticPageType;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Bo\StaticPages\StoreStaticPageRequest;
|
||||
use App\Http\Requests\Bo\StaticPages\UpdateStaticPageRequest;
|
||||
use App\Models\StaticPage;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class StaticPageController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
/** @var \Illuminate\Database\Eloquent\Builder $static_pages */
|
||||
$static_pages = StaticPage::query()->where('type', '=', StaticPageType::crud());
|
||||
|
||||
if ($request->search) {
|
||||
$this->searchQuery(
|
||||
$static_pages,
|
||||
$request->search,
|
||||
null,
|
||||
'title',
|
||||
'value'
|
||||
);
|
||||
} //end if
|
||||
|
||||
$this->sortQuery($static_pages);
|
||||
$searchFields = trans('Titre, contenu');
|
||||
|
||||
$static_pages->orderBy('updated_at', 'DESC');
|
||||
$static_pages = $static_pages->paginate();
|
||||
|
||||
return view('back::pages.static_pages.index', compact('static_pages', 'searchFields'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
return view('back::pages.static_pages.create');
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Bo\StaticPages\StoreStaticPageRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(StoreStaticPageRequest $request)
|
||||
{
|
||||
return DB::transaction(function () use ($request) {
|
||||
$static_page = new StaticPage();
|
||||
// * Only crud pages are allowed to be created.
|
||||
$static_page->type = StaticPageType::crud();
|
||||
$static_page->fill($request->validated());
|
||||
|
||||
if ($static_page->saveOrFail()) {
|
||||
return redirect()
|
||||
->to(
|
||||
\App\Models\StaticPage::getBoRouteForType($static_page->type, 'edit') ??
|
||||
route('bo.static_pages.edit', $static_page->id)
|
||||
)
|
||||
->with('success', trans(
|
||||
':model a été créé',
|
||||
['model' => Str::singular(trans('models.classes.static_pages'))]
|
||||
));
|
||||
}
|
||||
return back();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \App\Models\StaticPage $static_page
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit(StaticPage $static_page)
|
||||
{
|
||||
return view('back::pages.static_pages.edit', ['static_pageModel' => $static_page]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Bo\StaticPages\UpdateStaticPageRequest $request
|
||||
* @param \App\Models\StaticPage $static_page
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(UpdateStaticPageRequest $request, StaticPage $static_page)
|
||||
{
|
||||
return DB::transaction(function () use ($request, $static_page) {
|
||||
try {
|
||||
$static_page->fill($request->validated());
|
||||
} catch (\ErrorException $e) {
|
||||
return back()
|
||||
->with('danger', trans(
|
||||
':model n\'a pas pu être enregistré car l\'image n\'a pu être transférée.',
|
||||
['model' => Str::singular(trans('models.classes.pages'))]
|
||||
));
|
||||
}
|
||||
|
||||
if ($static_page->saveOrFail()) {
|
||||
return redirect()
|
||||
->to(
|
||||
\App\Models\StaticPage::getBoRouteForType($static_page->type, 'edit') ??
|
||||
route('bo.static_pages.edit', $static_page->id)
|
||||
)
|
||||
->with('success', trans(
|
||||
':model a été créé',
|
||||
['model' => trans('Page')]
|
||||
));
|
||||
}
|
||||
return back();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \App\Models\StaticPage $static_page
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(StaticPage $static_page)
|
||||
{
|
||||
if ($static_page->deleteOrFail()) {
|
||||
return redirect()
|
||||
->route('bo.static_pages.index')
|
||||
->with('warning', trans(
|
||||
':model a bien été supprimé',
|
||||
['model' => Str::singular(trans('models.classes.static_pages'))]
|
||||
));
|
||||
}
|
||||
return back();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,151 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Bo\Tags\StoreTagRequest;
|
||||
use App\Http\Requests\Bo\Tags\UpdateTagRequest;
|
||||
use App\Models\Tag;
|
||||
use App\Traits\Controllers\ChangesModelOrder;
|
||||
use App\Traits\Controllers\UpdateModelStatus;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class TagController extends Controller
|
||||
{
|
||||
use ChangesModelOrder;
|
||||
use UpdateModelStatus;
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
/** @var \Illuminate\Database\Eloquent\Builder $tags */
|
||||
$tags = Tag::query();
|
||||
|
||||
if ($request->search) {
|
||||
$this->searchQuery(
|
||||
$tags,
|
||||
$request->search,
|
||||
null,
|
||||
'label'
|
||||
);
|
||||
}
|
||||
|
||||
$this->sortQuery($tags);
|
||||
$searchFields = trans('Label');
|
||||
|
||||
$tags = $tags->paginate();
|
||||
|
||||
return view('back::pages.tags.index', compact('tags', 'searchFields'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
return view('back::pages.tags.create');
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Bo\Tags\StoreTagRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(StoreTagRequest $request)
|
||||
{
|
||||
return DB::transaction(function () use ($request) {
|
||||
$tag = new Tag();
|
||||
$tag->fill($request->validated());
|
||||
|
||||
if ($tag->saveOrFail()) {
|
||||
return redirect()
|
||||
->route('bo.tags.edit', $tag)
|
||||
->with('success', trans(
|
||||
':model a été créé',
|
||||
['model' => Str::singular(trans('models.classes.tags'))]
|
||||
));
|
||||
}
|
||||
return back();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Bo\Tags\StoreTagRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function jsonStore(StoreTagRequest $request)
|
||||
{
|
||||
return DB::transaction(function () use ($request) {
|
||||
/** @var \App\Models\Tag */
|
||||
$tag = Tag::where('slug', Str::slug($request->name))->firstOrNew();
|
||||
$tag->fill($request->validated());
|
||||
$saved = $tag->saveOrFail();
|
||||
return \response()->json($saved ? $tag->toArray() : [], $saved ? 200 : 500);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \App\Models\Tag $tag
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit(Tag $tag)
|
||||
{
|
||||
return view('back::pages.tags.edit', ['tagModel' => $tag]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Bo\Tags\UpdateTagRequest $request
|
||||
* @param \App\Models\Tag $tag
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(UpdateTagRequest $request, Tag $tag)
|
||||
{
|
||||
return DB::transaction(function () use ($request, $tag) {
|
||||
$tag->fill($request->validated());
|
||||
if ($tag->saveOrFail()) {
|
||||
return redirect()
|
||||
->route('bo.tags.edit', $tag)
|
||||
->with('success', trans(
|
||||
':model a été mis à jour',
|
||||
['model' => Str::singular(trans('models.classes.tags'))]
|
||||
));
|
||||
} //end if
|
||||
return back();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \App\Models\Tag $tag
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(Tag $tag)
|
||||
{
|
||||
if ($tag->deleteOrFail()) {
|
||||
return redirect()
|
||||
->route('bo.tags.index')
|
||||
->with('warning', trans(
|
||||
':model a bien été supprimé',
|
||||
['model' => Str::singular(trans('models.classes.tags'))]
|
||||
));
|
||||
}
|
||||
return back();
|
||||
}
|
||||
}
|
||||
174
app/Http/Controllers/Bo/TagsController.php
Normal file
174
app/Http/Controllers/Bo/TagsController.php
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Tag;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class TagsController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$tags = Tag::orderBy('order', 'ASC')->get();
|
||||
return view('bo.tags.index', compact('tags'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
return view('bo.tags.create');
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$label = $request->label;
|
||||
$slug = Str::slug($label);
|
||||
$status = $request->status === null ? 0 : 1;
|
||||
|
||||
$request->validate([
|
||||
'label' => 'required|string|max:255',
|
||||
]);
|
||||
|
||||
$tag = new Tag();
|
||||
$tag->label = $label;
|
||||
$tag->slug = $slug;
|
||||
$tag->status = $status;
|
||||
$tag->order = $this->getLastOrder();
|
||||
$tag->save();
|
||||
|
||||
return redirect()->route('bo.tags.index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param integer $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit(int $id)
|
||||
{
|
||||
$tag = Tag::findOrFail($id);
|
||||
return view('bo.tags.edit', compact('tag'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
$label = $request->label;
|
||||
$slug = Str::slug($label);
|
||||
$status = $request->status === null ? 0 : 1;
|
||||
|
||||
$request->validate([
|
||||
'label' => 'required|string|max:255',
|
||||
]);
|
||||
|
||||
$tag = Tag::findOrFail($id);
|
||||
|
||||
$tag->label = $label;
|
||||
$tag->slug = $slug;
|
||||
$tag->status = $status;
|
||||
$tag->save();
|
||||
|
||||
return redirect()->route('bo.tags.edit', $tag->id)->with('success', 'Modifications enregistrés !');
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param integer $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(int $id)
|
||||
{
|
||||
$tag = Tag::findOrFail($id);
|
||||
|
||||
$products = $tag->products()->count();
|
||||
if ($products !== 0) {
|
||||
return redirect()->back()
|
||||
->withErrors("Suppression impossible : \"" . $tag->label . "\" est associé à des produits.");
|
||||
}
|
||||
|
||||
$tag->delete();
|
||||
return redirect()->route('bo.tags.index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Change Tag Order
|
||||
*
|
||||
* @param integer $id
|
||||
* @param string $action
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function changeOrder(int $id, string $action)
|
||||
{
|
||||
$current = Tag::findOrFail($id);
|
||||
|
||||
if ($action === 'up') {
|
||||
$tmp = Tag::where('order', '<', $current->order)->orderBy('order', 'DESC')->first();
|
||||
$newOrder = $tmp->order;
|
||||
$tmp->order = $current->order;
|
||||
$current->order = $newOrder;
|
||||
} else {
|
||||
$tmp = Tag::where('order', '>', $current->order)->orderBy('order', 'ASC')->first();
|
||||
$newOrder = $tmp->order;
|
||||
$tmp->order = $current->order;
|
||||
$current->order = $newOrder;
|
||||
}
|
||||
$tmp->save();
|
||||
$current->save();
|
||||
|
||||
return back();
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle tag status
|
||||
*
|
||||
* @param integer $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function toggleStatus(int $id)
|
||||
{
|
||||
$tag = Tag::findOrFail($id);
|
||||
$tag->status = !($tag->status);
|
||||
$tag->save();
|
||||
return back();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* retreive order position to put a new slide to
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public static function getLastOrder()
|
||||
{
|
||||
$order = Tag::select('order')->orderBy('order', 'DESC')->first();
|
||||
if ($order === null) {
|
||||
return 1;
|
||||
}
|
||||
return $order->order + 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
use App\Enums\TimeSlot\WeekDay;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Bo\Timeslots\UpdateTimeslotRequest;
|
||||
use App\Models\Shop;
|
||||
use App\Models\TimeslotSetting;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class TimeslotController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display timeslot settings form
|
||||
*
|
||||
* @param \App\Models\Shop $shop
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function settings(Shop $shop)
|
||||
{
|
||||
// @phpcs:enable
|
||||
$timeslotSettings = $shop->timeslotSettings;
|
||||
if ($timeslotSettings->count() === 0) {
|
||||
// Aucun settings pour ce magasin.
|
||||
$timeslotSettings = $this->makeCreneauxSettings($shop);
|
||||
}
|
||||
|
||||
return view('back::pages.timeslots.settings', [
|
||||
'timeslotSettings' => $timeslotSettings,
|
||||
'shopModel' => $shop
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve creneaux settings
|
||||
*
|
||||
* @param \App\Models\Shop $shop
|
||||
* @return mixed
|
||||
*/
|
||||
private function makeCreneauxSettings(Shop $shop)
|
||||
{
|
||||
return DB::transaction(function () use ($shop) {
|
||||
for ($i = 0; $i < 7; $i++) {
|
||||
$dayset = new TimeslotSetting();
|
||||
$dayset->day_index = \strval($i);
|
||||
$dayset->shop()->associate($shop);
|
||||
$dayset->saveOrFail();
|
||||
}
|
||||
return $shop->timeslotSettings;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* save settings
|
||||
*
|
||||
* @param \App\Http\Requests\Bo\Timeslots\UpdateTimeslotRequest $request
|
||||
* @param \App\Models\Shop $shop
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function updateSettings(UpdateTimeslotRequest $request, Shop $shop)
|
||||
{
|
||||
return DB::transaction(function () use ($request, $shop) {
|
||||
$validated = $request->validated()['plages'];
|
||||
foreach (WeekDay::toArray() as $weekDay) {
|
||||
$setting = TimeslotSetting::where('day', $weekDay)
|
||||
->whereHas('shop', function (Builder $q) use ($shop) {
|
||||
$q->where('id', $shop->id);
|
||||
})->firstOrFail();
|
||||
$setting->fill($validated[$weekDay->value]);
|
||||
$setting->saveOrFail();
|
||||
}
|
||||
|
||||
return redirect()->route('bo.timeslots.settings', $shop)
|
||||
->with('success', 'Modifications enregistrées !');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Bo\XmlIncos\SearchXmlInco;
|
||||
use App\Http\Resources\XmlIncoCollection;
|
||||
use App\Models\XmlInco;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Kwaadpepper\ImageResizer\ImageResizer;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
|
||||
class XmlIncoController extends Controller
|
||||
{
|
||||
/**
|
||||
* Download a file from inco storage.
|
||||
*
|
||||
* @param string $inco_picture
|
||||
* @return \Symfony\Component\HttpFoundation\StreamedResponse
|
||||
*/
|
||||
public function getXmlIncoPicture(string $inco_picture): StreamedResponse
|
||||
{
|
||||
if (!($picturePath = XmlInco::getXmlIncoPicturePath($inco_picture))) {
|
||||
abort(404);
|
||||
}
|
||||
/** @var \Illuminate\Filesystem\FilesystemAdapter */
|
||||
$disk = XmlInco::getDisk();
|
||||
|
||||
// * Resized inco picture if wanted.
|
||||
if (request()->get('resize')) {
|
||||
$resizedPath = ImageResizer::resizeImageOrIgnore(
|
||||
$disk->path($picturePath),
|
||||
'boIncoPicture'
|
||||
);
|
||||
$picturePath = $resizedPath ? $resizedPath : $picturePath;
|
||||
/** @var \Illuminate\Filesystem\FilesystemAdapter */
|
||||
$disk = Storage::disk('public');
|
||||
}
|
||||
|
||||
return \response()->streamDownload(function () use ($disk, $picturePath) {
|
||||
$stream = $disk->readStream($picturePath);
|
||||
\fpassthru($stream);
|
||||
\fclose($stream);
|
||||
}, $inco_picture, [
|
||||
'Content-Type' => $disk->mimeType($picturePath),
|
||||
'Content-Length' => $disk->size($picturePath),
|
||||
'Content-Disposition' => 'inline',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for xml inco
|
||||
*
|
||||
* @param \App\Http\Requests\Bo\XmlIncos\SearchXmlInco $request
|
||||
* @return \App\Http\Resources\XmlIncoCollection
|
||||
*/
|
||||
public function getXmlIncos(SearchXmlInco $request)
|
||||
{
|
||||
return new XmlIncoCollection(XmlInco::where('id', 'LIKE', "%$request->term%")
|
||||
->orWhere('descriptif', 'LIKE', "%$request->term%")
|
||||
->get());
|
||||
}
|
||||
}
|
||||
69
app/Http/Controllers/ContactController.php
Normal file
69
app/Http/Controllers/ContactController.php
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Requests\ContactFormRequest;
|
||||
use App\Mail\SendContactMail;
|
||||
use App\Models\Magasin;
|
||||
use App\Models\Setting;
|
||||
use App\Models\Content;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
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)
|
||||
{
|
||||
// @phpcs:enable
|
||||
$status = $request->session()->get('status');
|
||||
|
||||
$magasin = Magasin::first();
|
||||
$magasins = Magasin::all();
|
||||
|
||||
$content = Content::where('key', 'contact')->first();
|
||||
|
||||
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)
|
||||
{
|
||||
/** @var \App\Model\Magasin|null */
|
||||
$shop = Magasin::where('name', $request->shop)->first();
|
||||
|
||||
if ($shop and $shop->email_contact) {
|
||||
/** @var string */
|
||||
$toMail = $shop->email_contact;
|
||||
} else {
|
||||
/** @var string|null */
|
||||
$toMail = \optional(Setting::where('key', 'send_contact_mail_to')->first())->value;
|
||||
if (!$toMail) {
|
||||
/** @var string|null */
|
||||
$toMail = config('mail.from.address');
|
||||
}
|
||||
}
|
||||
|
||||
if (!$toMail) {
|
||||
throw new \RuntimeException('Impossible de trouver un mail');
|
||||
}
|
||||
|
||||
// Envoi du mail d'alerte.
|
||||
Mail::to($toMail)->send(new SendContactMail($request));
|
||||
|
||||
return back()->with('status', true);
|
||||
}
|
||||
}
|
||||
|
|
@ -2,166 +2,14 @@
|
|||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Gloudemans\Shoppingcart\Cart;
|
||||
use Gloudemans\Shoppingcart\CartItem;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Foundation\Bus\DispatchesJobs;
|
||||
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||
use Illuminate\Routing\Controller as BaseController;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
|
||||
class Controller extends BaseController
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
use DispatchesJobs;
|
||||
use ValidatesRequests;
|
||||
|
||||
/**
|
||||
* Build Search query on specified fields
|
||||
* splitting search into words or using whole sentence
|
||||
*
|
||||
* @param Builder $query The eloquent query builder.
|
||||
* @param string $search The query string.
|
||||
* @param callable $searchQuery The query string.
|
||||
* @param string ...$fields Either a simple array or a string
|
||||
* in case of a string the two fields would be concatenate to make the search.
|
||||
* @return Builder
|
||||
*/
|
||||
protected function searchQuery(
|
||||
Builder $query,
|
||||
string $search,
|
||||
callable $searchQuery = null,
|
||||
string ...$fields
|
||||
): Builder {
|
||||
if (count($fields)) {
|
||||
// Search using words.
|
||||
$words = explode(' ', $search);
|
||||
$query->where(function ($query) use ($searchQuery, $words, $search, $fields) {
|
||||
foreach ($words as $word) {
|
||||
if (!strlen($word)) {
|
||||
continue;
|
||||
}
|
||||
$this->searchOnFields($query, $word, $fields);
|
||||
} //end foreach
|
||||
// Search whole using whole sentence.
|
||||
$this->searchOnFields($query, $search, $fields);
|
||||
if ($searchQuery) {
|
||||
$searchQuery($query);
|
||||
}
|
||||
});
|
||||
} //end if
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build query search on all fields
|
||||
*
|
||||
* @param Builder $query
|
||||
* @param string $search
|
||||
* @param array $fields
|
||||
* @return Builder
|
||||
*/
|
||||
private function searchOnFields(Builder $query, string $search, array $fields): Builder
|
||||
{
|
||||
$table = $query->getModel()->getTable();
|
||||
foreach ($fields as $f) {
|
||||
$f = str_replace('?', '\?', $f);
|
||||
if (is_array($f)) {
|
||||
$query->orWhereRaw(
|
||||
sprintf("UPPER(CONCAT(%s)) LIKE UPPER(?)", collect($f)->map(function ($q) use ($table) {
|
||||
return "`$table`.`$q`";
|
||||
})->implode(', \' \', ')),
|
||||
['%' . filter_var($search, FILTER_SANITIZE_STRING) . '%']
|
||||
);
|
||||
} else {
|
||||
$query->orWhereRaw(
|
||||
"UPPER(`$table`.`$f`) LIKE UPPER(?)",
|
||||
['%' . filter_var($search, FILTER_SANITIZE_STRING) . '%']
|
||||
);
|
||||
}
|
||||
}
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort columns with a query
|
||||
*
|
||||
* @param Builder $query
|
||||
* @param array $ignore
|
||||
* @return Builder
|
||||
*/
|
||||
protected function sortQuery(Builder $query, array $ignore = []): Builder
|
||||
{
|
||||
$rName = request()->route()->getName();
|
||||
$table = $query->getModel()->getTable();
|
||||
if (request()->sort_col) {
|
||||
Session::put("$rName.sort_col", request()->sort_col);
|
||||
Session::put("$rName.sorted", true);
|
||||
}
|
||||
if (request()->sort_way) {
|
||||
Session::put("$rName.sort_way", request()->sort_way);
|
||||
Session::put("$rName.sorted", true);
|
||||
}
|
||||
if (request()->rst) {
|
||||
Session::remove("$rName.sorted");
|
||||
Session::remove("$rName.sort_col");
|
||||
Session::remove("$rName.sort_way");
|
||||
}
|
||||
if (request()->sort_col and request()->sort_way and Schema::hasColumn($table, request()->sort_col)) {
|
||||
if (
|
||||
!isset($ignore) or
|
||||
(isset($ignore) and !in_array(request()->sort_col, $ignore))
|
||||
) {
|
||||
$query = $query->orderBy(\sprintf("$table.%s", request()->sort_col), request()->sort_way);
|
||||
}
|
||||
} elseif (Schema::hasColumn($table, 'order')) {
|
||||
$query = $query->orderBy('order', 'ASC');
|
||||
Session::put("$rName.sort_col", 'order');
|
||||
Session::put("$rName.sort_way", 'asc');
|
||||
}
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter basket items to keep only the orderable ones
|
||||
*
|
||||
* ! Assert Model found, status true and orderable true.
|
||||
*
|
||||
* @param \Gloudemans\Shoppingcart\Cart $basket
|
||||
* @param array<string> $messages Will be filled with messages on warnings.
|
||||
* @return \Gloudemans\Shoppingcart\Cart
|
||||
*/
|
||||
protected function filterBasketKeepOnlyOrderableItems(Cart $basket, array &$messages = []): Cart
|
||||
{
|
||||
\collect($basket->content())->each(function (CartItem $item) use (&$basket, &$messages) {
|
||||
/** @var \App\Models\Product|null */
|
||||
$product = $item->model;
|
||||
if (!$product or !$product->status or !$product->orderable) {
|
||||
$basket->remove($item->rowId);
|
||||
$messages[] = \trans(
|
||||
'Le produit :name a été retiré du panier car il n\'est plus disponible',
|
||||
[
|
||||
'name' => $item->name
|
||||
]
|
||||
);
|
||||
}
|
||||
});
|
||||
return $basket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get basket as product list
|
||||
*
|
||||
* @param \Gloudemans\Shoppingcart\Cart $basket
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
protected function basketToList(Cart $basket): Collection
|
||||
{
|
||||
return $basket->content()->map(function (CartItem $cartItem) {
|
||||
return \json_decode(\json_encode($cartItem->toArray()));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
642
app/Http/Controllers/CustomerController.php
Normal file
642
app/Http/Controllers/CustomerController.php
Normal file
|
|
@ -0,0 +1,642 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Requests\CustomerRegisterRequest;
|
||||
use App\Http\Requests\LoginRequest;
|
||||
use App\Http\Requests\UpdateInfosRequest;
|
||||
use App\Mail\OrderCanceledConfirmMail;
|
||||
use App\Mail\PasswordResetMail;
|
||||
use App\Mail\RegisterConfirmMail;
|
||||
use App\Models\Customers;
|
||||
use App\Models\Magasin;
|
||||
use App\Models\Order;
|
||||
use App\Models\PasswordReset;
|
||||
use App\Models\Salarie;
|
||||
use App\Models\Setting;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Illuminate\Support\Str;
|
||||
use LDC\LDCCRM\Enums\ApiError;
|
||||
use LDC\LDCCRM\Enums\Country;
|
||||
use LDC\LDCCRM\Exceptions\ApiErrorException;
|
||||
use LDC\LDCCRM\Exceptions\CrmException;
|
||||
use LDC\LDCCRM\Exceptions\ValidationException;
|
||||
use LDC\LDCCRM\Models\Customer as CrmCustomer;
|
||||
|
||||
class CustomerController extends Controller
|
||||
{
|
||||
/**
|
||||
* Affiche la page d'inscription
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function registerForm()
|
||||
{
|
||||
if (Auth::guard('customer')->check()) {
|
||||
return redirect()->route('home');
|
||||
}
|
||||
|
||||
return view('auth.register');
|
||||
}
|
||||
|
||||
/**
|
||||
* Enregistre le customer dans la base de données
|
||||
* et CRM
|
||||
*
|
||||
* @param CustomerRegisterRequest $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function register(CustomerRegisterRequest $request)
|
||||
{
|
||||
try {
|
||||
return DB::transaction(function () use ($request) {
|
||||
$crmCustomer = new CrmCustomer(\array_intersect_key(
|
||||
$request->validated(),
|
||||
[
|
||||
'firstname' => '',
|
||||
'lastname' => '',
|
||||
'birth_date' => '',
|
||||
'address' => '',
|
||||
'postcode' => '',
|
||||
'country' => '',
|
||||
'city' => '',
|
||||
'phone' => '',
|
||||
'email' => '',
|
||||
'password' => '',
|
||||
'opt_in' => '',
|
||||
]
|
||||
));
|
||||
|
||||
$crmCustomer->city = $request->town;
|
||||
$crmCustomer->postcode = $request->postal_code;
|
||||
$crmCustomer->opt_in = $request->optin ? true : false;
|
||||
|
||||
// * Country Is forced to france
|
||||
$crmCustomer->country = Country::france();
|
||||
$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
|
||||
if ($request->matricule && $request->code) {
|
||||
/** @var \App\Models\Salarie $salarie */
|
||||
$salarie = Salarie::where('matricule', '=', $request->matricule)
|
||||
->where('code', '=', $request->code)
|
||||
->firstOrFail();
|
||||
$salarie->customer()->associate($customer);
|
||||
$salarie->saveOrFail();
|
||||
}
|
||||
|
||||
Mail::to($request->email)->send(new RegisterConfirmMail($customer, $request->firstname));
|
||||
|
||||
return view('auth.register-success', ['mail' => $request->email]);
|
||||
});
|
||||
} catch (ApiErrorException $e) {
|
||||
if ($e->getApiError()->equals(ApiError::customerExists())) {
|
||||
return back()->withInput()->withErrors('Un compte est déjà associé à cette adresse email.');
|
||||
}
|
||||
if ($e->getApiError()->equals(ApiError::validationFailed())) {
|
||||
return back()->withInput()->withErrors($e->getMessage());
|
||||
}
|
||||
report($e);
|
||||
return back()->withErrors('Une erreur est survenue, merci de réessayer ultérieurement.');
|
||||
} catch (ModelNotFoundException $e) {
|
||||
return back()->withErrors("Salarié $request->matricule, $request->code introuvable.");
|
||||
} catch (ValidationException $e) {
|
||||
return back()->withErrors($e->getMessage());
|
||||
} catch (\Exception | \TypeError | CrmException $e) {
|
||||
report($e);
|
||||
// * Une erreur critique est survenue avec la CRM
|
||||
return back()->withErrors('Une erreur est survenue, merci de réessayer ultérieurement.');
|
||||
} //end try
|
||||
return back()->withErrors('Une erreur est survenue, merci de réessayer ultérieurement.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la page de connexion
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function authenticateForm(Request $request)
|
||||
{
|
||||
if (Auth::guard('customer')->check()) {
|
||||
return redirect()->route('account.dashboard');
|
||||
}
|
||||
if ($request->get('url')) {
|
||||
Session::put('url.intended', $request->get('url'));
|
||||
Session::save();
|
||||
}
|
||||
return view('auth.login');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gère l'authentification des customers
|
||||
*
|
||||
* @param LoginRequest $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function authenticate(LoginRequest $request)
|
||||
{
|
||||
/** @var Customers|null */
|
||||
$customer = Customers::where('email', $request->email)->first();
|
||||
|
||||
try {
|
||||
/** @var \LDC\LDCCRM\CrmApiV2 */
|
||||
$crm = app('crmAPI');
|
||||
|
||||
// * Ne devrait pas survenir, $crm->login throws ApiError::authFailed()
|
||||
if (!$crm->login($request->email, $request->password)) {
|
||||
// * mauvais identifiants
|
||||
return back()->withErrors('Email ou mot de passe incorrect.');
|
||||
}
|
||||
|
||||
// Dans tout les cas : récupérer le crm user.
|
||||
$crmCustomer = $crm->getCustomer($request->email);
|
||||
|
||||
// Si pas de compte local mais existe en CRM.
|
||||
if (!$customer) {
|
||||
$customer = $this->createLocalCustomer($crmCustomer);
|
||||
}
|
||||
|
||||
return $this->processLogin($customer, $request->remember);
|
||||
} catch (ApiErrorException $e) {
|
||||
return $this->handleLoginApiErrorException($e, $request);
|
||||
} catch (CrmException | \Exception $e) {
|
||||
report($e);
|
||||
// Une erreur critique est survenue avec la CRM.
|
||||
return back()->withErrors('Une erreur est survenue, merci de réessayer ultérieurement.');
|
||||
} //end try
|
||||
}
|
||||
|
||||
/**
|
||||
* Active le compte d'un customer
|
||||
*
|
||||
* @param mixed $hashcode
|
||||
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
|
||||
*/
|
||||
public function activate($hashcode)
|
||||
{
|
||||
$hashcode = filter_var($hashcode, FILTER_SANITIZE_STRING);
|
||||
if (!($customer = Customers::select('hashcode')->where('hashcode', $hashcode)->first())) {
|
||||
return view('auth.activate')->with('message', 'Ce lien d\'activation n\'est pas valide.');
|
||||
}
|
||||
try {
|
||||
/** @var \LDC\LDCCRM\Models\Customer $crmCustomer */
|
||||
$crmCustomer = $customer->apiData;
|
||||
if ($crmCustomer->activate()) {
|
||||
return view('auth.activate')
|
||||
->with('message', 'Votre compte a bien été activé, vous pouvez désormais vous connecter.');
|
||||
}
|
||||
} catch (ApiErrorException $e) {
|
||||
if ($e->getApiError()->equals(ApiError::customerAlreadyActive())) {
|
||||
// phpcs:disable Generic.Files.LineLength.TooLong
|
||||
return view('auth.activate')
|
||||
->with('message', 'Votre compte est déjà activé, vous pouvez dès à présent vous connecter avec celui-ci.');
|
||||
}
|
||||
report($e);
|
||||
// Une erreur critique est survenue avec la CRM.
|
||||
return view('auth.activate')
|
||||
->with('message', 'Une erreur est survenue, merci de réessayer ultérieurement.');
|
||||
} catch (CrmException $e) {
|
||||
report($e);
|
||||
// Une erreur critique est survenue avec la CRM.
|
||||
return view('auth.activate')
|
||||
->with('message', 'Une erreur est survenue, merci de réessayer ultérieurement.');
|
||||
} //end try
|
||||
return view('auth.activate')->with('message', 'Ce lien d\'activation n\'est pas valide.');
|
||||
}
|
||||
|
||||
/**
|
||||
* deconnexion customer
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function logout()
|
||||
{
|
||||
if (Auth::guard('customer')->check()) {
|
||||
Auth::guard('customer')->logout();
|
||||
return redirect()->route('home');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
// @phpcs:enable
|
||||
return view('auth.passwords.forgot');
|
||||
}
|
||||
|
||||
/**
|
||||
* initialisation de la procédure de mdp oublié
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function passwordReset(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'email' => 'required|email:rfc|max:255',
|
||||
]);
|
||||
|
||||
$email = filter_var($request->email, FILTER_SANITIZE_EMAIL);
|
||||
|
||||
$customerExist = Customers::where('email', $email)->count() === 0 ? false : true;
|
||||
|
||||
if ($customerExist) {
|
||||
// Suppression des anciens tokens.
|
||||
PasswordReset::where('email', $email)->delete();
|
||||
|
||||
$token = Str::random(80);
|
||||
|
||||
$passwordReset = new PasswordReset();
|
||||
$passwordReset->email = $email;
|
||||
$passwordReset->token = $token;
|
||||
$passwordReset->created_at = now();
|
||||
$passwordReset->save();
|
||||
|
||||
Mail::to($email)->send(new PasswordResetMail($token));
|
||||
return back()->with(
|
||||
'success',
|
||||
__("La procédure pour changer votre mot de passe a été envoyé sur votre email.")
|
||||
);
|
||||
} else {
|
||||
return back()->withErrors(__("Cette adresse email n'est pas enregistrée dans nos services."));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the view used to change the password of a user when he required it
|
||||
* @param string $token Token used to identificate the user to change the password.
|
||||
* @return \Illuminate\Contracts\View\View The view to print
|
||||
*/
|
||||
public function viewChangePassword(string $token)
|
||||
{
|
||||
$pwdReset = PasswordReset::where('token', $token)->first();
|
||||
if (!$pwdReset) {
|
||||
abort(419);
|
||||
}
|
||||
$customer = Customers::where('email', $pwdReset->email)->first();
|
||||
if (!$customer) {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
return view('auth.passwords.reset', compact('customer'))->with('token', $token);
|
||||
}
|
||||
|
||||
/**
|
||||
* changement de mot de passe (depuis la procédure de mdp oublié)
|
||||
*
|
||||
* @param Request $request
|
||||
* @param mixed $token
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
|
||||
*/
|
||||
public function changePassword(Request $request, $token)
|
||||
{
|
||||
$request->validate([
|
||||
'password' => 'required|confirmed|min:8|max:255'
|
||||
]);
|
||||
|
||||
/** @var \App\Models\PasswordReset $passwordReset */
|
||||
$passwordReset = PasswordReset::where('token', $token)->first();
|
||||
/** @var \App\Models\Customers $customer */
|
||||
$customer = Customers::where('email', optional($passwordReset)->email)->firstOrFail();
|
||||
|
||||
/** @var \LDC\LDCCRM\CrmApiV2 */
|
||||
$crm = app('crmAPI');
|
||||
|
||||
try {
|
||||
if ($crm->login($customer->email, $request->password)) {
|
||||
return back()->withErrors('Vous ne pouvez pas utiliser un de vos anciens mot de passe.');
|
||||
}
|
||||
// phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch
|
||||
} catch (ApiErrorException $e) {
|
||||
// * continue
|
||||
}
|
||||
|
||||
try {
|
||||
if (!($crmCustomer = $crm->getCustomer($customer->hashcode))) {
|
||||
return back()
|
||||
->withErrors('Changement impossible, compte inexistant.');
|
||||
}
|
||||
$crmCustomer->password = $request->password;
|
||||
$crmCustomer->save();
|
||||
} catch (\TypeError | CrmException | ApiErrorException $e) {
|
||||
report($e);
|
||||
// Une erreur critique est survenue avec la CRM.
|
||||
return back()->withErrors('Une erreur est survenue, merci de réessayer ultérieurement.');
|
||||
} catch (ValidationException $e) {
|
||||
return back()->withErrors(sprintf('Nouveau mot de passe : %s', $e->getMessage()));
|
||||
}
|
||||
|
||||
$passwordReset->deleteOrFail();
|
||||
|
||||
return view('auth.passwords.reset-ok', compact('customer'));
|
||||
}
|
||||
|
||||
/**
|
||||
* profil client (mon compte)
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*
|
||||
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
|
||||
*/
|
||||
public function dashboard(Request $request)
|
||||
{
|
||||
// @phpcs:enable
|
||||
// Show Profile.
|
||||
/** @var \App\Models\Customers|null $customer */
|
||||
$customer = Auth::guard('customer')->user();
|
||||
if (!$customer) {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
/** @var \LDC\LDCCRM\Models\Customer $crmCustomer */
|
||||
$crmCustomer = $customer->apiData;
|
||||
|
||||
/** @var object $crmInfos */
|
||||
$crmInfos = \json_decode(\json_encode($crmCustomer));
|
||||
$birthDate = explode('-', $crmCustomer->birth_date);
|
||||
|
||||
return view('customer.dashboard', compact('customer', 'crmInfos', 'birthDate'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send a request to the CRM to change the given customer's informations
|
||||
* @param UpdateInfosRequest $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function updateInfos(UpdateInfosRequest $request)
|
||||
{
|
||||
if (($result = $this->updateUserInfo($request)) === true) {
|
||||
return back()->with('success', trans(
|
||||
'Vos informations ont bien été enregistrées.'
|
||||
));
|
||||
}
|
||||
return back()->withInput()->withErrors(
|
||||
$result !== false ? $result : trans(
|
||||
'Une erreur est survenue, merci de réessayer ultérieurement.'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* changement de mot de passe depuis le profil
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function changePasswordWhenAuthenticated(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'password' => 'required|min:8|confirmed|max:255'
|
||||
]);
|
||||
|
||||
$crm = app('crmApi');
|
||||
$customer = $crm->changePwdCustomer(Auth::guard('customer')->user()->crm_id, $request->password);
|
||||
|
||||
if ($customer->status === "OK") {
|
||||
return back()->with('success', __("Modifications enregistrés !"));
|
||||
} else {
|
||||
return back()->withErrors(__("Une erreur est survenue, merci de réessayer ultérieurement."));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
// @phpcs:enable
|
||||
$orders = Order::where('customer_id', Auth::guard('customer')->user()->id)->orderBy('date', 'DESC')->get();
|
||||
return view('customer.my-orders', compact('orders'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show detail commande
|
||||
*
|
||||
* @param string $reference
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function orderDetail(string $reference)
|
||||
{
|
||||
$order = Order::where('reference', '=', $reference)
|
||||
->where('customer_id', Auth::guard('customer')->user()->id)
|
||||
->firstOrFail();
|
||||
|
||||
if ($order->status_id == 1) {
|
||||
$magasin = null;
|
||||
} else {
|
||||
$magasin = Magasin::find($order->timeslot->magasin->id);
|
||||
}
|
||||
|
||||
return view('customer.order-detail', compact('order', 'magasin'));
|
||||
}
|
||||
|
||||
/**
|
||||
* mise au statut annulé d'une commande
|
||||
*
|
||||
* @param string $reference
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \RuntimeException If email missing.
|
||||
*/
|
||||
public function cancelOrder(string $reference)
|
||||
{
|
||||
/** @var \App\Models\Order|null */
|
||||
$order = Order::where('reference', $reference)->first();
|
||||
if (!$order) {
|
||||
throw new \RuntimeException('Impossible de trouver un enregistrement Order');
|
||||
}
|
||||
$order->status_id = 7;
|
||||
$order->save();
|
||||
|
||||
// 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');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a local customer
|
||||
*
|
||||
* @param CrmCustomer $crmCustomer
|
||||
* @return \app\Models\Customers
|
||||
* @throws \Throwable If saving to DB failed.
|
||||
*/
|
||||
private function createLocalCustomer(CrmCustomer $crmCustomer): Customers
|
||||
{
|
||||
/** @var \App\Models\Customers $customer */
|
||||
$customer = Customers::firstOrNew([
|
||||
'email' => $crmCustomer->email
|
||||
]);
|
||||
$customer->hashcode = $crmCustomer->hashcode;
|
||||
$customer->saveOrFail();
|
||||
|
||||
return $customer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Api error exception
|
||||
*
|
||||
* @param ApiErrorException $e
|
||||
* @param LoginRequest $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
private function handleLoginApiErrorException(ApiErrorException $e, LoginRequest $request)
|
||||
{
|
||||
/** @var Customers|null */
|
||||
$customer = Customers::where('email', $request->email)->first();
|
||||
/** @var \LDC\LDCCRM\CrmApiV2 */
|
||||
$crm = app('crmAPI');
|
||||
|
||||
switch ($e->getApiError()) {
|
||||
case ApiError::authFailed():
|
||||
// * mauvais identifiants
|
||||
return back()->withErrors('Email ou mot de passe incorrect.');
|
||||
case ApiError::customerNotActivated():
|
||||
// * le compte n'est pas activé
|
||||
if (!$customer) {
|
||||
try {
|
||||
if (!($crmCustomer = $crm->getCustomer($request->email))) {
|
||||
Log::critical(sprintf('Customer %s coulnd not be retrieved from crm', $request->email));
|
||||
return back()->withErrors(
|
||||
trans('Une erreur est survenue, merci de réessayer ultérieurement.')
|
||||
);
|
||||
}
|
||||
$customer = $this->createLocalCustomer($crmCustomer);
|
||||
} catch (CrmException | ApiErrorException $e) {
|
||||
report($e);
|
||||
// Une erreur critique est survenue avec la CRM.
|
||||
return back()->withErrors('Une erreur est survenue, merci de réessayer ultérieurement.');
|
||||
}
|
||||
}
|
||||
Mail::to($request->email)->send(new RegisterConfirmMail($customer, null));
|
||||
return back()
|
||||
->withErrors(
|
||||
trans('Votre compte n\'est pas activé, vérifiez dans vos emails pour y trouver
|
||||
le mail de confirmation. Un lien d\'activation vous a été renvoyé.')
|
||||
);
|
||||
default:
|
||||
report($e);
|
||||
// * une erreur non gérée
|
||||
return back()->withErrors('Une erreur est survenue, merci de réessayer ultérieurement.');
|
||||
} //end switch
|
||||
}
|
||||
|
||||
/**
|
||||
* Login a customer
|
||||
*
|
||||
* @param Customers $customer
|
||||
* @param boolean $remember
|
||||
* @return \Illuminate\Routing\Redirector|\Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
private function processLogin(Customers $customer, bool $remember)
|
||||
{
|
||||
/** @var \Illuminate\Auth\SessionGuard */
|
||||
$guard = auth('customer');
|
||||
$guard->login($customer, $remember);
|
||||
$url = Session::pull('url.intended');
|
||||
Session::forget('url.intended');
|
||||
Session::save();
|
||||
return !empty($url) ? redirect()->to($url) : redirect()->route('account.dashboard');
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates user info
|
||||
*
|
||||
* @param UpdateInfosRequest $request
|
||||
* @return boolean|string return strictly true if success,
|
||||
* false il failed, could be a string with message error if failed
|
||||
*/
|
||||
private function updateUserInfo(UpdateInfosRequest $request)
|
||||
{
|
||||
/** @var \App\Models\Customers */
|
||||
$customer = auth('customer')->user();
|
||||
if (!$customer) {
|
||||
return \redirect()->back();
|
||||
}
|
||||
|
||||
/** @var \LDC\LDCCRM\Models\Customer */
|
||||
$crmCustomer = $customer->apiData;
|
||||
|
||||
$data = [
|
||||
'firstname' => $request->firstname,
|
||||
'lastname' => $request->lastname,
|
||||
'birth_date' => $request->year . '-' . $request->month . '-' . $request->day,
|
||||
'address' => $request->address,
|
||||
'postcode' => $request->postcode,
|
||||
'city' => $request->city,
|
||||
'phone' => \strval($request->phone),
|
||||
'opt_in' => \boolval($request->optin),
|
||||
];
|
||||
|
||||
// * remove phone if empty
|
||||
if (isset($data['phone']) and !strlen($data['phone'])) {
|
||||
unset($data['phone']);
|
||||
}
|
||||
|
||||
try {
|
||||
$crmCustomer->fill($data);
|
||||
$crmCustomer->save();
|
||||
} catch (ValidationException $e) {
|
||||
return $e->getMessage();
|
||||
} catch (ApiErrorException $e) {
|
||||
if ($e->getApiError()->equals(ApiError::validationFailed())) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
report($e);
|
||||
return false;
|
||||
} catch (CrmException | \TypeError $e) {
|
||||
report($e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Fo\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Foundation\Auth\ConfirmsPasswords;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class ConfirmPasswordController extends Controller
|
||||
{
|
||||
use ConfirmsPasswords;
|
||||
|
||||
/**
|
||||
* Display the password confirmation view.
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function showConfirmForm()
|
||||
{
|
||||
if (Auth::guard('frontend')->check()) {
|
||||
return \response()->redirectToRoute('home');
|
||||
}
|
||||
return view('theme::auth.passwords.confirm');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the post register / login redirect path.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function redirectPath()
|
||||
{
|
||||
return response()->redirectToRoute('home')->getTargetUrl();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Fo\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Password;
|
||||
|
||||
class ForgotPasswordController extends Controller
|
||||
{
|
||||
use SendsPasswordResetEmails;
|
||||
|
||||
/**
|
||||
* Message to user
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $message =
|
||||
'Si votre compte existe vous devriez recevoir un message avec un lien pour réinitialiser votre mot de passe';
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('guest:frontend');
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the form to request a password reset link.
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function showLinkRequestForm()
|
||||
{
|
||||
return view('theme::auth.passwords.email');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the broker to be used during password reset.
|
||||
*
|
||||
* @return \Illuminate\Contracts\Auth\PasswordBroker
|
||||
*/
|
||||
public function broker()
|
||||
{
|
||||
return Password::broker('customers');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the response for a successful password reset link.
|
||||
* ! Dans les deux cas on ne divulgue pas si un user existe.
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
protected function sendResetLinkResponse()
|
||||
{
|
||||
return back()->with('info', trans($this->message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the response for a failed password reset link.
|
||||
* ! Dans les deux cas on ne divulgue pas si un user existe.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param string $response
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
protected function sendResetLinkFailedResponse(Request $request, string $response)
|
||||
{
|
||||
// ! Ne pas notifier que l'utilisateur n'existe pas.
|
||||
if ($response === 'passwords.user') {
|
||||
return back()->with('info', trans($this->message));
|
||||
}
|
||||
// * Renvoyer les autres message d'erreur style throttle.
|
||||
return back()
|
||||
->withInput($request->only('email'))
|
||||
->withErrors(['email' => trans($response)]);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,96 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Fo\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Providers\RouteServiceProvider;
|
||||
use Illuminate\Foundation\Auth\AuthenticatesUsers;
|
||||
use Illuminate\Foundation\Auth\ThrottlesLogins;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
|
||||
class LoginController extends Controller
|
||||
{
|
||||
use AuthenticatesUsers;
|
||||
use ThrottlesLogins;
|
||||
|
||||
/**
|
||||
* Where to redirect users after login.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $redirectTo = RouteServiceProvider::HOME;
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('guest:frontend')->except('logout');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the guard to be used during authentication.
|
||||
*
|
||||
* @return \Illuminate\Contracts\Auth\StatefulGuard
|
||||
*/
|
||||
protected function guard()
|
||||
{
|
||||
return Auth::guard('frontend');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the application's login form.
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function showLoginForm()
|
||||
{
|
||||
return view('theme::auth.login');
|
||||
}
|
||||
|
||||
/**
|
||||
* The user has been authenticated.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param null $user
|
||||
* @return mixed
|
||||
* @phpcs:disable Squiz.Commenting.FunctionComment.TypeHintMissing, Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
|
||||
*/
|
||||
protected function authenticated(Request $request, $user)
|
||||
{
|
||||
/** @var \App\Models\Customer|null */
|
||||
$user = Auth::guard('frontend')->user();
|
||||
if ($user) {
|
||||
$user->saveOrFail();
|
||||
Session::flash('info', trans('Vous êtes à présent connecté'));
|
||||
}
|
||||
// FIXME: Read destroy basket here.
|
||||
// OrderController::detroyCurrentBasket();
|
||||
}
|
||||
|
||||
/**
|
||||
* The user has logged out of the application.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return mixed
|
||||
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
|
||||
*/
|
||||
protected function loggedOut(Request $request)
|
||||
{
|
||||
Session::flash('info', trans('Vous êtes à présent déconnecté'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the post register / login redirect path.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function redirectPath()
|
||||
{
|
||||
return response()->redirectToRoute('home')->getTargetUrl();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,174 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Fo\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Fo\Customers\CreateAccountRequest;
|
||||
use App\Models\Customer;
|
||||
use Illuminate\Foundation\Auth\RegistersUsers;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use LDC\LDCCRM\Enums\ApiError;
|
||||
use LDC\LDCCRM\Enums\Country;
|
||||
use LDC\LDCCRM\Exceptions\ApiErrorException;
|
||||
use LDC\LDCCRM\Exceptions\ValidationException as CrmValidationException;
|
||||
use LDC\LDCCRM\Models\Customer as CrmCustomer;
|
||||
|
||||
class RegisterController extends Controller
|
||||
{
|
||||
use RegistersUsers;
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('guest:frontend');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the guard to be used during authentication.
|
||||
*
|
||||
* @return \Illuminate\Contracts\Auth\StatefulGuard
|
||||
*/
|
||||
protected function guard()
|
||||
{
|
||||
return Auth::guard('frontend');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the application registration form.
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function showRegistrationForm()
|
||||
{
|
||||
return view('theme::auth.register');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a validator for an incoming registration request.
|
||||
*
|
||||
* @param array $data
|
||||
* @return \Illuminate\Contracts\Validation\Validator
|
||||
* @throws \Illuminate\Validation\ValidationException If local client cannot validate data.
|
||||
*/
|
||||
protected function validator(array $data)
|
||||
{
|
||||
$data['optin'] = \request()->boolean('optin');
|
||||
$data['ok_cgv'] = \request()->boolean('ok_cgv');
|
||||
|
||||
// * Let Crm client validate data
|
||||
try {
|
||||
(new CrmCustomer())->fill($this->getOnlyCrmData($data));
|
||||
} catch (CrmValidationException $e) {
|
||||
throw ValidationException::withMessages([
|
||||
'error' => $e->getMessage()
|
||||
]);
|
||||
}
|
||||
$request = new CreateAccountRequest();
|
||||
|
||||
$data['phone'] = $data['phone'] ?? null;
|
||||
$data['opt_in'] = ($data['opt_in'] ?? false) ? true : false;
|
||||
return Validator::make(
|
||||
$data,
|
||||
$request->rules(),
|
||||
$request->messages(),
|
||||
$request->attributes()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new user instance after a valid registration.
|
||||
*
|
||||
* @param array $data
|
||||
* @return \App\Models\Customer
|
||||
* @throws \Illuminate\Validation\ValidationException If there are validation errors.
|
||||
* @throws \RuntimeException On unhandled api Error.
|
||||
*/
|
||||
protected function create(array $data)
|
||||
{
|
||||
$data['country'] = Country::france();
|
||||
|
||||
try {
|
||||
return DB::transaction(function () use ($data) {
|
||||
$crmCustomer = new CrmCustomer($this->getOnlyCrmData($data));
|
||||
|
||||
// * Country Is forced to france
|
||||
$crmCustomer->country = Country::france();
|
||||
$crmCustomer->save();
|
||||
|
||||
// * Enregistrement du Hashcode
|
||||
/** @var \App\Models\Customer $customer */
|
||||
$customer = new Customer($data);
|
||||
$customer->hashcode = $crmCustomer->hashcode;
|
||||
// * Customer will be logged in.
|
||||
$customer->last_connection = \now();
|
||||
$customer->saveOrFail();
|
||||
|
||||
if ($customer->saveOrFail()) {
|
||||
// phpcs:ignore Generic.Files.LineLength.TooLong
|
||||
Session::flash('success', trans('Votre compte à bien été crée, vous devez valider votre adresse email, un email de confirmation vous à été envoyé.'));
|
||||
}
|
||||
|
||||
return $customer;
|
||||
});
|
||||
} catch (ApiErrorException $e) {
|
||||
if ($e->getApiError()->equals(ApiError::customerExists())) {
|
||||
throw ValidationException::withMessages([
|
||||
'error' => 'Un compte est déjà associé à cette adresse email.'
|
||||
]);
|
||||
}
|
||||
if ($e->getApiError()->equals(ApiError::validationFailed())) {
|
||||
throw ValidationException::withMessages([
|
||||
'error' => $e->getMessage()
|
||||
]);
|
||||
}
|
||||
report($e);
|
||||
Log::error(__CLASS__ . '::create reached end of possibilities.');
|
||||
throw new \RuntimeException(__CLASS__ . '::create reached end of possibilities.');
|
||||
} //end try
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the post register / login redirect path.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function redirectPath()
|
||||
{
|
||||
return response()->redirectToRoute('account.dashboard')->getTargetUrl();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get only data used in crm
|
||||
*
|
||||
* @param array $data
|
||||
* @return array
|
||||
*/
|
||||
private function getOnlyCrmData(array $data): array
|
||||
{
|
||||
return \array_intersect_key(
|
||||
$data,
|
||||
[
|
||||
'firstname' => '',
|
||||
'lastname' => '',
|
||||
'birth_date' => '',
|
||||
'address' => '',
|
||||
'postcode' => '',
|
||||
'country' => '',
|
||||
'city' => '',
|
||||
'phone' => '',
|
||||
'email' => '',
|
||||
'password' => '',
|
||||
'opt_in' => '',
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,121 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Fo\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Auth\Events\PasswordReset;
|
||||
use Illuminate\Foundation\Auth\ResetsPasswords;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Password;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use LDC\LDCCRM\Exceptions\ApiErrorException;
|
||||
use LDC\LDCCRM\Exceptions\CrmException;
|
||||
use LDC\LDCCRM\Exceptions\ValidationException as ExceptionsValidationException;
|
||||
|
||||
class ResetPasswordController extends Controller
|
||||
{
|
||||
use ResetsPasswords;
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('guest:frontend');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the guard to be used during authentication.
|
||||
*
|
||||
* @return \Illuminate\Contracts\Auth\StatefulGuard
|
||||
*/
|
||||
protected function guard()
|
||||
{
|
||||
return Auth::guard('frontend');
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the password reset view for the given token.
|
||||
*
|
||||
* If no token is present, display the link request form.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
*/
|
||||
public function showResetForm(Request $request)
|
||||
{
|
||||
$token = $request->route()->parameter('token');
|
||||
|
||||
return view('theme::auth.passwords.reset')->with(
|
||||
['token' => $token, 'email' => $request->email]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the given user's password.
|
||||
*
|
||||
* @param mixed $customer
|
||||
* @param mixed $password
|
||||
* @return void
|
||||
* @throws \Illuminate\Validation\ValidationException If something goes wrong.
|
||||
*/
|
||||
protected function resetPassword($customer, $password)
|
||||
{
|
||||
/** @var \App\Models\Customer $user */
|
||||
/** @var string $password */
|
||||
|
||||
/** @var \LDC\LDCCRM\CrmApiV2 */
|
||||
$crm = app('crmAPI');
|
||||
|
||||
try {
|
||||
if (!($crmCustomer = $crm->getCustomer($customer->hashcode))) {
|
||||
throw ValidationException::withMessages([
|
||||
'error' => 'Changement impossible, compte inexistant.'
|
||||
]);
|
||||
}
|
||||
$crmCustomer->password = $password;
|
||||
$crmCustomer->save();
|
||||
} catch (\TypeError | CrmException | ApiErrorException $e) {
|
||||
report($e);
|
||||
throw ValidationException::withMessages([
|
||||
'error' => 'Une erreur est survenue, merci de réessayer ultérieurement.'
|
||||
]);
|
||||
} catch (ExceptionsValidationException $e) {
|
||||
throw ValidationException::withMessages([
|
||||
'error' => $e->getMessage()
|
||||
]);
|
||||
}
|
||||
|
||||
$customer->setRememberToken(Str::random(60));
|
||||
|
||||
$customer->save();
|
||||
|
||||
event(new PasswordReset($customer));
|
||||
|
||||
$this->guard()->login($customer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the post register / login redirect path.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function redirectPath()
|
||||
{
|
||||
return response()->redirectToRoute('home')->getTargetUrl();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the broker to be used during password reset.
|
||||
*
|
||||
* @return \Illuminate\Contracts\Auth\PasswordBroker
|
||||
*/
|
||||
public function broker()
|
||||
{
|
||||
return Password::broker('customers');
|
||||
}
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Fo\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Foundation\Auth\VerifiesEmails;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class VerificationController extends Controller
|
||||
{
|
||||
use VerifiesEmails;
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth:frontend');
|
||||
$this->middleware('signed')->only('verify');
|
||||
$this->middleware('throttle:6,1')->only('verify', 'resend');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the email verification notice.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View
|
||||
*/
|
||||
public function show(Request $request)
|
||||
{
|
||||
return $request->user()->hasVerifiedEmail()
|
||||
? redirect($this->redirectPath())
|
||||
: view('theme::auth.verify');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the post register / login redirect path.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function redirectPath()
|
||||
{
|
||||
return response()->redirectToRoute('home')->getTargetUrl();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,152 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Fo;
|
||||
|
||||
use App\Enums\Product\WeightUnit;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Product;
|
||||
use Gloudemans\Shoppingcart\Facades\Cart as FacadesCart;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class BasketController extends Controller
|
||||
{
|
||||
/**
|
||||
* Get Basket
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function getBasket()
|
||||
{
|
||||
$this->authorize('useBasketSystem', Product::class);
|
||||
/** @var \Gloudemans\Shoppingcart\Cart */
|
||||
$basket = app('basket');
|
||||
|
||||
return \response()->json($this->basketToList($basket));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajout d'un produit au panier
|
||||
*
|
||||
* ! Assert Model found, status true and orderable true.
|
||||
*
|
||||
* @param \App\Models\Product $product
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @throws \Illuminate\Validation\ValidationException Si le produit n'est pas disponible (orderable).
|
||||
*/
|
||||
public function addToBasket(Product $product)
|
||||
{
|
||||
$this->authorize('useBasketSystem', Product::class);
|
||||
$this->authorize('addToCart', $product);
|
||||
|
||||
/** @var \Gloudemans\Shoppingcart\Cart */
|
||||
$basket = app('basket');
|
||||
|
||||
$basket = $this->filterBasketKeepOnlyOrderableItems($basket);
|
||||
|
||||
if (!$product->status or !$product->orderable) {
|
||||
throw ValidationException::withMessages([
|
||||
'error' => \trans('Ce produit n\'est plus disponible')
|
||||
]);
|
||||
}
|
||||
|
||||
// ! Use cart facade here because of lib bug
|
||||
// ! https://github.com/bumbummen99/LaravelShoppingcart/pull/181
|
||||
// * Note Lib is is actually refactoring for laravel 9 php8 only
|
||||
// * https://github.com/bumbummen99/LaravelShoppingcart/pull/145
|
||||
/** @var \Gloudemans\Shoppingcart\CartItem */
|
||||
$cartItem = FacadesCart::add($product, 1, [
|
||||
'slug' => $product->slug,
|
||||
'picture' => $product->picture,
|
||||
'sell_unit' => $product->sell_unit,
|
||||
'weight_with_unit' => WeightUnit::getDisplayableWeight($product->weight),
|
||||
'discount_type' => \optional(\optional($product->discount)->type)->value,
|
||||
// * Prix ttc du produit
|
||||
'price_ttc' => $product->price_ttc,
|
||||
// * Prix ttc du produit remisé
|
||||
'undiscounted_price_ttc' => $product->undiscounted_price_ttc,
|
||||
]);
|
||||
|
||||
$cartItem->setTaxRate($product->tax_rate->rate / 100);
|
||||
$cartItem->setDiscountRate($product->discount_rate);
|
||||
|
||||
return \response()->json($this->basketToList($basket));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrait d'un produit du panier (1 quantité d'1 type)
|
||||
*
|
||||
* @param \App\Models\Product $product
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function removeFromBasket(Product $product)
|
||||
{
|
||||
$this->authorize('useBasketSystem', Product::class);
|
||||
|
||||
/** @var \Gloudemans\Shoppingcart\Cart */
|
||||
$basket = app('basket');
|
||||
|
||||
/** @var \Gloudemans\Shoppingcart\CartItem|null */
|
||||
$basketItem = $basket->content()->where('id', $product->id)->first();
|
||||
|
||||
/** @var string|null */
|
||||
$rowId = \optional($basketItem)->rowId;
|
||||
/** @var integer|null */
|
||||
$qty = \optional($basketItem)->qty;
|
||||
|
||||
if ($rowId and !\is_null($qty)) {
|
||||
$basket->update($rowId, $qty - 1);
|
||||
}
|
||||
|
||||
$basket = $this->filterBasketKeepOnlyOrderableItems($basket);
|
||||
|
||||
return \response()->json($this->basketToList($basket));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrait d'un type produit du panier (toute les quantités d'1 type)
|
||||
*
|
||||
* @param \App\Models\Product $product
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function removeItemTypeFromBasket(Product $product)
|
||||
{
|
||||
$this->authorize('useBasketSystem', Product::class);
|
||||
|
||||
/** @var \Gloudemans\Shoppingcart\Cart */
|
||||
$basket = app('basket');
|
||||
|
||||
/** @var \Gloudemans\Shoppingcart\CartItem|null */
|
||||
$basketItem = $basket->content()->where('id', $product->id)->first();
|
||||
|
||||
/** @var string|null */
|
||||
$rowId = \optional($basketItem)->rowId;
|
||||
|
||||
if ($rowId) {
|
||||
$basket->remove($rowId);
|
||||
}
|
||||
|
||||
$basket = $this->filterBasketKeepOnlyOrderableItems($basket);
|
||||
|
||||
return \response()->json($this->basketToList($basket));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrait d'un type produit du panier (toute les quantités d'1 type)
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function emptyBasket()
|
||||
{
|
||||
$this->authorize('useBasketSystem', Product::class);
|
||||
|
||||
/** @var \Gloudemans\Shoppingcart\Cart */
|
||||
$basket = app('basket');
|
||||
|
||||
$basket->destroy();
|
||||
|
||||
/** @var \Gloudemans\Shoppingcart\Cart */
|
||||
$basket = app('basket');
|
||||
|
||||
return \response()->json($this->basketToList($basket));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Fo;
|
||||
|
||||
use App\Enums\StaticPageType;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Fo\ContactFormRequest;
|
||||
use App\Models\Contact;
|
||||
use App\Models\StaticPage;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class ContactController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display contact from
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function contact(Request $request)
|
||||
{
|
||||
$status = $request->session()->get('status');
|
||||
|
||||
$content = StaticPage::getPageOfType(StaticPageType::contact());
|
||||
|
||||
return view('theme::pages.contact', compact('status', 'content'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit contact form
|
||||
*
|
||||
* @param \App\Http\Requests\Fo\ContactFormRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function contactSubmit(ContactFormRequest $request)
|
||||
{
|
||||
|
||||
$contact = new Contact($request->validated());
|
||||
if ($contact->saveOrFail()) {
|
||||
return redirect()
|
||||
->back()
|
||||
->with('status', true)
|
||||
->with('success', trans('Votre message à été envoyé'));
|
||||
}
|
||||
|
||||
return back();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,263 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Fo;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Fo\Ajax\SubscribeNewsletterRequest;
|
||||
use App\Http\Requests\Fo\Customers\ConfirmDeleteRequest;
|
||||
use App\Http\Requests\Fo\Customers\UpdateEmailRequest;
|
||||
use App\Http\Requests\Fo\Customers\UpdatePasswordRequest;
|
||||
use App\Http\Requests\Fo\Customers\UpdateInfosRequest;
|
||||
use App\Models\Customer;
|
||||
use App\Models\Order;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use LDC\LDCCRM\Enums\ApiError;
|
||||
use LDC\LDCCRM\Exceptions\ApiErrorException;
|
||||
use LDC\LDCCRM\Exceptions\CrmException;
|
||||
use LDC\LDCCRM\Exceptions\ValidationException as CrmValidationException;
|
||||
use LDC\LDCCRM\Models\SingleOptin;
|
||||
|
||||
class CustomerController extends Controller
|
||||
{
|
||||
// * --- Backoffice ---
|
||||
|
||||
/**
|
||||
* profil client (mon compte)
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function dashboard()
|
||||
{
|
||||
// Show Profile.
|
||||
/** @var \App\Models\Customer|null $customer */
|
||||
$customer = Auth::guard('frontend')->user();
|
||||
if (!$customer) {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
/** @var \LDC\LDCCRM\Models\Customer $crmCustomer */
|
||||
$crmCustomer = $customer->apiData;
|
||||
|
||||
/** @var object $crmInfos */
|
||||
$crmInfos = \json_decode(\json_encode($crmCustomer));
|
||||
|
||||
return view('theme::pages.customer.dashboard', compact('customer', 'crmInfos'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show update customer informations form
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
|
||||
*/
|
||||
public function email()
|
||||
{
|
||||
return view('theme::auth.change-email');
|
||||
}
|
||||
|
||||
/**
|
||||
* Uupdate customer email
|
||||
*
|
||||
* @param \App\Http\Requests\Fo\Customers\UpdateEmailRequest $request
|
||||
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
|
||||
*/
|
||||
public function emailSubmit(UpdateEmailRequest $request)
|
||||
{
|
||||
/** @var \App\Models\Customer */
|
||||
$customer = \auth('frontend')->user();
|
||||
|
||||
// FIXME:Add warning email to customer !!!
|
||||
|
||||
return $this->updateCrmCustomerInfo($customer, ['email' => $request->get('email')]) ?
|
||||
back()->with('success', trans('Vos informations ont bien été enregistrées.')) :
|
||||
back()->withInput()->withErrors(trans('Une erreur est survenue, merci de réessayer ultérieurement.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show update customer password form
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
|
||||
*/
|
||||
public function password()
|
||||
{
|
||||
return view('theme::auth.passwords.change');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update customer password
|
||||
*
|
||||
* @param UpdatePasswordRequest $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function passwordSubmit(UpdatePasswordRequest $request)
|
||||
{
|
||||
/** @var \App\Models\Customer */
|
||||
$customer = \auth('frontend')->user();
|
||||
|
||||
// FIXME:Add warning email to customer !!!
|
||||
|
||||
return $this->updateCrmCustomerInfo($customer, ['password' => $request->get('password')]) ?
|
||||
back()->with('success', trans('Vos informations ont bien été enregistrées.')) :
|
||||
back()->withInput()->withErrors(trans('Une erreur est survenue, merci de réessayer ultérieurement.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a request to the CRM to change the given customer's informations
|
||||
* @param \App\Http\Requests\Fo\UpdateInfosRequest $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function updateInfos(UpdateInfosRequest $request)
|
||||
{
|
||||
/** @var \App\Models\Customer */
|
||||
$customer = auth('frontend')->user();
|
||||
|
||||
return $this->updateCrmCustomerInfo($customer, $request->validated()) ?
|
||||
back()->with('success', trans('Vos informations ont bien été enregistrées.')) :
|
||||
back()->withInput()->withErrors(trans('Une erreur est survenue, merci de réessayer ultérieurement.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show customer delete account page
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
|
||||
*/
|
||||
public function destroy()
|
||||
{
|
||||
return view('theme::pages.customer.destroy');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show customer delete account page
|
||||
*
|
||||
* @param \App\Http\Requests\Fo\Customers\ConfirmDeleteRequest $request
|
||||
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
|
||||
*/
|
||||
public function destroySubmit(ConfirmDeleteRequest $request)
|
||||
{
|
||||
if ($request->confirm) {
|
||||
try {
|
||||
return DB::transaction(function () {
|
||||
|
||||
// FIXME:Add warning email to customer !!!
|
||||
|
||||
/** @var \App\Models\Customer */
|
||||
$customer = auth('frontend')->user();
|
||||
|
||||
/** @var \Ldc\LDCCRM\Models\Customer */
|
||||
$crmCustomer = $customer->api_data;
|
||||
|
||||
$customer->deleteOrFail();
|
||||
$crmCustomer->delete();
|
||||
|
||||
// * Force logout
|
||||
auth('frontend')->logout();
|
||||
|
||||
return response()->redirectToRoute('home')
|
||||
->with('info', trans(
|
||||
// phpcs:ignore Generic.Files.LineLength.TooLong
|
||||
'Votre compte à bien été supprimé, si vous avez des commandes en cours vous pouvez utiliser le formulaire de contact en cas de besoin.'
|
||||
));
|
||||
});
|
||||
} catch (\Exception $e) {
|
||||
report($e);
|
||||
Session::flash('error', trans('Une erreur est survenue veuillez réssayer plus tard.'));
|
||||
} //end try
|
||||
} //end if
|
||||
return back();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates user info
|
||||
*
|
||||
* @param \App\Models\Customer $customer
|
||||
* @param array $data
|
||||
* @return boolean
|
||||
* @throws \Illuminate\Validation\ValidationException If something failed.
|
||||
*/
|
||||
private function updateCrmCustomerInfo(Customer $customer, array $data)
|
||||
{
|
||||
return DB::transaction(function () use ($customer, $data) {
|
||||
try {
|
||||
/** @var \LDC\LDCCRM\Models\Customer */
|
||||
$crmCustomer = $customer->apiData;
|
||||
if (\array_key_exists('email', $data)) {
|
||||
$customer->email = $data['email'];
|
||||
$customer->saveOrFail();
|
||||
}
|
||||
$crmCustomer->fill($data);
|
||||
return $crmCustomer->save();
|
||||
} catch (CrmValidationException $e) {
|
||||
throw ValidationException::withMessages([
|
||||
'error' => $e->getMessage()
|
||||
]);
|
||||
} catch (ApiErrorException $e) {
|
||||
if ($e->getApiError()->equals(ApiError::validationFailed())) {
|
||||
throw ValidationException::withMessages([
|
||||
'error' => $e->getMessage()
|
||||
]);
|
||||
}
|
||||
report($e);
|
||||
return false;
|
||||
} //end try
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Affichage des commandes du customer connecté
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function myOrders()
|
||||
{
|
||||
/** @var \App\Models\Customer */
|
||||
$customer = auth('frontend')->user();
|
||||
|
||||
$orders = $customer->orders;
|
||||
return view('theme::pages.customer.my-orders', compact('orders'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show detail commande
|
||||
*
|
||||
* @param \App\Models\Order $order
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function orderDetail(Order $order)
|
||||
{
|
||||
$order->load('timeslot.shop');
|
||||
return view('theme::pages.customer.order-detail', compact('order'));
|
||||
}
|
||||
|
||||
// * --- END Backoffice ---
|
||||
|
||||
/**
|
||||
* Call the CRM to add a single optin
|
||||
*
|
||||
* @param \App\Http\Requests\Fo\Ajax\SubscribeNewsletterRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*
|
||||
*/
|
||||
public function addOptIn(SubscribeNewsletterRequest $request)
|
||||
{
|
||||
try {
|
||||
SingleOptin::setStatus($request->email, true);
|
||||
return \response()->json();
|
||||
} catch (ApiErrorException $e) {
|
||||
// * Il y a deja un customerInfo avec optin a true pour ce customer
|
||||
if ($e->getApiError()->equals(ApiError::singleOptinCustomerExists())) {
|
||||
return \response()->json([
|
||||
'errors' => [
|
||||
'email' => [\trans('Vous êtes déjà inscrit avec cette adresse email')]
|
||||
]
|
||||
], 422);
|
||||
}
|
||||
report($e);
|
||||
return \response()->json([], 500);
|
||||
} catch (CrmException $e) {
|
||||
report($e);
|
||||
return \response()->json([], 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,536 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Fo;
|
||||
|
||||
use App\Enums\DeliveryMode\DeliveryModeEnum;
|
||||
use App\Enums\GeneralConfigType;
|
||||
use App\Enums\Order\DeliveryStatus;
|
||||
use App\Enums\Order\OrderProcess;
|
||||
use App\Enums\Order\PaymentStatus;
|
||||
use App\Enums\Order\ValidationStatus;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Fo\Orders\CheckoutRequest;
|
||||
use App\Http\Requests\Fo\Orders\SetOrderTimeSlotRequest;
|
||||
use App\Http\Requests\Fo\Orders\ShippingFormRequest;
|
||||
use App\Http\Requests\Fo\Orders\ShippingModeFormRequest;
|
||||
use App\Http\Resources\ShopResource;
|
||||
use App\Mail\NewOrderIncome;
|
||||
use App\Models\Customer;
|
||||
use App\Models\DeliveryMode;
|
||||
use App\Models\GeneralConfig;
|
||||
use App\Models\Order;
|
||||
use App\Models\Shop;
|
||||
use App\Models\Timeslot;
|
||||
use App\Notifications\OrderCreated;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use LDC\LDCCRM\Enums\Country;
|
||||
|
||||
class OrderController extends Controller
|
||||
{
|
||||
// * --- TUNNEL DE COMMANDE ---
|
||||
/**
|
||||
* Récapitualtif du panier
|
||||
*
|
||||
* * --- 1 ---
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function basketRecap()
|
||||
{
|
||||
$this->assertDoesNotHaveEmptyBasket();
|
||||
$this->assertBasketDidNotChange();
|
||||
// * On peut passer commande ?
|
||||
$this->authorize('orderThings', Order::class);
|
||||
$this->setOrderProcessStep(OrderProcess::reviewBasket());
|
||||
|
||||
/** @var \Gloudemans\Shoppingcart\Cart */
|
||||
$basket = app('basket');
|
||||
$messages = [];
|
||||
|
||||
$basket = $this->filterBasketKeepOnlyOrderableItems($basket, $messages);
|
||||
|
||||
if (!empty($messages)) {
|
||||
Session::flash('warning', \collect($messages)->implode(",\n"));
|
||||
}
|
||||
|
||||
$basketItems = $this->basketToList($basket);
|
||||
|
||||
return view('theme::pages.order-tunnel.basket-recap', compact(
|
||||
'basket',
|
||||
'basketItems'
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Select shipping Mode And create Session Order
|
||||
*
|
||||
* * --- 2 ---
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function shippingMode()
|
||||
{
|
||||
$this->assertDoesNotHaveEmptyBasket();
|
||||
$this->assertBasketDidNotChange();
|
||||
$this->setOrderProcessStep(OrderProcess::shippingMethod(), OrderProcess::reviewBasket());
|
||||
|
||||
// * CREATE ORDER
|
||||
|
||||
/** @var \App\Models\Customer $customer */
|
||||
$customer = auth('frontend')->user();
|
||||
|
||||
/** @var \Gloudemans\Shoppingcart\Cart */
|
||||
$basket = app('basket');
|
||||
|
||||
/** @var \App\Models\Order|null $order */
|
||||
$order = Order::getCurrentOrder();
|
||||
|
||||
// * If there was a previous order that was not ended use the ID.
|
||||
/** @var \App\Models\Order */
|
||||
$order = $order ?? new Order();
|
||||
$order->mail_sent = false;
|
||||
$order->delivery_status = DeliveryStatus::pending();
|
||||
$order->payment_status = PaymentStatus::pending();
|
||||
$order->validation_status = ValidationStatus::pending();
|
||||
$order->assignBasket($basket);
|
||||
$order->customer()->associate($customer);
|
||||
|
||||
// * Save Session Order
|
||||
Session::put('currentOrder', $order);
|
||||
|
||||
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\DeliveryMode> */
|
||||
$deliveryModes = app('DeliveryModesGlobal');
|
||||
|
||||
return view('theme::pages.order-tunnel.shipping-mode', \compact('deliveryModes'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Save shipping Mode
|
||||
*
|
||||
* * --- 2 ---
|
||||
*
|
||||
* @param \App\Http\Requests\Fo\Orders\ShippingModeFormRequest $request
|
||||
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
|
||||
*/
|
||||
public function shippingModeSubmit(ShippingModeFormRequest $request)
|
||||
{
|
||||
$this->assertDoesNotHaveEmptyBasket();
|
||||
$this->assertBasketDidNotChange();
|
||||
$this->assertDoesHaveCurrentOrder();
|
||||
$this->setOrderProcessStep(OrderProcess::shippingMethod(), OrderProcess::reviewBasket());
|
||||
|
||||
/** @var \App\Models\DeliveryMode $mode */
|
||||
if (!($mode = DeliveryMode::availables()->whereId($request->mode)->first())) {
|
||||
$e = new \RuntimeException('Mode de livraison non disponible', 1);
|
||||
report($e);
|
||||
Session::flash('error', trans('Mode de livraison non disponible'));
|
||||
return \back()->withException($e);
|
||||
}
|
||||
|
||||
/** @var \App\Models\Order $order */
|
||||
$order = Order::getCurrentOrder();
|
||||
|
||||
$order->deliveryMode()->associate($mode);
|
||||
|
||||
Session::put('currentOrder', $order);
|
||||
|
||||
return \response()->redirectToRoute('order-tunnel.shipping');
|
||||
}
|
||||
|
||||
/**
|
||||
* Shipping informations
|
||||
*
|
||||
* * --- 3 ---
|
||||
*
|
||||
* ! Pour - Click and collect
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
|
||||
* @throws \RuntimeException If delivery mode is unhandled.
|
||||
*/
|
||||
public function shipping()
|
||||
{
|
||||
$this->assertDoesNotHaveEmptyBasket();
|
||||
$this->assertBasketDidNotChange();
|
||||
$this->assertDoesHaveCurrentOrder();
|
||||
$this->setOrderProcessStep(OrderProcess::shippment(), OrderProcess::shippingMethod());
|
||||
|
||||
/** @var \App\Models\Order $order */
|
||||
$order = Order::getCurrentOrder();
|
||||
|
||||
// * Switch Delivery modes
|
||||
// * Pour afficher formulaire qui devra retourner une adresse 'shipping'
|
||||
/**
|
||||
* * Switch Delivery modes
|
||||
* - Pour afficher formulaire qui devra retourner une adresse 'shipping'.
|
||||
* - Qui devra fournir un timeslot dans le cas de clickAndCollect.
|
||||
*/
|
||||
/** @var \App\Enums\DeliveryMode\DeliveryModeEnum|null */
|
||||
$delivery_mode = \optional($order->deliveryMode)->mode;
|
||||
switch ($delivery_mode) {
|
||||
case DeliveryModeEnum::inShop():
|
||||
// * 1 Select timeslot if not already done.
|
||||
if (!$order->timeslot()->first() or !Session::get('deliveryModePickSlot')) {
|
||||
$shops = Shop::all()->map(function (Shop $shop) {
|
||||
return new ShopResource($shop);
|
||||
});
|
||||
Session::put('deliveryModePickSlot', true);
|
||||
return \view('theme::pages.order-tunnel.pick-slot', \compact('order', 'shops'));
|
||||
}
|
||||
return \view('theme::pages.order-tunnel.shipping', \compact('order'));
|
||||
default:
|
||||
throw new \RuntimeException('Unhandled delivery mode ');
|
||||
}
|
||||
|
||||
throw new \RuntimeException('This should never happen');
|
||||
}
|
||||
|
||||
/**
|
||||
* Save and validate timeslot
|
||||
*
|
||||
* * --- 3 ---
|
||||
*
|
||||
* @param \App\Http\Requests\Fo\Orders\SetOrderTimeSlotRequest $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Validation\ValidationException If Creneau is not available anomore.
|
||||
*/
|
||||
public function validateSelectedTimeSlot(SetOrderTimeSlotRequest $request)
|
||||
{
|
||||
$this->assertDoesNotHaveEmptyBasket();
|
||||
$this->assertBasketDidNotChange();
|
||||
$this->assertDoesHaveCurrentOrder();
|
||||
$this->setOrderProcessStep(OrderProcess::shippment(), OrderProcess::shippingMethod());
|
||||
/** @var \App\Models\Shop */
|
||||
$shop = Shop::query()->where('id', $request->shop_id)->firstOrFail();
|
||||
$creneau = Carbon::createFromFormat('d/m/Y H:i', "{$request->selected_day} {$request->selected_time}");
|
||||
if (!$shop->isCreneauAvailable($creneau)) {
|
||||
throw ValidationException::withMessages([
|
||||
'error' => 'Ce créneau n\'est plus disponible'
|
||||
]);
|
||||
}
|
||||
|
||||
DB::transaction(function () use ($shop, $creneau) {
|
||||
/** @var \App\Models\Order $order */
|
||||
$order = Order::getCurrentOrder();
|
||||
// * Assign order uuid we would use, if none already.
|
||||
if (!$order->uuid) {
|
||||
$order->uuid = Str::uuid();
|
||||
}
|
||||
Session::put('currentOrder', $order);
|
||||
|
||||
/** @var \App\Models\Timeslot */
|
||||
$timeSlot = Timeslot::query()->where('order_uuid', $order->uuid)->firstOrNew();
|
||||
$timeSlot->order()->associate($order);
|
||||
$timeSlot->shop()->associate($shop);
|
||||
$timeSlot->slot = $creneau;
|
||||
$timeSlot->saveOrFail();
|
||||
});
|
||||
return response()->redirectToRoute('order-tunnel.shipping');
|
||||
}
|
||||
|
||||
/**
|
||||
* SaveShippingAdress
|
||||
*
|
||||
* * --- 3 ---
|
||||
*
|
||||
* @param \App\Http\Requests\Fo\Orders\ShippingFormRequest $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \RuntimeException If somehow no email can be found.
|
||||
*/
|
||||
public function shippingSubmit(ShippingFormRequest $request)
|
||||
{
|
||||
$this->assertDoesNotHaveEmptyBasket();
|
||||
$this->assertDoesHaveCurrentOrder();
|
||||
$this->assertBasketDidNotChange();
|
||||
$this->setOrderProcessStep(OrderProcess::shippment(), OrderProcess::shippingMethod());
|
||||
|
||||
/** @var \App\Models\Order $order */
|
||||
$order = Order::getCurrentOrder();
|
||||
|
||||
$order->fill($request->validated());
|
||||
|
||||
/** @var object */
|
||||
$billing = $order->billing;
|
||||
$billing->country = Country::france();
|
||||
$order->billing = $billing;
|
||||
|
||||
Session::put('deliveryModePickSlot', false);
|
||||
|
||||
// Fetch right email to send in.
|
||||
if ($order->billing->email) {
|
||||
$order->email = $order->billing->email;
|
||||
} elseif ($order->shipping->email) {
|
||||
$order->email = $order->shipping->email;
|
||||
} else {
|
||||
$order->email = $order->customer->api_data->email;
|
||||
}
|
||||
|
||||
if (!$order->email) {
|
||||
throw new \RuntimeException('Somehow no email was provided');
|
||||
}
|
||||
|
||||
$this->fillShippingFromShopInfo($order);
|
||||
|
||||
Session::put('currentOrder', $order);
|
||||
|
||||
return \response()->redirectToRoute('order-tunnel.review');
|
||||
}
|
||||
|
||||
/**
|
||||
* Valider le panier avant achat.
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
|
||||
*/
|
||||
public function review()
|
||||
{
|
||||
$this->assertDoesNotHaveEmptyBasket();
|
||||
$this->assertBasketDidNotChange();
|
||||
$this->assertDoesHaveCurrentOrder();
|
||||
$this->setOrderProcessStep(OrderProcess::paymentReview(), OrderProcess::shippment());
|
||||
|
||||
/** @var \App\Models\Customer $customer */
|
||||
$customer = auth('frontend')->user();
|
||||
|
||||
/** @var \App\Models\Order $order */
|
||||
$order = Order::getCurrentOrder();
|
||||
|
||||
// * Order completed email already sent.
|
||||
if ($order->mail_sent) {
|
||||
self::detroyCurrentBasket();
|
||||
return \view('theme::pages.order-tunnel.done', \compact('order'));
|
||||
}
|
||||
|
||||
/** @var \Gloudemans\Shoppingcart\Cart */
|
||||
$basket = app('basket');
|
||||
|
||||
return view('theme::pages.order-tunnel.review', \compact('basket', 'order'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup Order for stripe submit
|
||||
*
|
||||
* @param \App\Http\Requests\Fo\Orders\CheckoutRequest $request
|
||||
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
|
||||
* @throws \RuntimeException If payment method is unhandled somehow.
|
||||
*/
|
||||
public function reviewSubmit(CheckoutRequest $request)
|
||||
{
|
||||
$this->assertDoesNotHaveEmptyBasket();
|
||||
$this->assertBasketDidNotChange();
|
||||
$this->assertDoesHaveCurrentOrder();
|
||||
$this->setOrderProcessStep(OrderProcess::paymentReview(), OrderProcess::shippment());
|
||||
|
||||
/** @var \App\Models\Customer $customer */
|
||||
$customer = auth('frontend')->user();
|
||||
|
||||
/** @var \App\Models\Order $order */
|
||||
$order = Order::getCurrentOrder();
|
||||
|
||||
// * Order completed email already sent.
|
||||
if ($order->mail_sent) {
|
||||
self::detroyCurrentBasket();
|
||||
return \view('theme::pages.order-tunnel.done', \compact('order'));
|
||||
}
|
||||
|
||||
if ($request->method === 'cnc') {
|
||||
return $this->checkoutCnC($customer, $order);
|
||||
}
|
||||
|
||||
throw new \RuntimeException('Unhandled method payment');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checkout click and collect
|
||||
*
|
||||
* @param \App\Models\Customer $customer
|
||||
* @param \App\Models\Order $order
|
||||
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
|
||||
* @throws \Illuminate\Validation\ValidationException If saving order fails.
|
||||
*/
|
||||
private function checkoutCnC(Customer $customer, Order $order)
|
||||
{
|
||||
return DB::transaction(function () use ($customer, $order) {
|
||||
// * Notification has been sent
|
||||
$order->mail_sent = true;
|
||||
|
||||
// * Enregistrement commande + envoi de mail.
|
||||
if (!$order->save()) {
|
||||
report(new \RuntimeException("Order saving error happened."));
|
||||
throw ValidationException::withMessages([
|
||||
'error' => trans('Une erreur est survenue, veuillez réssayer')
|
||||
]);
|
||||
}
|
||||
|
||||
// * Notifiy customer
|
||||
$customer->notify(new OrderCreated($order));
|
||||
|
||||
/** @var object|null */
|
||||
$notificationMail = \optional(\optional(GeneralConfig::query()->where('type', GeneralConfigType::global())
|
||||
->first())->data)->confirmed_orders_destination_email;
|
||||
if (!\optional($notificationMail)->value) {
|
||||
throw new \RuntimeException('Could not get new order email notification setting');
|
||||
}
|
||||
Mail::to($notificationMail->value)->send(new NewOrderIncome($order));
|
||||
|
||||
self::detroyCurrentBasket();
|
||||
|
||||
return \view('theme::pages.order-tunnel.done', \compact('order'));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// * --- FIN TUNNEL DE COMMANDE ---
|
||||
// * PRIVATE METHODS
|
||||
|
||||
/**
|
||||
* Assert user does not have an empty basket
|
||||
* or redirect with warning
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function assertDoesHaveCurrentOrder()
|
||||
{
|
||||
$order = Order::getCurrentOrder();
|
||||
if (
|
||||
$order = Order::getCurrentOrder() and
|
||||
$order->payment_status and
|
||||
$order->payment_status->equals(PaymentStatus::payed())
|
||||
) {
|
||||
self::detroyCurrentBasket();
|
||||
abort(\response()->view('theme::pages.order-tunnel.done', \compact('order')));
|
||||
}
|
||||
|
||||
if (!$order) {
|
||||
\redirect()->route('order-tunnel.basket.recap')->throwResponse();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete order steps, removes basket, ends tunnel transaction.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function detroyCurrentBasket()
|
||||
{
|
||||
/** @var \Gloudemans\Shoppingcart\Cart */
|
||||
$basket = app('basket');
|
||||
$basket->destroy();
|
||||
|
||||
Session::remove('currentOrder');
|
||||
Session::remove('PreviousOrderStep');
|
||||
Session::remove('OrderStep');
|
||||
Session::remove('deliveryModePickSlot');
|
||||
Session::remove('basketFingerPrint');
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert user does not have an empty basket
|
||||
* or redirect with warning
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function assertDoesNotHaveEmptyBasket(): void
|
||||
{
|
||||
/** @var \Gloudemans\Shoppingcart\Cart */
|
||||
$basket = app('basket');
|
||||
|
||||
if (!$basket->count()) {
|
||||
\redirect()->route('home')
|
||||
->with('warning', trans('Vous n\'avez aucun produit dans votre panier'))
|
||||
->throwResponse();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert user does not have an empty basket
|
||||
* or redirect with warning
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function assertBasketDidNotChange(): void
|
||||
{
|
||||
/** @var \Gloudemans\Shoppingcart\Cart */
|
||||
$basket = app('basket');
|
||||
$actual_finger_print = hash('sha256', \json_encode($basket->content()->jsonSerialize()));
|
||||
$session_finger_print = Session::get('basketFingerPrint');
|
||||
|
||||
Session::put('basketFingerPrint', $actual_finger_print);
|
||||
|
||||
if ($session_finger_print !== $actual_finger_print) {
|
||||
Session::remove('deliveryModePickSlot');
|
||||
\redirect()->route('order-tunnel.basket.recap')
|
||||
->with('warning', trans('Votre panier à été modifié'))
|
||||
->throwResponse();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate Process step
|
||||
*
|
||||
* @param \App\Enums\Order\OrderProcess $step
|
||||
* @param \App\Enums\Order\OrderProcess|null $assertDid
|
||||
* @return void
|
||||
* @throws \Illuminate\Validation\ValidationException If previous was not done.
|
||||
*/
|
||||
private function setOrderProcessStep(OrderProcess $step, OrderProcess $assertDid = null): void
|
||||
{
|
||||
if ($assertDid) {
|
||||
if (!Session::get('PreviousOrderStep')) {
|
||||
Session::put('PreviousOrderStep', collect());
|
||||
}
|
||||
/** @var \Illuminate\Support\Collection */
|
||||
$previousSteps = Session::get('PreviousOrderStep');
|
||||
if (Session::get('OrderStep') < $step) {
|
||||
/** @var \App\Enums\OrderProcess */
|
||||
$previousStep = Session::get('OrderStep');
|
||||
$previousSteps->put($previousStep->value, $previousStep);
|
||||
Session::put('PreviousOrderStep', $previousSteps);
|
||||
}
|
||||
if (!$previousSteps->count()) {
|
||||
\redirect()->route('home')
|
||||
->with('warning', trans('Vous devez d\'abord valider votre panier'))
|
||||
->throwResponse();
|
||||
}
|
||||
if (!$previousSteps->contains($assertDid)) {
|
||||
throw ValidationException::withMessages(['Étape précédente requise']);
|
||||
}
|
||||
} //end if
|
||||
|
||||
Session::put('OrderStep', $step);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill order shipping with in shop infos
|
||||
*
|
||||
* @param \App\Models\Order $order
|
||||
* @return void
|
||||
* @throws \Illuminate\Validation\ValidationException Si le créneau de reservation n'est plus trouvable.
|
||||
*/
|
||||
private function fillShippingFromShopInfo(Order $order)
|
||||
{
|
||||
/** @var \App\Models\Customer */
|
||||
$user = auth('frontend')->user();
|
||||
if ($order->deliveryMode->mode->equals(DeliveryModeEnum::inShop())) {
|
||||
/** @var \App\Models\Timeslot|null */
|
||||
if (!($timeslot = $order->timeslot()->first())) {
|
||||
throw ValidationException::withMessages([
|
||||
'error' => trans('Créneau de réservation introuvable')
|
||||
]);
|
||||
}
|
||||
$order->shipping = [
|
||||
'firstname' => $timeslot->shop->name,
|
||||
'lastname' => '',
|
||||
'email' => null,
|
||||
'phone' => $timeslot->shop->phone,
|
||||
'line1' => $timeslot->shop->address,
|
||||
'postal_code' => $timeslot->shop->postal_code,
|
||||
'city' => $timeslot->shop->city,
|
||||
'country' => $timeslot->shop->country
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Fo;
|
||||
|
||||
use App\Enums\StaticPageType;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Product;
|
||||
use App\Models\Slider;
|
||||
use App\Models\StaticPage;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class StaticPageController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display static page type home
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*
|
||||
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
|
||||
*/
|
||||
public function home(Request $request)
|
||||
{
|
||||
// @phpcs:enable
|
||||
$content = StaticPage::getPageOfType(StaticPageType::home());
|
||||
// Star products.
|
||||
$products = Product::where('status', true)->where('star', true)->get();
|
||||
|
||||
$slider = Slider::where('slug', 'home')->first();
|
||||
$slides = $slider->showable_slides;
|
||||
|
||||
return view(
|
||||
'theme::pages.home',
|
||||
compact('content', 'products', 'slides')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a static page
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \App\Models\StaticPage $static_page_front
|
||||
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
|
||||
* @throws \RuntimeException If the static page type is not handled.
|
||||
*/
|
||||
public function displayStaticPage(Request $request, StaticPage $static_page_front)
|
||||
{
|
||||
$static_page = $static_page_front;
|
||||
switch ($static_page->type) {
|
||||
case StaticPageType::contact():
|
||||
return app(ContactController::class)->contact($request);
|
||||
case StaticPageType::home():
|
||||
return $this->callAction('home', [$request]);
|
||||
case StaticPageType::legals():
|
||||
case StaticPageType::sellconditions():
|
||||
case StaticPageType::confidentiality():
|
||||
case StaticPageType::faq():
|
||||
return view('theme::pages.static-page', compact('static_page'));
|
||||
case StaticPageType::crud():
|
||||
default:
|
||||
throw new \RuntimeException("Unhandled static page {$static_page->type->label}");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a crud static page
|
||||
*
|
||||
* @param \App\Models\StaticPage $static_page
|
||||
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
|
||||
* @throws \RuntimeException If the static page type is not handled.
|
||||
*/
|
||||
public function displayCrudStaticPage(StaticPage $static_page)
|
||||
{
|
||||
if (!$static_page->type->equals(StaticPageType::crud())) {
|
||||
throw new \RuntimeException("Unhandled static page {$static_page->type->label}");
|
||||
}
|
||||
return view('theme::pages.static-page', compact('static_page'));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Fo;
|
||||
|
||||
use App\Models\Shop;
|
||||
|
||||
class TimeSlotController
|
||||
{
|
||||
/**
|
||||
* Récupérer tout les créneaux disponible à partir de
|
||||
* maintenant pour un magasin sur les jours à venir.
|
||||
*
|
||||
* @param \App\Models\Shop $shop Le magasin concerné.
|
||||
* @param integer $days_to_come Sur quelle période proposer des créneaux à partir de maintenant.
|
||||
* @return array
|
||||
* @throws \RuntimeException Si la période demandé est incohérente.
|
||||
*/
|
||||
public function getAvailableCreneauxByShop(Shop $shop, int $days_to_come = 1)
|
||||
{
|
||||
return $shop->getAvailableCreneaux($days_to_come);
|
||||
}
|
||||
}
|
||||
76
app/Http/Controllers/HomeController.php
Normal file
76
app/Http/Controllers/HomeController.php
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Content;
|
||||
use App\Models\Product;
|
||||
use App\Models\Slider;
|
||||
use App\Models\Range;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use LDC\LDCCRM\Enums\ApiError;
|
||||
use LDC\LDCCRM\Exceptions\ApiErrorException;
|
||||
use LDC\LDCCRM\Exceptions\CrmException;
|
||||
use LDC\LDCCRM\Models\SingleOptin;
|
||||
|
||||
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)
|
||||
{
|
||||
// @phpcs:enable
|
||||
$content = Content::where('key', 'accueil')->first();
|
||||
// Star products.
|
||||
$products = Product::where('status', 1)->where('star', 1)->get();
|
||||
|
||||
$slider = Slider::where('slug', 'home')->first();
|
||||
$slides = $slider->showableSlides;
|
||||
|
||||
$quickorder_ranges = Range::with('products')->get();
|
||||
foreach ($quickorder_ranges as $range) {
|
||||
foreach ($range->products as $product) {
|
||||
$product->calculatedPrices = $product->getCalcPrices();
|
||||
}
|
||||
}
|
||||
|
||||
return view('home', compact('content', 'products', 'slides', 'quickorder_ranges'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the CRM to add a single optin
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*
|
||||
*/
|
||||
public function addOptIn(Request $request)
|
||||
{
|
||||
$validator = Validator::make($request->all(), ['email' => 'required|email']);
|
||||
if ($validator->fails()) {
|
||||
return __('L\'adresse email est incorrecte');
|
||||
}
|
||||
|
||||
try {
|
||||
SingleOptin::setStatus($request->email, true);
|
||||
return trans('Votre inscription à la newsletter a été prise en compte');
|
||||
} catch (ApiErrorException $e) {
|
||||
// * Il y a deja un customerInfo avec optin a true pour ce customer
|
||||
if ($e->getApiError()->equals(ApiError::singleOptinCustomerExists())) {
|
||||
return trans('Vous êtes déjà inscrit avec cette adresse email');
|
||||
}
|
||||
report($e);
|
||||
return trans('Une erreur est survenue, merci de réessayer ultérieurement');
|
||||
} catch (CrmException $e) {
|
||||
report($e);
|
||||
return trans('Une erreur est survenue, merci de réessayer ultérieurement');
|
||||
}
|
||||
return trans('Une erreur est survenue, merci de réessayer ultérieurement ');
|
||||
}
|
||||
}
|
||||
71
app/Http/Controllers/IndexController.php
Normal file
71
app/Http/Controllers/IndexController.php
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Content;
|
||||
use App\Models\Faq;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class IndexController extends Controller
|
||||
{
|
||||
/**
|
||||
* legal notice page
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*
|
||||
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
|
||||
*/
|
||||
public function legalNotice(Request $request)
|
||||
{
|
||||
// @phpcs:enable
|
||||
$content = Content::where('key', 'legals')->first();
|
||||
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)
|
||||
{
|
||||
// @phpcs:enable
|
||||
$content = Content::where('key', 'cgv')->first();
|
||||
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)
|
||||
{
|
||||
// @phpcs:enable
|
||||
$content = Content::where('key', 'confidentialite')->first();
|
||||
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)
|
||||
{
|
||||
// @phpcs:enable
|
||||
$content = Content::where('key', 'faq')->first();
|
||||
$faq = Faq::all();
|
||||
return view('faq', compact('faq', 'content'));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,14 +1,13 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Fo;
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Product;
|
||||
use App\Models\Range;
|
||||
use App\Models\Tag;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class ProductController extends Controller
|
||||
class ProductsController extends Controller
|
||||
{
|
||||
/**
|
||||
* Ranges page
|
||||
|
|
@ -22,7 +21,7 @@ class ProductController extends Controller
|
|||
{
|
||||
// @phpcs:enable
|
||||
// $ranges shared in AppServiceProvider.
|
||||
return view('theme::pages.ranges');
|
||||
return view('ranges');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -44,10 +43,10 @@ class ProductController extends Controller
|
|||
$products = Product::where('range_id', $range->id)->where('status', 1)->paginate(9);
|
||||
// Find promo within range.
|
||||
$offres = Product::where('range_id', $range->id)
|
||||
->where('status', 1)
|
||||
->has('discount')
|
||||
->with('discount')->get();
|
||||
return view('theme::pages.range', compact('range', 'products', 'offres'));
|
||||
->where('status', 1)
|
||||
->has('promotions')
|
||||
->with('promotions')->get();
|
||||
return view('range', compact('range', 'products', 'offres'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -66,8 +65,17 @@ class ProductController extends Controller
|
|||
if (!$product || !$product->status) {
|
||||
abort(404);
|
||||
}
|
||||
$product->additionnalProductInfo = $product->additionnalProductInfo($product->product_type);
|
||||
if ($product->additionnalProductInfo === null && !empty($product_type)) {
|
||||
// N'existe pas on renseigne un vide.
|
||||
$product_type = $product->product_type;
|
||||
$modelClass = 'App\Models\\' . ucfirst($product_type);
|
||||
$product->$product_type = new $modelClass();
|
||||
}
|
||||
|
||||
return view('theme::pages.product', ['productModel' => $product]);
|
||||
$associated = $product->products;
|
||||
|
||||
return view('product', compact('product', 'associated'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -93,7 +101,7 @@ class ProductController extends Controller
|
|||
|
||||
$search_title = 'Recherche : ' . $filter;
|
||||
|
||||
return view('theme::pages.search', compact('products', 'search_title', 'filter'));
|
||||
return view('search', compact('products', 'search_title', 'filter'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -118,6 +126,6 @@ class ProductController extends Controller
|
|||
$tag = Tag::where('slug', $tag_slug)->firstOrFail();
|
||||
$search_title = $tag->label;
|
||||
|
||||
return view('theme::pages.search', compact('products', 'search_title', 'tag'));
|
||||
return view('search', compact('products', 'search_title', 'tag'));
|
||||
}
|
||||
}
|
||||
30
app/Http/Controllers/QuickOrderController.php
Normal file
30
app/Http/Controllers/QuickOrderController.php
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Range;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
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)
|
||||
{
|
||||
// @phpcs:enable
|
||||
$quickorder_ranges = Range::with('products')->get();
|
||||
foreach ($quickorder_ranges as $range) {
|
||||
foreach ($range->products as $product) {
|
||||
$product->calculatedPrices = $product->getCalcPrices();
|
||||
}
|
||||
}
|
||||
|
||||
return view('quickorder', compact('quickorder_ranges'));
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Http;
|
||||
|
||||
use App\Http\Middleware\IsAdmin;
|
||||
use Illuminate\Foundation\Http\Kernel as HttpKernel;
|
||||
|
||||
class Kernel extends HttpKernel
|
||||
|
|
@ -29,14 +30,12 @@ class Kernel extends HttpKernel
|
|||
*/
|
||||
protected $middlewareGroups = [
|
||||
'web' => [
|
||||
'htmlsanitize',
|
||||
\App\Http\Middleware\EncryptCookies::class,
|
||||
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
|
||||
\Illuminate\Session\Middleware\StartSession::class,
|
||||
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
|
||||
\App\Http\Middleware\VerifyCsrfToken::class,
|
||||
\Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||
\App\Http\Middleware\SecureHeaders::class
|
||||
],
|
||||
|
||||
'api' => [
|
||||
|
|
@ -63,6 +62,6 @@ class Kernel extends HttpKernel
|
|||
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
|
||||
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
|
||||
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
|
||||
'htmlsanitize' => \App\Http\Middleware\HtmlSanitizer::class,
|
||||
'is-admin' => IsAdmin::class,
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
namespace App\Http\Middleware;
|
||||
|
||||
use Illuminate\Auth\Middleware\Authenticate as Middleware;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
|
||||
class Authenticate extends Middleware
|
||||
{
|
||||
|
|
@ -15,24 +14,8 @@ class Authenticate extends Middleware
|
|||
*/
|
||||
protected function redirectTo($request)
|
||||
{
|
||||
$logins = [
|
||||
'frontend' => route('login'),
|
||||
'backend' => route('bo.login')
|
||||
];
|
||||
if (!$request->expectsJson()) {
|
||||
// * Notify must login
|
||||
Session::flash('warning', trans('Veuillez vous connecter pour continuer'));
|
||||
|
||||
foreach ($request->route()->gatherMiddleware() as $middleware) {
|
||||
if (\is_string($middleware) and strpos($middleware, 'auth:') !== false) {
|
||||
$route = $logins[str_replace('auth:', '', $middleware)] ?? null;
|
||||
if ($route) {
|
||||
return $route;
|
||||
}
|
||||
}
|
||||
}
|
||||
return route('login');
|
||||
if (! $request->expectsJson()) {
|
||||
return route('auth.login');
|
||||
}
|
||||
abort(401);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,53 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use App\Lib\Helpers\ToolboxHelper;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class HtmlSanitizer
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @param mixed ...$params
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle(Request $request, \Closure $next, ...$params)
|
||||
{
|
||||
$inputs = $request->all();
|
||||
/** @var callable|null */
|
||||
$cleanInput = null;
|
||||
$cleanInput = function (&$input, $name, $rootName = null) use ($params, &$cleanInput) {
|
||||
// * Nested element array
|
||||
if (is_array($input)) {
|
||||
array_walk_recursive($input, $cleanInput, $name);
|
||||
}
|
||||
if (!is_string($input)) {
|
||||
return;
|
||||
}
|
||||
if (in_array($name, $params) or in_array($rootName ?? $name, $params)) {
|
||||
// ? Is a json input ?
|
||||
if ($isJson = \json_decode($input, true) and is_array($isJson)) {
|
||||
// ! Decode each json field recursive.
|
||||
\array_walk_recursive($isJson, function (&$item) {
|
||||
if (\is_string($item)) {
|
||||
$item = clean($item);
|
||||
$item = ToolboxHelper::stripCkEditorSchemesOnMediaInputs($item);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
$input = clean($input);
|
||||
$input = ToolboxHelper::stripCkEditorSchemesOnMediaInputs($input);
|
||||
}
|
||||
} else {
|
||||
$input = strip_tags($input);
|
||||
}
|
||||
};
|
||||
\array_walk($inputs, $cleanInput);
|
||||
$request->merge($inputs);
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
26
app/Http/Middleware/IsAdmin.php
Normal file
26
app/Http/Middleware/IsAdmin.php
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class IsAdmin
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
$role = Auth::user()->role;
|
||||
if ($role === 1 || $role === 2) {
|
||||
return $next($request);
|
||||
}
|
||||
abort(404, "Cette page n'existe pas.");
|
||||
}
|
||||
}
|
||||
|
|
@ -16,7 +16,6 @@ class RedirectIfAuthenticated
|
|||
* @param \Closure $next
|
||||
* @param string|null ...$guards
|
||||
* @return mixed
|
||||
* @throws \RuntimeException If guard is unhandled.
|
||||
*/
|
||||
public function handle(Request $request, Closure $next, ...$guards)
|
||||
{
|
||||
|
|
@ -24,14 +23,7 @@ class RedirectIfAuthenticated
|
|||
|
||||
foreach ($guards as $guard) {
|
||||
if (Auth::guard($guard)->check()) {
|
||||
switch ($guard) {
|
||||
case 'frontend':
|
||||
return \redirect()->route('home');
|
||||
case 'backend':
|
||||
return \redirect()->route('bo.dashboard');
|
||||
default:
|
||||
throw new \RuntimeException("Unhandled guard `{$guard}` .");
|
||||
}
|
||||
return redirect(RouteServiceProvider::HOME);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use App\Models\OldSlugable;
|
||||
use App\Models\OldSlug;
|
||||
use App\Models\Product;
|
||||
use App\Models\Range;
|
||||
use Closure;
|
||||
|
|
@ -25,10 +25,10 @@ class RedirectOldSlugs
|
|||
if ($productSlug !== null) {
|
||||
$product = Product::where('slug', $productSlug)->first();
|
||||
if (!$product) {
|
||||
$productOldSlug = OldSlugable::where('slug', $productSlug)->first();
|
||||
$productOldSlug = OldSlug::where('slug', $productSlug)->first();
|
||||
if ($productOldSlug) {
|
||||
$product = Product::where('id', $productOldSlug->product_id)->first();
|
||||
return redirect()->route('products.show', $product->slug);
|
||||
return redirect()->route('product', $product->slug);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -36,10 +36,10 @@ class RedirectOldSlugs
|
|||
if ($rangeSlug !== null) {
|
||||
$range = Range::where('slug', $rangeSlug)->first();
|
||||
if (!$range) {
|
||||
$rangeOldSlug = OldSlugable::where('slug', $rangeSlug)->first();
|
||||
$rangeOldSlug = OldSlug::where('slug', $rangeSlug)->first();
|
||||
if ($rangeOldSlug) {
|
||||
$range = Range::where('id', $rangeOldSlug->range_id)->first();
|
||||
return redirect()->route('ranges.show', $range->slug);
|
||||
return redirect()->route('range', $range->slug);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,82 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Illuminate\Support\Facades\View;
|
||||
|
||||
class SecureHeaders
|
||||
{
|
||||
/**
|
||||
* Enumerate headers which you do not want in your application's responses.
|
||||
* Great starting point would be to go check out @Scott_Helme's:
|
||||
* https://securityheaders.com/
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $unwantedHeaderList = [
|
||||
'X-Powered-By',
|
||||
'Server',
|
||||
];
|
||||
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
View::share('nonce', $nonce = \uniqid());
|
||||
// * For VueJS dev tool to execute
|
||||
$jsDev = config('app.debug') ? "'unsafe-eval' 'unsafe-inline'" : "'nonce-$nonce'";
|
||||
$scheme = config('app.env') === 'local' ? 'http' : 'https';
|
||||
$reportUri = Route::has('cspReportUri') ?
|
||||
\sprintf(' report-uri %s ;', \parse_url(route('cspReportUri'), \PHP_URL_PATH)) : '';
|
||||
$this->removeUnwantedHeaders($this->unwantedHeaderList);
|
||||
$response = $next($request);
|
||||
$response->headers->set('Referrer-Policy', 'no-referrer-when-downgrade');
|
||||
$response->headers->set('X-Content-Type-Options', 'nosniff');
|
||||
$response->headers->set('X-XSS-Protection', '1; mode=block');
|
||||
$response->headers->set('X-Frame-Options', 'SAMEORIGIN');
|
||||
$response->headers->set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains;');
|
||||
$cspPolicies = [
|
||||
// * Unsafe inline ck-editor requires unsafe-inline
|
||||
"style-src 'self' 'unsafe-inline' " . \implode(' ', [
|
||||
'https://cdnjs.cloudflare.com',
|
||||
// * File Manager
|
||||
'https://fonts.googleapis.com',
|
||||
'https://cdn.jsdelivr.net',
|
||||
'https://use.fontawesome.com',
|
||||
'https://fonts.googleapis.com'
|
||||
]) . ';',
|
||||
"script-src 'self' $jsDev " . \implode(' ', [
|
||||
'https://www.googletagmanager.com',
|
||||
'https://cdnjs.cloudflare.com',
|
||||
"$scheme://www.google-analytics.com",
|
||||
]) . ';'
|
||||
];
|
||||
$response->headers->set(
|
||||
'Content-Security-Policy',
|
||||
implode(' ', $cspPolicies) . $reportUri
|
||||
);
|
||||
$response->headers->set('Feature-Policy', 'fullscreen \'self\';');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove unwanted headers
|
||||
*
|
||||
* @param array $headerList
|
||||
* @return void
|
||||
*/
|
||||
private function removeUnwantedHeaders(array $headerList)
|
||||
{
|
||||
foreach ($headerList as $header) {
|
||||
header_remove($header);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -19,8 +19,5 @@ class TrustProxies extends Middleware
|
|||
*
|
||||
* @var integer
|
||||
*/
|
||||
protected $headers = Request::HEADER_X_FORWARDED_FOR |
|
||||
Request::HEADER_X_FORWARDED_HOST |
|
||||
Request::HEADER_X_FORWARDED_PORT |
|
||||
Request::HEADER_X_FORWARDED_PROTO;
|
||||
protected $headers = Request::HEADER_X_FORWARDED_ALL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,5 +11,6 @@ class VerifyCsrfToken extends Middleware
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $except = [];
|
||||
protected $except = [
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,32 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Bo\Ajax\TimeslotExceptions;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class SaveTimeslotExceptionsRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return \auth('backend')->check();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'dates' => 'present|array',
|
||||
'dates.*' => 'sometimes|array',
|
||||
'dates.*.date' => 'required|date_format:Y-m-d|distinct'
|
||||
];
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue