Merge branch 'trunk'

This commit is contained in:
Noah Lancien 2024-10-24 10:44:53 +00:00
commit 48ae62caa6
125 changed files with 8645 additions and 861 deletions

View file

@ -1,2 +1,16 @@
.git
*.md
node_modules/
npm-debug.log
.npmrc
tests/
Dockerfile*
.dockerignore
.git
.gitignore
README.md
LICENSE
.vscode
vendor/
public/build/
auth.json

View file

@ -81,3 +81,6 @@ GOOGLE_RECAPTCHA_VERSION=
MERCANET_SECRET=
MERCANET_MERCHAND_ID=
MERCANET_ENV=
## TELESCOPE
TELESCOPE_ENABLED=

2
.gitignore vendored
View file

@ -1,5 +1,6 @@
.env
.env.backup
.env.testing
.env.production
.phpunit.result.cache
.stylelintcache
@ -23,6 +24,7 @@ Homestead.yaml
npm-debug.log
yarn-error.log
.npmrc
/tests/coverage
# Ignore public favicon
/public/android-chrome-192x192.png

View file

@ -1,5 +1,43 @@
FROM composer:2.8 AS vendor
ARG GITLAB_USER
ARG GITLAB_PASSWORD
COPY database/ database/
COPY composer.json composer.json
COPY composer.lock composer.lock
RUN composer config gitlab-token.lab.s-web.fr ${GITLAB_USER} ${GITLAB_PASSWORD}
RUN composer install \
--ignore-platform-reqs \
--no-interaction \
--no-plugins \
--no-scripts \
--no-dev \
--prefer-dist
FROM node:20.18 AS frontend
ARG GITLAB_PASSWORD
RUN mkdir -p /app/public/build
COPY package*.json tsconfig.json vite.config.ts .eslintrc.json .stylelintrc.json /app/
COPY resources/ /app/resources/
WORKDIR /app
RUN npm config set @ldc-web:registry https://lab.s-web.fr/api/v4/packages/npm/
RUN npm config set -- '//lab.s-web.fr/api/v4/packages/npm/:_authToken' "${GITLAB_PASSWORD}"
RUN npm ci && npm run prod
FROM registry.s-web.fr/ldc-web/projets/ldc-web-images-docker/ldcweb-production-8.3:latest
COPY --chown=www-data:www-data . /app/srcs
ARG USER=www-data
COPY --chown=${USER}:${USER} . /app/srcs
COPY --from=vendor --chown=${USER}:${USER} /app/vendor/ /app/srcs/vendor/
COPY --from=frontend --chown=${USER}:${USER} /app/public/build/ /app/srcs/public/build/
USER root
RUN chmod -R 755 /app/srcs/storage
USER www-data
USER ${USER}

View file

@ -14,6 +14,60 @@ apt install trimage
# Copy paste from the admin secure readme.md
Put every min in PROD :
```php
php artisan schedule:run
```
# Unit tests
Create new `.env.testing` with a new empty database `le-gaulois-testing` and just run this command :
```php
php artisan test
```
To see more details, please read the documentation of [uwil/unit-tests-laravel](https://lab.s-web.fr/ldc-web/projets/unit-tests-laravel/-/blob/main/README.md?ref_type=heads#documentation)
Legend : ✅ test added & operational, ⚠️ test added & operational but modified, ❌ no test (because no CRUD or specific model)
Models list :
✅ ActivityLog
⚠️ Approach (label/demarche)
❌ BlockList
✅ BrandAdvantage
❌ Breeder
✅ Claim
✅ ConsumptionMoment
❌ Customer
❌ DeliveryAddress
✅ DemarcheSlide
❌ DepartaimantsCollection
✅ Discount
❌ GeneralSetting
✅ HistoricalMilestone
❌ IncoNutritionalValue
✅ KeyNumber
✅ MainSlide
✅ Meat
⚠️ MenuNodeData
❌ Message
⚠️ News
✅ NewsBreeding
✅ NewsCategory
⚠️ NewsClub (News/Survey)
✅ NewsCorporate
❌ Notification
✅ Offer
❌ Order
❌ OrderSellItem
✅ Product
✅ ProductType
✅ Profession
✅ Range
✅ Recipe
✅ SellItem
✅ StaticPage
✅ Submeat
✅ Subrange
✅ SurveysAnswer
✅ Testimonial
❌ User
✅ Video

View file

@ -16,8 +16,8 @@ enum GeoType: int
*
* @phpstan-ignore-next-line
*/
private const ROUTENAMES = [
self::exact->name => trans('Exacte'),
self::commune->name => trans('Code commune'),
private const LABELS = [
self::exact->name => 'Exacte',
self::commune->name => 'Code commune',
];
}

View file

@ -4,7 +4,7 @@ namespace App\Enums\Breeders;
use App\Traits\Enums\BaseEnum;
enum EleveurOcbStatus: int
enum OCBStatus: int
{
use BaseEnum;
@ -19,9 +19,9 @@ enum EleveurOcbStatus: int
* @phpstan-ignore-next-line
*/
private const LABELS = [
self::none->name => trans('Non'),
self::pending->name => trans('En attente'),
self::no->name => trans('Réfusé'),
self::yes->name => trans('Valide'),
self::none->name => 'Non',
self::pending->name => 'En attente',
self::no->name => 'Réfusé',
self::yes->name => 'Valide',
];
}

View file

@ -18,8 +18,8 @@ enum OCBType: int
* @phpstan-ignore-next-line
*/
private const LABELS = [
self::rabbit->name => trans('Lapin'),
self::chicken->name => trans('Poulet'),
self::turkey->name => trans('Dinde'),
self::rabbit->name => 'Lapin',
self::chicken->name => 'Poulet',
self::turkey->name => 'Dinde',
];
}

View file

@ -17,7 +17,7 @@ enum PresentationType: int
* @phpstan-ignore-next-line
*/
private const LABELS = [
self::picture->name => trans('Photo'),
self::video->name => trans('Video'),
self::picture->name => 'Photo',
self::video->name => 'Video',
];
}

View file

@ -1,23 +0,0 @@
<?php
namespace App\Enums;
use App\Traits\Enums\BaseEnum;
enum HistoricalMilestonePosition: string
{
use BaseEnum;
case hg = "hg";
case hd = "hd";
/**
* Optionnal labels definition.
*
* @phpstan-ignore-next-line
*/
private const LABELS = [
self::hg->name => 'Haut gauche',
self::hd->name => "Haut droit",
];
}

View file

@ -0,0 +1,23 @@
<?php
namespace App\Enums\HistoricalMilestones;
use App\Traits\Enums\BaseEnum;
enum HistoricalMilestonePosition: int
{
use BaseEnum;
case topLeft = 1;
case topRight = 2;
/**
* Optionnal labels definition.
*
* @phpstan-ignore-next-line
*/
private const LABELS = [
self::topLeft->name => 'Haut gauche',
self::topRight->name => "Haut droit",
];
}

View file

@ -57,6 +57,17 @@ class DiscountController extends Controller
return view('bo.pages.discounts.index', compact('discountModels', 'search', 'searchFields'));
}
/**
* Show the specified resource.
*
* @param \App\Models\Discount $discount
* @return \Illuminate\Contracts\View\View
*/
public function show(Discount $discount): \Illuminate\Contracts\View\View
{
return view('bo.pages.discounts.show', ['discountModel' => $discount]);
}
/**
* Show the specified resource.
*

View file

@ -315,7 +315,7 @@ class Controller extends BaseController
string|null $search = null
): \Illuminate\Pagination\LengthAwarePaginator {
$modelsTitles = [];
$searchLower = Str::lower($search);
$searchLower = Str::lower($search);
$query->when(!is_null($search), function (Builder $q) use ($searchLower, $searchField) {
$q->where($searchField, 'like', "%{$searchLower}%");
})

View file

@ -60,8 +60,8 @@ class StoreDemarcheSlideRequest extends FormRequest
'button_2_url' => 'required_if_accepted:button_2_status|string|nullable|url:http,https',
'button_2_target' => 'required_if_accepted:button_2_status|boolean',
'published' => 'required|boolean',
'publish_at' => 'nullable|date',
'unpublish_at' => 'nullable|date|after:publish_at',
'published_at' => 'nullable|date',
'unpublished_at' => 'nullable|date|after:publish_at',
];
return \array_merge(
$rules,
@ -91,8 +91,8 @@ class StoreDemarcheSlideRequest extends FormRequest
'button_2_status' => trans('validation.custom.button_status') . ' n°2',
'button_2_target' => trans('validation.custom.button_target') . ' n°2',
'published' => trans('validation.attributes.published'),
'publish_at' => trans('validation.custom.publish_at'),
'unpublish_at' => trans('validation.custom.unpublish_at'),
'published_at' => trans('validation.custom.publish_at'),
'unpublished_at' => trans('validation.custom.unpublish_at'),
];
}
}

View file

@ -2,7 +2,7 @@
namespace App\Http\Requests\Bo\HistoricalMilestones;
use App\Enums\HistoricalMilestonePosition;
use App\Enums\HistoricalMilestones\HistoricalMilestonePosition;
use App\Models\HistoricalMilestone;
use App\Rules\WysiwygLength;
use App\Traits\Requests\HasPicture;
@ -48,12 +48,12 @@ class StoreHistoricalMilestoneRequest extends FormRequest
public function rules(): array
{
$rules = [
'year' => 'required|integer|min:1901|max:2155',
'title' => 'required|string|between:3,255',
'description' => ['required', 'string', new WysiwygLength()],
'picture_alt' => 'required_with:picture|nullable|between:3,255',
'picture_title' => 'required_with:picture|nullable|between:3,255',
'video_id' => [
'year' => 'required|integer|min:1901|max:2155',
'title' => 'required|string|between:3,255',
'description' => ['required', 'string', new WysiwygLength()],
'picture_alt' => 'required_with:picture|nullable|between:3,255',
'picture_title' => 'required_with:picture|nullable|between:3,255',
'video_id' => [
'sometimes',
'nullable',
'string',
@ -67,10 +67,10 @@ class StoreHistoricalMilestoneRequest extends FormRequest
}
}
],
'picto_alt' => 'required_with:picto|nullable|between:3,255',
'picto_title' => 'required_with:picto|nullable|between:3,255',
'published' => 'required|boolean',
'picto_placement' => ['required_with:picto', 'nullable', Rule::enum(HistoricalMilestonePosition::class)]
'picto_alt' => 'required_with:picto|nullable|between:3,255',
'picto_title' => 'required_with:picto|nullable|between:3,255',
'picto_position' => ['required_with:picto', 'nullable', Rule::enum(HistoricalMilestonePosition::class)],
'published' => 'required|boolean',
];
return \array_merge(
$rules,
@ -87,17 +87,18 @@ class StoreHistoricalMilestoneRequest extends FormRequest
public function attributes(): array
{
return [
'year' => trans('validation.attributes.year'),
'title' => trans('validation.attributes.title'),
'description' => trans('validation.attributes.description'),
'picture' => trans('validation.attributes.image'),
'picture_alt' => trans('validation.custom.attribute_alt'),
'picture_title' => trans('validation.custom.attribute_title'),
'video_id' => trans('validation.custom.video_id'),
'picto' => trans('validation.custom.picto'),
'picto_alt' => trans('validation.custom.attribute_alt'),
'picto_title' => trans('validation.custom.attribute_title'),
'published' => trans('validation.attributes.published')
'year' => trans('validation.attributes.year'),
'title' => trans('validation.attributes.title'),
'description' => trans('validation.attributes.description'),
'picture' => trans('validation.attributes.image'),
'picture_alt' => trans('validation.custom.attribute_alt'),
'picture_title' => trans('validation.custom.attribute_title'),
'video_id' => trans('validation.custom.video_id'),
'picto' => trans('validation.custom.picto'),
'picto_alt' => trans('validation.custom.attribute_alt'),
'picto_title' => trans('validation.custom.attribute_title'),
'picto_position' => trans('validation.custom.picto_position'),
'published' => trans('validation.attributes.published')
];
}
}

View file

@ -34,8 +34,8 @@ class StoreMainSlideRequest extends FormRequest
'button_1_target' => $this->boolean('button_1_target'),
'button_2_status' => $this->boolean('button_2_status'),
'button_2_target' => $this->boolean('button_2_target'),
'published' => $this->boolean('published'),
'new' => $this->boolean('new'),
'published' => $this->boolean('published'),
]);
$this->mergePicture('picture');
$this->mergePicture('background');
@ -69,10 +69,10 @@ class StoreMainSlideRequest extends FormRequest
'button_1_color_background' => ['required_if_accepted:button_1_status', new Hex()],
'button_2_color_text' => ['required_if_accepted:button_2_status', new Hex()],
'button_2_color_background' => ['required_if_accepted:button_2_status', new Hex()],
'published' => 'required|boolean',
'new' => 'required|boolean',
'publish_at' => 'nullable|date',
'unpublish_at' => 'nullable|date|after:publish_at',
'published' => 'required|boolean',
'published_at' => 'nullable|date',
'unpublished_at' => 'nullable|date|after:published_at',
];
return \array_merge(
$rules,
@ -112,8 +112,8 @@ class StoreMainSlideRequest extends FormRequest
'button_2_color_background' => trans('validation.custom.button_color_background') . ' n°2',
'new' => trans('validation.custom.new'),
'published' => trans('validation.custom.published'),
'publish_at' => trans('validation.custom.publish_at'),
'unpublish_at' => trans('validation.custom.unpublish_at'),
'published_at' => trans('validation.custom.published_at'),
'unpublished_at' => trans('validation.custom.unpublished_at'),
];
}
}

View file

@ -8,7 +8,7 @@ use Illuminate\Support\Facades\Log;
/**
* Update published attribute reading its
* publish_at and unpublish_at attributes.
* published_at and unpublished_at attributes.
*/
class DemarcheSlidesStatusUpdate
{
@ -21,20 +21,20 @@ class DemarcheSlidesStatusUpdate
{
/** @var \Illuminate\Database\Eloquent\Collection<array-key,\App\Models\DemarcheSlide> */
$demarcheSlidesListToUnPublish = DemarcheSlide::query()
->where('unpublish_at', '<=', Carbon::now())
->whereNotNull('unpublish_at')
->where('unpublished_at', '<=', Carbon::now())
->whereNotNull('unpublished_at')
->where('published', true)->get();
Log::debug(__CLASS__ . " demarcheSlides to unpublish " . $demarcheSlidesListToUnPublish->count());
foreach ($demarcheSlidesListToUnPublish as $demarcheSlide) {
$demarcheSlide->publish_at = null;
$demarcheSlide->unpublish_at = null;
$demarcheSlide->published_at = null;
$demarcheSlide->unpublished_at = null;
$demarcheSlide->published = false;
$demarcheSlide->saveOrFail();
}
/** @var \Illuminate\Database\Eloquent\Collection<array-key,\App\Models\DemarcheSlide> */
$demarcheSlidesListToPublish = DemarcheSlide::query()
->where('publish_at', '<=', Carbon::now())
->whereNotNull('publish_at')
->where('published_at', '<=', Carbon::now())
->whereNotNull('published_at')
->where('published', false)->get();
Log::debug(__CLASS__ . " demarcheSlides to publish " . $demarcheSlidesListToPublish->count());
// Unpublish all demarcheSlide with no date because only 1 demarcheSlide can be published.
@ -46,7 +46,7 @@ class DemarcheSlidesStatusUpdate
});
}
foreach ($demarcheSlidesListToPublish as $demarcheSlide) {
$demarcheSlide->publish_at = null;
$demarcheSlide->published_at = null;
$demarcheSlide->published = true;
$demarcheSlide->saveOrFail();
}

View file

@ -8,7 +8,7 @@ use Illuminate\Support\Facades\Log;
/**
* Update published attribute reading its
* publish_at and unpublish_at attributes.
* published_at and unpublished_at attributes.
*/
class MainSlidesStatusUpdate
{
@ -20,33 +20,33 @@ class MainSlidesStatusUpdate
public function handle(): void
{
/** @var \Illuminate\Database\Eloquent\Collection<array-key,\App\Models\MainSlide> */
$mainSlidesListToUnPublish = MainSlide::query()
->where('unpublish_at', '<=', Carbon::now())
$mainSlidesListToUnPublished = MainSlide::query()
->where('unpublished_at', '<=', Carbon::now())
->whereNotNull('unpublish_at')
->where('published', true)->get();
Log::debug(__CLASS__ . " mainSlides to unpublish " . $mainSlidesListToUnPublish->count());
foreach ($mainSlidesListToUnPublish as $mainSlide) {
$mainSlide->publish_at = null;
$mainSlide->unpublish_at = null;
Log::debug(__CLASS__ . " mainSlides to unpublished " . $mainSlidesListToUnPublished->count());
foreach ($mainSlidesListToUnPublished as $mainSlide) {
$mainSlide->published_at = null;
$mainSlide->unpublished_at = null;
$mainSlide->published = false;
$mainSlide->saveOrFail();
}
/** @var \Illuminate\Database\Eloquent\Collection<array-key,\App\Models\MainSlide> */
$mainSlidesListToPublish = MainSlide::query()
$mainSlidesListToPublished = MainSlide::query()
->where('publish_at', '<=', Carbon::now())
->whereNotNull('publish_at')
->where('published', false)->get();
Log::debug(__CLASS__ . " mainSlides to publish " . $mainSlidesListToPublish->count());
Log::debug(__CLASS__ . " mainSlides to publish " . $mainSlidesListToPublished->count());
// Unpublish all mainSlide with no date because only 1 mainSlide can be published.
if ($mainSlidesListToPublish->count()) {
if ($mainSlidesListToPublished->count()) {
MainSlide::query()->where('published', true)
->each(function (MainSlide $mainSlide) {
$mainSlide->published = false;
$mainSlide->saveOrFail();
});
}
foreach ($mainSlidesListToPublish as $mainSlide) {
$mainSlide->publish_at = null;
foreach ($mainSlidesListToPublished as $mainSlide) {
$mainSlide->published_at = null;
$mainSlide->published = true;
$mainSlide->saveOrFail();
}

View file

@ -2,7 +2,7 @@
namespace App\Models;
use App\Enums\Breeders\EleveurOcbStatus;
use App\Enums\Breeders\OCBStatus;
use App\Enums\Breeders\GeoType;
use App\Enums\Breeders\OCBType;
use App\Enums\Breeders\PresentationType;
@ -80,7 +80,7 @@ class Breeder extends Model
'published' => 'boolean',
'display_random' => 'boolean',
'presentation_type' => PresentationType::class,
'ocbStatus' => EleveurOcbStatus::class,
'ocbStatus' => OCBStatus::class,
'ocbType' => OCBType::class,
'geo_type' => GeoType::class
];

View file

@ -334,7 +334,9 @@ class Customer extends Authenticatable implements MustVerifyEmail
if (!$crmCustomer) {
throw new CrmException('CRM get Customer returned null');
}
$data['postcode'] = Arr::get($data, 'postal_code');
if (isset($data["postal_code"])) {
$data['postcode'] = Arr::get($data, 'postal_code');
}
unset(
$data["username"],
$data["question_id"],

View file

@ -24,10 +24,10 @@ use Illuminate\Support\Facades\Cache;
* @property boolean $button_2_status Slide button n°2 publish status.
* @property boolean $button_2_target Slide button n°2 target.
* @property boolean $published Slide publish status.
* @property-read \Illuminate\Support\Carbon $published_at Slide published_at.
* @property-read \Illuminate\Support\Carbon $unpublished_at Slide unpublished_at.
* @property-read \Illuminate\Support\Carbon $created_at Created date.
* @property-read \Illuminate\Support\Carbon $updated_at Updated date.
* @property-read \Illuminate\Support\Carbon $published_at Slide published at.
* @property-read \Illuminate\Support\Carbon $unpublished_at Slide unpublished at.
* @property-read \Carbon\Carbon $created_at Created date.
* @property-read \Carbon\Carbon $updated_at Updated date.
*/
class DemarcheSlide extends Model
{
@ -55,8 +55,8 @@ class DemarcheSlide extends Model
'button_2_target',
'order',
'published',
'publish_at',
'unpublish_at',
'published_at',
'unpublished_at',
];
/**
@ -69,8 +69,8 @@ class DemarcheSlide extends Model
'button_1_target' => 'boolean',
'button_2_status' => 'boolean',
'button_2_target' => 'boolean',
'publish_at' => 'datetime',
'unpublish_at' => 'datetime',
'published_at' => 'datetime',
'unpublished_at' => 'datetime',
];
/**
@ -135,11 +135,11 @@ class DemarcheSlide extends Model
private static function makeStatusSense(self $demarcheSlide): void
{
/** @var \Carbon\Carbon|null */
$publish_at = $demarcheSlide->publish_at;
$published_at = $demarcheSlide->published_at;
/** @var \Carbon\Carbon|null */
$unpublish_at = $demarcheSlide->unpublish_at;
$unpublished_at = $demarcheSlide->unpublished_at;
$wantedStatus = $demarcheSlide->published;
if ($publish_at or $unpublish_at) {
if ($published_at or $unpublished_at) {
$demarcheSlide->published = $demarcheSlide->planificated_status;
}
if ($wantedStatus !== $demarcheSlide->published) {
@ -158,17 +158,17 @@ class DemarcheSlide extends Model
public function getPlanificatedStatusAttribute(): bool
{
/** @var \Carbon\Carbon|null */
$publish_at = $this->publish_at;
$published_at = $this->published_at;
/** @var \Carbon\Carbon|null */
$unpublish_at = $this->unpublish_at;
if ($publish_at and $unpublish_at) {
return $unpublish_at->greaterThanOrEqualTo(now()) and $publish_at->lessThan(now());
$unpublished_at = $this->unpublished_at;
if ($published_at and $unpublished_at) {
return $unpublished_at->greaterThanOrEqualTo(now()) and $published_at->lessThan(now());
}
if ($publish_at) {
return $publish_at->lessThan(now());
if ($published_at) {
return $published_at->lessThan(now());
}
if ($unpublish_at) {
return $unpublish_at->greaterThanOrEqualTo(now());
if ($unpublished_at) {
return $unpublished_at->greaterThanOrEqualTo(now());
}
return false;
}

View file

@ -2,6 +2,7 @@
namespace App\Models;
use App\Enums\HistoricalMilestones\HistoricalMilestonePosition;
use App\Lib\Helpers\FileStorageHelper;
use App\Traits\Models\ActivityLog;
use Illuminate\Database\Eloquent\Factories\HasFactory;
@ -9,19 +10,20 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Cache;
/**
* @property \Carbon\Carbon $year Historical milestone year.
* @property string $title Historical milestone title.
* @property string $description Historical milestone description.
* @property string|null $picture Historical milestone picture.
* @property string|null $picture_alt Picture alt attribute.
* @property string|null $picture_title Picture title attribute.
* @property string|null $video_id Historical milestone video ID.
* @property string|null $picto Historical milestone picto.
* @property string|null $picto_alt picto alt attribute.
* @property string|null $picto_title picto title attribute.
* @property boolean $published Historical milestone publish status.
* @property-read \Illuminate\Support\Carbon $created_at Created date.
* @property-read \Illuminate\Support\Carbon $updated_at Updated date.
* @property \Carbon\Carbon $year Historical milestone year.
* @property string $title Historical milestone title.
* @property string $description Historical milestone description.
* @property string|null $picture Historical milestone picture.
* @property string|null $picture_alt Picture alt attribute.
* @property string|null $picture_title Picture title attribute.
* @property string|null $video_id Historical milestone video ID.
* @property string|null $picto Historical milestone picto.
* @property string|null $picto_alt Picto alt attribute.
* @property string|null $picto_title Picto title attribute.
* @property \App\Enums\HistoricalMilestones\HistoricalMilestonePosition $picto_position Historical milestone picto position.
* @property boolean $published Historical milestone publish status.
* @property-read \Illuminate\Support\Carbon $created_at Created date.
* @property-read \Illuminate\Support\Carbon $updated_at Updated date.
*/
class HistoricalMilestone extends Model
{
@ -44,7 +46,7 @@ class HistoricalMilestone extends Model
'picto',
'picto_alt',
'picto_title',
'picto_placement',
'picto_position',
'order',
'published',
];
@ -55,8 +57,9 @@ class HistoricalMilestone extends Model
* @var array<string, string>
*/
protected $casts = [
'year' => 'integer',
'published' => 'boolean',
'year' => 'integer',
'picto_position' => HistoricalMilestonePosition::class,
'published' => 'boolean',
];
/**

View file

@ -76,8 +76,8 @@ class MainSlide extends Model
'order',
'new',
'published',
'publish_at',
'unpublish_at',
'published_at',
'unpublished_at',
];
/**
@ -95,8 +95,8 @@ class MainSlide extends Model
'button_1_color_background' => HtmlColor::class,
'button_2_color_text' => HtmlColor::class,
'button_2_color_background' => HtmlColor::class,
'publish_at' => 'datetime',
'unpublish_at' => 'datetime',
'published_at' => 'datetime',
'unpublished_at' => 'datetime',
];
/**
@ -177,7 +177,7 @@ class MainSlide extends Model
}
/**
* Adjusts mainSlide status using current status and publish dates.
* Adjusts mainSlide status using current status and published dates.
*
* @param self $mainSlide
* @return void
@ -185,11 +185,11 @@ class MainSlide extends Model
private static function makeStatusSense(self $mainSlide): void
{
/** @var \Carbon\Carbon|null */
$publish_at = $mainSlide->publish_at;
$published_at = $mainSlide->published_at;
/** @var \Carbon\Carbon|null */
$unpublish_at = $mainSlide->unpublish_at;
$unpublished_at = $mainSlide->unpublished_at;
$wantedStatus = $mainSlide->published;
if ($publish_at or $unpublish_at) {
if ($published_at or $unpublished_at) {
$mainSlide->published = $mainSlide->planificated_status;
}
if ($wantedStatus !== $mainSlide->published) {
@ -208,17 +208,17 @@ class MainSlide extends Model
public function getPlanificatedStatusAttribute(): bool
{
/** @var \Carbon\Carbon|null */
$publish_at = $this->publish_at;
$published_at = $this->published_at;
/** @var \Carbon\Carbon|null */
$unpublish_at = $this->unpublish_at;
if ($publish_at and $unpublish_at) {
return $unpublish_at->greaterThanOrEqualTo(now()) and $publish_at->lessThan(now());
$unpublished_at = $this->unpublished_at;
if ($published_at and $unpublished_at) {
return $unpublished_at->greaterThanOrEqualTo(now()) and $published_at->lessThan(now());
}
if ($publish_at) {
return $publish_at->lessThan(now());
if ($published_at) {
return $published_at->lessThan(now());
}
if ($unpublish_at) {
return $unpublish_at->greaterThanOrEqualTo(now());
if ($unpublished_at) {
return $unpublished_at->greaterThanOrEqualTo(now());
}
return false;
}

View file

@ -12,6 +12,10 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Str;
use Spatie\Sitemap\Contracts\Sitemapable;
use Spatie\Sitemap\Tags\Url;
use Uwil\SitemapGenerator\Lib\SitemapHelper;
/**
* @property string $seo_title The seo title of the news.
@ -34,7 +38,7 @@ use Illuminate\Support\Str;
* @property-read \Illuminate\Support\Carbon $created_at Created date.
* @property-read \Illuminate\Support\Carbon $updated_at Updated date.
*/
class News extends Model
class News extends Model implements Sitemapable
{
use ActivityLog;
use HasFactory;
@ -298,6 +302,19 @@ class News extends Model
});
}
/**
* toSitemapTag method
*
* @return Url|string|array
*/
public function toSitemapTag(): Url | string | array
{
$model = $this;
$route = 'fo.news.show';
$params = ['slug' => $model->slug];
return SitemapHelper::generateUrl($route, $params, $model);
}
// * RELATIONS
/**

View file

@ -13,6 +13,10 @@ use Illuminate\Support\Facades\Cache;
use Uwil\Seo\Laravel\Interfaces\SeoInterface;
use Uwil\Seo\Laravel\Traits\SeoTrait;
use Uwil\Seo\Laravel\Objects\SeoItem;
use Spatie\Sitemap\Contracts\Sitemapable;
use Spatie\Sitemap\Tags\Url;
use Uwil\SitemapGenerator\Lib\SitemapHelper;
/**
* @property string $seo_title Product seo title.
@ -43,7 +47,7 @@ use Uwil\Seo\Laravel\Objects\SeoItem;
* @property-read \Carbon\Carbon $created_at Created date.
* @property-read \Carbon\Carbon $updated_at Updated date.
*/
class Product extends Model implements SeoInterface
class Product extends Model implements SeoInterface, Sitemapable
{
use ActivityLog;
use HasFactory;
@ -225,6 +229,19 @@ class Product extends Model implements SeoInterface
});
}
/**
* toSitemapTag method
*
* @return Url|string|array
*/
public function toSitemapTag(): Url | string | array
{
$model = $this;
$route = 'fo.products.show';
$params = ['slug' => $model->slug];
return SitemapHelper::generateUrl($route, $params, $model);
}
// * RELATIONSHIPS
/**

View file

@ -13,6 +13,9 @@ use Illuminate\Support\Str;
use Uwil\Seo\Laravel\Interfaces\SeoInterface;
use Uwil\Seo\Laravel\Traits\SeoTrait;
use Uwil\Seo\Laravel\Objects\SeoItem;
use Spatie\Sitemap\Contracts\Sitemapable;
use Spatie\Sitemap\Tags\Url;
use Uwil\SitemapGenerator\Lib\SitemapHelper;
/**
* @property string $slug Recipe slug.
@ -36,7 +39,7 @@ use Uwil\Seo\Laravel\Objects\SeoItem;
* @property-read \Illuminate\Support\Carbon $created_at Created date.
* @property-read \Illuminate\Support\Carbon $updated_at Updated date.
*/
class Recipe extends Model implements SeoInterface
class Recipe extends Model implements SeoInterface, Sitemapable
{
use ActivityLog;
use HasFactory;
@ -233,6 +236,19 @@ class Recipe extends Model implements SeoInterface
});
}
/**
* toSitemapTag method
*
* @return Url|string|array
*/
public function toSitemapTag(): Url | string | array
{
$model = $this;
$route = 'fo.recipes.show';
$params = ['slug' => $model->slug];
return SitemapHelper::generateUrl($route, $params, $model);
}
// * RELATIONSHIPS
/**

View file

@ -72,25 +72,44 @@ class User extends Authenticatable
protected static function booted(): void
{
static::creating(function (self $model) {
// * Prevent user elevation privileges
throw_if(
auth('backend')->user() and auth('backend')->user()->role->value() > $model->role->value(),
AuthorizationException::class
);
self::checkElevationPrivileges($model);
});
static::updating(function (self $model) {
if (optional(auth('backend')->user())->getKey() === $model->getKey()) {
\validator(
['published' => $model->published],
['published' => 'required|boolean|accepted'],
['published.accepted' => trans('crud.messages.user_unpublished')],
)->validate();
}
// * Prevent user elevation privileges
throw_if(
auth('backend')->user() and auth('backend')->user()->role->value() > $model->role->value(),
AuthorizationException::class
);
self::updatePublishedStatus($model);
self::checkElevationPrivileges($model);
});
}
// * METHODS
/**
* Check if the authenticable user can update the published status.
*
* @param self $user
* @return void
*/
private static function updatePublishedStatus(self $user): void
{
if (optional(auth('backend')->user())->getKey() === $user->getKey()) {
\validator(
['published' => $user->published],
['published' => 'required|boolean|accepted'],
['published.accepted' => trans('Vous ne pouvez pas désactiver votre propre compte')],
)->validate();
}
}
/**
* Prevent user elevation privileges.
*
* @param self $user
* @return void
*/
private static function checkElevationPrivileges(self $user): void
{
throw_if(
auth('backend')->user() and auth('backend')->user()->role->value() > $user->role->value(),
AuthorizationException::class
);
}
}

View file

@ -18,6 +18,17 @@ class DiscountPolicy
return UserStaticRules::everyOne();
}
/**
* Determine whether the user can view the model.
*
* @param \App\Models\User $authUser
* @return boolean
*/
public function view(User $authUser): bool
{
return UserStaticRules::atLeastRole($authUser, RoleEnum::admin);
}
/**
* Determine whether the user can update the model.
*

View file

@ -5,12 +5,14 @@ namespace App\Providers;
use App\Enums\Settings\SettingsType;
use App\Models\GeneralSetting;
use App\Models\MenuNodeData;
use App\Providers\TelescopeServiceProvider as CustomTelescopeServiceProvider;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\ServiceProvider;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Blade;
use Laravel\Telescope\TelescopeServiceProvider;
use Money\Currencies\ISOCurrencies;
use Money\Currency;
use Money\Formatter\IntlMoneyFormatter;
@ -71,8 +73,8 @@ class AppServiceProvider extends ServiceProvider
public function register(): void
{
if ($this->app->environment('local')) {
$this->app->register(\Laravel\Telescope\TelescopeServiceProvider::class);
$this->app->register(TelescopeServiceProvider::class);
$this->app->register(CustomTelescopeServiceProvider::class);
}
}

View file

@ -2,36 +2,54 @@
namespace App\Providers;
use App\Enums\Theme\BootstrapThemeEnum;
use Illuminate\Support\Facades\Gate;
use Laravel\Telescope\IncomingEntry;
use Laravel\Telescope\Telescope;
use Laravel\Telescope\TelescopeApplicationServiceProvider;
use Illuminate\Support\Facades\Cache;
class TelescopeServiceProvider extends TelescopeApplicationServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot(): void
{
// Matches Telescope theme with back-end theme.
if (Cache::get('theme', BootstrapThemeEnum::light->value()) === BootstrapThemeEnum::dark->value()) {
Telescope::night();
}
$this->authorization();
}
/**
* Register any application services.
*
* @return void
*/
public function register(): void
{
// Telescope::night();
$this->hideSensitiveRequestDetails();
$isLocal = $this->app->environment('local');
Telescope::filter(function (IncomingEntry $entry) use ($isLocal) {
return $isLocal ||
$entry->isReportableException() ||
$entry->isFailedRequest() ||
$entry->isFailedJob() ||
$entry->isScheduledTask() ||
$entry->hasMonitoredTag();
$entry->isReportableException() ||
$entry->isFailedRequest() ||
$entry->isFailedJob() ||
$entry->isScheduledTask() ||
$entry->hasMonitoredTag();
});
}
/**
* Prevent sensitive request details from being logged by Telescope.
*
* @return void
*/
protected function hideSensitiveRequestDetails(): void
{
@ -50,15 +68,14 @@ class TelescopeServiceProvider extends TelescopeApplicationServiceProvider
/**
* Register the Telescope gate.
*
* This gate determines who can access Telescope in non-local environments.
*
* @return void
*/
protected function gate(): void
{
Gate::define('viewTelescope', function ($user) {
return in_array($user->email, [
//
]);
return in_array($user->email, []);
});
}
}

View file

@ -35,6 +35,8 @@
"uwil/k8s-laravel": "^1.4",
"uwil/laravel-common": "^2.1",
"uwil/seo-laravel": "^3.0",
"uwil/sitemap-generator": "^3.0",
"uwil/unit-tests-laravel": "^1.0",
"verschuur/laravel-robotstxt": "^5.1"
},
"require-dev": {

982
composer.lock generated

File diff suppressed because it is too large Load diff

View file

@ -98,9 +98,9 @@ return [
// Contacts List.
'contactsList' => [
'contact' => explode(',', env('MAIL_LIST_CONTACT')),
'passerelle' => explode(',', env('MAIL_LIST_PASSERELLE')),
'contactNL' => explode(',', env('MAIL_LIST_NL')),
'contact' => explode(',', env('MAIL_LIST_CONTACT', 'contact@legaulois.fr')),
'passerelle' => explode(',', env('MAIL_LIST_PASSERELLE', '')),
'contactNL' => explode(',', env('MAIL_LIST_NL', '')),
],
/*

View file

@ -0,0 +1,97 @@
<?php
return [
/**
* Single route names
*
* Ex:
*
* 'singlePages' => [
* 'homepage',
* ],
*/
'singlePages' => [
'fo.home.show',
'fo.recruitment.show',
'fo.legals.show',
'fo.policies.show',
'fo.conditions.show',
'fo.accessibility.show',
'fo.contact.show',
'fo.brand.story',
'fo.brand.saga',
'fo.news.index',
'fo.products.index',
'fo.recipes.index',
'fo.commitments.index',
'fo.commitments.brand',
'fo.commitments.raise',
'fo.commitments.eat',
'fo.commitments.life',
'fo.commitments.respect',
'fo.breeding.index',
'fo.breeding.oui-c-est-bon',
'fo.breeding.sortant-a-l-exterieur',
'fo.breeders.get-geojson',
'fo.breeders.get-count-per-department',
'fo.breeders.get-manageable-text-component',
],
/**
* Model namespaces with filters
*
* Ex:
* 'cruds' => [
* [
* 'model' => 'App\Models\Product',
* 'filters' => [
* ['published', '=', true]
* ]
* ],
* [
* 'model' => 'App\Models\Article',
* 'filters' => []
* ]
* ],
*/
'cruds' => [
[
'model' => 'App\Models\Product',
'filters' => [
['published', '=', true]
],
],
[
'model' => 'App\Models\Recipe',
'filters' => [
['published', '=', true]
],
],
[
'model' => 'App\Models\News',
'filters' => [
['published', '=', true]
],
]
],
/**
* Enable or disable schedule for the job
* If set to true the sitemap generator will be run
* using the 'cron' instruction
*/
'schedule' => true,
/**
* If you want to set specific
* instruction for when to schedule job
* you can set this with a cron instruction
* You can generate one using https://crontab.guru/
*
* schedule must be set to true
*
* Default is every day at 15:45
*/
'cron' => '45 15 * * *',
];

View file

@ -6,53 +6,53 @@ use Laravel\Telescope\Watchers;
return [
/*
|--------------------------------------------------------------------------
| Telescope Master Switch
|--------------------------------------------------------------------------
|
| This option may be used to disable all Telescope watchers regardless
| of their individual configuration, which simply provides a single
| and convenient way to enable or disable Telescope data storage.
|
|--------------------------------------------------------------------------
| Telescope Master Switch
|--------------------------------------------------------------------------
|
| This option may be used to disable all Telescope watchers regardless
| of their individual configuration, which simply provides a single
| and convenient way to enable or disable Telescope data storage.
|
*/
'enabled' => env('TELESCOPE_ENABLED', false),
/*
|--------------------------------------------------------------------------
| Telescope Domain
|--------------------------------------------------------------------------
|
| This is the subdomain where Telescope will be accessible from. If the
| setting is null, Telescope will reside under the same domain as the
| application. Otherwise, this value will be used as the subdomain.
|
|--------------------------------------------------------------------------
| Telescope Domain
|--------------------------------------------------------------------------
|
| This is the subdomain where Telescope will be accessible from. If the
| setting is null, Telescope will reside under the same domain as the
| application. Otherwise, this value will be used as the subdomain.
|
*/
'domain' => env('TELESCOPE_DOMAIN'),
/*
|--------------------------------------------------------------------------
| Telescope Path
|--------------------------------------------------------------------------
|
| This is the URI path where Telescope will be accessible from. Feel free
| to change this path to anything you like. Note that the URI will not
| affect the paths of its internal API that aren't exposed to users.
|
|--------------------------------------------------------------------------
| Telescope Path
|--------------------------------------------------------------------------
|
| This is the URI path where Telescope will be accessible from. Feel free
| to change this path to anything you like. Note that the URI will not
| affect the paths of its internal API that aren't exposed to users.
|
*/
'path' => env('TELESCOPE_PATH', 'telescope'),
/*
|--------------------------------------------------------------------------
| Telescope Storage Driver
|--------------------------------------------------------------------------
|
| This configuration options determines the storage driver that will
| be used to store Telescope's data. In addition, you may set any
| custom options as needed by the particular driver you choose.
|
|--------------------------------------------------------------------------
| Telescope Storage Driver
|--------------------------------------------------------------------------
|
| This configuration options determines the storage driver that will
| be used to store Telescope's data. In addition, you may set any
| custom options as needed by the particular driver you choose.
|
*/
'driver' => env('TELESCOPE_DRIVER', 'database'),
@ -65,14 +65,14 @@ return [
],
/*
|--------------------------------------------------------------------------
| Telescope Queue
|--------------------------------------------------------------------------
|
| This configuration options determines the queue connection and queue
| which will be used to process ProcessPendingUpdate jobs. This can
| be changed if you would prefer to use a non-default connection.
|
|--------------------------------------------------------------------------
| Telescope Queue
|--------------------------------------------------------------------------
|
| This configuration options determines the queue connection and queue
| which will be used to process ProcessPendingUpdate jobs. This can
| be changed if you would prefer to use a non-default connection.
|
*/
'queue' => [
@ -81,14 +81,14 @@ return [
],
/*
|--------------------------------------------------------------------------
| Telescope Route Middleware
|--------------------------------------------------------------------------
|
| These middleware will be assigned to every Telescope route, giving you
| the chance to add your own middleware to this list or change any of
| the existing middleware. Or, you can simply stick with this list.
|
|--------------------------------------------------------------------------
| Telescope Route Middleware
|--------------------------------------------------------------------------
|
| These middleware will be assigned to every Telescope route, giving you
| the chance to add your own middleware to this list or change any of
| the existing middleware. Or, you can simply stick with this list.
|
*/
'middleware' => [
@ -97,14 +97,14 @@ return [
],
/*
|--------------------------------------------------------------------------
| Allowed / Ignored Paths & Commands
|--------------------------------------------------------------------------
|
| The following array lists the URI paths and Artisan commands that will
| not be watched by Telescope. In addition to this list, some Laravel
| commands, like migrations and queue commands, are always ignored.
|
|--------------------------------------------------------------------------
| Allowed / Ignored Paths & Commands
|--------------------------------------------------------------------------
|
| The following array lists the URI paths and Artisan commands that will
| not be watched by Telescope. In addition to this list, some Laravel
| commands, like migrations and queue commands, are always ignored.
|
*/
'only_paths' => [
@ -117,19 +117,17 @@ return [
'pulse*',
],
'ignore_commands' => [
//
],
'ignore_commands' => [],
/*
|--------------------------------------------------------------------------
| Telescope Watchers
|--------------------------------------------------------------------------
|
| The following array lists the "watchers" that will be registered with
| Telescope. The watchers gather the application's profile data when
| a request or task is executed. Feel free to customize this list.
|
|--------------------------------------------------------------------------
| Telescope Watchers
|--------------------------------------------------------------------------
|
| The following array lists the "watchers" that will be registered with
| Telescope. The watchers gather the application's profile data when
| a request or task is executed. Feel free to customize this list.
|
*/
'watchers' => [

64
config/unit-tests.php Normal file
View file

@ -0,0 +1,64 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| View options
|--------------------------------------------------------------------------
|
| Here you can configure the optional prefix of existing views and all their
| file names.
|
*/
'view' => [
'prefix' => 'bo.',
'name-homepage' => 'dashboard',
'resources-index' => 'index',
'resources-create' => 'create',
'resources-update' => 'edit',
'resources-read' => 'show',
],
/*
|--------------------------------------------------------------------------
| Route options
|--------------------------------------------------------------------------
|
| Here you can configure the optional prefix of existing routes and all
| their action names.
|
*/
'route' => [
'prefix' => 'bo.',
'action-create' => 'store',
'action-update' => 'update',
'action-delete' => 'destroy',
],
/*
|--------------------------------------------------------------------------
| Model field used for an update
|--------------------------------------------------------------------------
|
| Here you can configure the list of possible text fields existing in a model,
| (the first one to exist will be updated, must be a text field).
| ex: ['name', 'label', 'title', 'first_name'].
|
*/
'list-fields' => [
'name',
'label',
'title',
'first_name',
'catchline',
'text',
'answer',
]
];

View file

@ -0,0 +1,32 @@
<?php
namespace Database\Factories;
use App\Enums\ActivityLogs\ActivityLogsEventEnum;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends Factory<\App\Models\ActivityLog>
*/
final class ActivityLogFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
$boolean = fake()->boolean(50);
return [
'user_id' => null,
'is_anonymous' => $boolean,
'is_console' => !$boolean,
'model_class' => "\App\Models\User",
'model_id' => 1,
'event' => \collect(ActivityLogsEventEnum::toArray())->random()->value,
'data' => [],
'created_at' => now(),
];
}
}

View file

@ -17,6 +17,7 @@ class ApproachFactory extends Factory
return [
'type' => fake()->boolean(50) ? ApproachTypeEnum::label : ApproachTypeEnum::demarche,
'name' => fake()->words(3, true),
'picture' => '',
'picture_title' => fake()->words(5, true),
'picture_alt' => fake()->words(8, true),
'published' => fake()->boolean(75),

View file

@ -16,10 +16,12 @@ class BrandAdvantageFactory extends Factory
return [
'title' => fake()->text(10),
'sustitle' => fake()->text(10),
'picto' => '',
'picto_alt' => fake()->text(255),
'picto_title' => fake()->text(255),
'text' => fake()->text(165),
'is_large' => fake()->boolean(25),
'order' => 1,
'published' => fake()->boolean(75),
];
}

View file

@ -2,6 +2,11 @@
namespace Database\Factories;
use App\Enums\Breeders\GeoType;
use App\Enums\Breeders\OCBStatus;
use App\Enums\Breeders\OCBType;
use App\Enums\Department;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Factories\Factory;
class BreederFactory extends Factory
@ -13,19 +18,36 @@ class BreederFactory extends Factory
*/
public function definition(): array
{
$code = strval(fake()->numberBetween(1, 1000));
$lastname = fake()->lastname();
$firstname = fake()->firstName();
return [
'inuav_codes' => [
'breeder_code' => $code,
'inuav_codes' => [
fake()->text(10),
fake()->text(10),
],
'first_name' => fake()->firstName(),
'last_name' => fake()->lastName(),
'picture_title' => fake()->words(5, true),
'picture_alt' => fake()->words(8, true),
'postal_code' => fake()->postcode(),
'testimony' => fake()->text(),
'is_highlighted' => fake()->boolean(75),
'published' => fake()->boolean(75),
'slug' => sprintf("%s-%s-%s", $code, $lastname, $firstname),
'first_name' => $firstname,
'last_name' => fake()->lastName(),
'picture' => '',
'picture_title' => fake()->words(5, true),
'picture_alt' => fake()->words(8, true),
'postal_code' => fake()->postcode(),
'department' => \collect(Department::toArray())->random()->value,
'place' => fake()->word(),
'testimony' => fake()->text(),
'latitude' => fake()->randomFloat(2),
'longitude' => fake()->randomFloat(2),
'geo_type' => \collect(GeoType::toArray())->random()->value,
'ocbStatus' => \collect(OCBStatus::toArray())->random()->value,
'ocbType' => \collect(OCBType::toArray())->random()->value,
'audit' => 1, // FIXME: utilité de ce champs, aucune indication
'valid_marketing_date' => Carbon::now(),
'approaches' => [],
'is_highlighted' => fake()->boolean(75),
'order' => 1,
'published' => fake()->boolean(75),
];
}
}

View file

@ -11,7 +11,7 @@ class ClaimFactory extends Factory
*
* @return array<string, mixed>
*/
public function definition()
public function definition(): array
{
return [
'label' => fake()->words(rand(1, 2), true),

View file

@ -12,13 +12,15 @@ class ConsumptionMomentFactory extends Factory
*
* @return array<string, mixed>
*/
public function definition()
public function definition(): array
{
$title = fake()->words(rand(1, 2), true);
return [
'title' => $title,
'subtitle' => fake()->text(10),
'slug' => Str::of($title)->slug(),
'description' => fake()->text(),
'picture' => '',
'picture_alt' => fake()->sentence(),
'picture_title' => fake()->sentence(),
];

View file

@ -17,9 +17,10 @@ class DemarcheSlideFactory extends Factory
$button1status = fake()->boolean(75);
$button2status = fake()->boolean(75);
$publishedStatus = fake()->boolean(75);
$publish_at = Carbon::now()->addMonth();
$publishedAt = Carbon::now()->addMonth();
return [
'title' => fake()->words(rand(1, 2), true),
'picture' => '',
'picture_alt' => fake()->sentence(),
'picture_title' => fake()->sentence(),
'button_1_text' => $button1status ? fake()->sentence(3) : null,
@ -27,13 +28,14 @@ class DemarcheSlideFactory extends Factory
'button_2_text' => $button2status ? fake()->sentence(3) : null,
'button_2_url' => $button2status ? fake()->url() : null,
'text' => \clean(\fake()->randomHtml(1, 1)),
'order' => 1,
'button_1_status' => $button1status,
'button_1_target' => $button1status ? fake()->boolean(75) : false,
'button_2_status' => $button2status,
'button_2_target' => $button2status ? fake()->boolean(75) : false,
'published' => $publishedStatus,
'publish_at' => !$publishedStatus ? $publish_at : null,
'unpublish_at' => !$publishedStatus ? $publish_at->copy()->addDays(rand(10, 20)) : null,
'published_at' => $publishedStatus ? $publishedAt : null,
'unpublished_at' => !$publishedStatus ? $publishedAt->copy()->addDays(rand(10, 20)) : null,
];
}
}

View file

@ -19,7 +19,7 @@ class DepartaimantsCollectionFactory extends Factory
*
* @return array
*/
public function definition()
public function definition(): array
{
$bigNumber = function () {
// * prevent the first number from being 0

View file

@ -11,13 +11,16 @@ class DiscountFactory extends Factory
*
* @return array<string, mixed>
*/
public function definition()
public function definition(): array
{
return [
'picture_alt' => fake()->sentence(),
'picture_title' => fake()->sentence(),
'amount' => fake()->randomNumber(),
'validity' => fake()->sentence(),
'name' => fake()->word(),
'desktop_image_available' => '',
'desktop_image_unavailable' => '',
'mobile_image_available' => '',
'mobile_image_unavailable' => '',
'code' => fake()->numberBetween(1, 10000),
'value' => fake()->randomFloat(1, 1, 100),
];
}
}

View file

@ -11,17 +11,20 @@ class HistoricalMilestoneFactory extends Factory
*
* @return array<string, mixed>
*/
public function definition()
public function definition(): array
{
return [
'year' => fake()->randomFloat(1, 1900, 2100),
'year' => fake()->randomFloat(1, 1901, 2100),
'title' => fake()->words(rand(1, 2), true),
'description' => fake()->sentence(),
'picture' => '',
'picture_alt' => fake()->sentence(),
'picture_title' => fake()->sentence(),
'video_id' => null,
'picture_alt' => null,
'picture_title' => null,
'picto' => null,
'picto_alt' => null,
'picto_title' => null,
'order' => 1,
'published' => fake()->boolean(75),
];
}

View file

@ -11,7 +11,7 @@ class IncoNutritionalValueFactory extends Factory
*
* @return array<string, mixed>
*/
public function definition()
public function definition(): array
{
return [
'energy' => fake()->randomFloat(1, 0, 100),

View file

@ -11,13 +11,15 @@ class KeyNumberFactory extends Factory
*
* @return array<string, mixed>
*/
public function definition()
public function definition(): array
{
return [
'text' => fake()->sentence(),
'picto' => '',
'picto_alt' => fake()->sentence(),
'picto_title' => fake()->sentence(),
'text' => fake()->sentence(),
'source' => fake()->sentence(),
'order' => 1,
'published' => fake()->boolean(75),
];
}

View file

@ -15,27 +15,30 @@ class MainSlideFactory extends Factory
* @return array<string, mixed>
* @phpcs:disable Generic.Metrics.CyclomaticComplexity.TooHigh
*/
public function definition()
public function definition(): array
{
// @phpcs:enable
$button1status = fake()->boolean(75);
$button2status = fake()->boolean(75);
$publishedStatus = fake()->boolean(75);
$publish_at = Carbon::now()->addMonth();
$published_at = Carbon::now()->addMonth();
return [
'title' => fake()->words(rand(1, 2), true),
'subtitle' => fake()->words(rand(1, 2), true),
'approach_id' => (fake()->boolean(50)) ? collect(
Approach::query()->where('published', true)->where('type', ApproachTypeEnum::demarche)->get()->random(1)
)->first()->getKey() : null,
'background' => '',
'background_alt' => fake()->sentence(),
'background_title' => fake()->sentence(),
'picture' => '',
'picture_alt' => fake()->sentence(),
'picture_title' => fake()->sentence(),
'button_1_text' => $button1status ? fake()->sentence(3) : null,
'button_1_url' => $button1status ? fake()->url() : null,
'button_2_text' => $button2status ? fake()->sentence(3) : null,
'button_2_url' => $button2status ? fake()->url() : null,
'order' => 1,
'color_block' => fake()->unique()->safeHexColor(),
'button_1_color_text' => '#FFFFFF',
'button_1_color_background' => '#4E3238',
@ -47,8 +50,8 @@ class MainSlideFactory extends Factory
'button_2_target' => $button2status ? fake()->boolean(75) : false,
'new' => fake()->boolean(75),
'published' => fake()->boolean(75),
'publish_at' => !$publishedStatus ? $publish_at : null,
'unpublish_at' => !$publishedStatus ? $publish_at->copy()->addDays(rand(10, 20)) : null,
'published_at' => $publishedStatus ? $published_at : null,
'unpublished_at' => !$publishedStatus ? $published_at->copy()->addDays(rand(10, 20)) : null,
];
}
}

View file

@ -12,7 +12,7 @@ class MeatFactory extends Factory
*
* @return array<string, mixed>
*/
public function definition()
public function definition(): array
{
$label = fake()->unique()->words(rand(1, 2), true);
return [
@ -20,11 +20,14 @@ class MeatFactory extends Factory
'subtitle' => fake()->text(10),
'slug' => Str::slug($label),
'description' => fake()->sentence(),
'banner' => '',
'banner_alt' => fake()->sentence(),
'banner_title' => fake()->sentence(),
'picture' => '',
'picture_alt' => fake()->sentence(),
'picture_title' => fake()->sentence(),
'color' => fake()->unique()->safeHexColor(),
'order' => 1,
'published' => fake()->boolean(75),
];
}

View file

@ -2,6 +2,7 @@
namespace Database\Factories;
use App\Enums\Settings\MenuNodeType;
use Illuminate\Database\Eloquent\Factories\Factory;
class MenuNodeDataFactory extends Factory
@ -11,9 +12,10 @@ class MenuNodeDataFactory extends Factory
*
* @return array<string, mixed>
*/
public function definition()
public function definition(): array
{
return [
'type' => \collect(MenuNodeType::toArray())->random()->value,
'sub_label' => fake()->sentence(),
'title' => fake()->sentence(),
'text' => fake()->sentence(),
@ -22,9 +24,11 @@ class MenuNodeDataFactory extends Factory
'link_title' => fake()->sentence(),
'link_target' => fake()->boolean(),
'link_status' => fake()->boolean(),
'picture' => '',
'picture_alt' => fake()->sentence(),
'picture_title' => fake()->sentence(),
'picture_status' => fake()->boolean(),
'background_picture' => '',
'background_picture_alt' => fake()->sentence(),
'background_picture_title' => fake()->sentence(),
];

View file

@ -29,9 +29,11 @@ class NewsBreedingFactory extends Factory
'subtitle' => fake()->sentence(),
'content' => fake()->text(),
'slug' => Str::slug($title),
'picture' => '',
'picture_alt' => fake()->sentence(),
'picture_title' => fake()->sentence(),
'associated_page' => collect(StaticPageType::getBreedingPages())->random(),
'order' => 1,
'published' => $publishedStatus,
'publish_at' => !$publishedStatus ? $publish_at : null,
'unpublish_at' => !$publishedStatus ? $publish_at->copy()->addDays(rand(10, 20)) : null,

View file

@ -23,6 +23,8 @@ class NewsCategoryFactory extends Factory
'seo_description' => fake()->sentence(),
'title' => $title,
'slug' => Str::slug($title),
'color' => fake()->numberBetween(),
'order' => 1,
'published' => fake()->boolean(75),
];
}

View file

@ -22,11 +22,13 @@ class NewsClubFactory extends Factory
return [
'title' => $title,
'slug' => Str::slug($title),
'picture' => '',
'picture_alt' => fake()->sentence(),
'picture_title' => fake()->sentence(),
'content' => fake()->text(),
'type' => \collect(NewsClubTypeEnum::toArray())->random()->value,
'multiple_answers' => fake()->boolean(50),
'published' => fake()->boolean(75),
];
}
}

View file

@ -23,6 +23,7 @@ class NewsCorporateFactory extends Factory
'title' => fake()->sentence(),
'content' => fake()->text(),
'url' => fake()->url(),
'picture' => '',
'picture_alt' => fake()->sentence(),
'picture_title' => fake()->sentence(),
'published' => $publishedStatus,

View file

@ -28,8 +28,10 @@ class NewsFactory extends Factory
'subtitle' => fake()->sentence(),
'content' => fake()->text(),
'slug' => Str::slug($title),
'picture' => '',
'picture_alt' => fake()->sentence(),
'picture_title' => fake()->sentence(),
'thumbnail' => '',
'thumbnail_alt' => fake()->sentence(),
'thumbnail_title' => fake()->sentence(),
'highlight' => false,

View file

@ -11,15 +11,17 @@ class OfferFactory extends Factory
*
* @return array<string, mixed>
*/
public function definition()
public function definition(): array
{
return [
'title' => fake()->words(3, true),
'location' => fake()->words(5, true),
'contract' => fake()->words(5, true),
'function' => fake()->words(5, true),
'picture' => '',
'picture_alt' => fake()->words(5, true),
'picture_title' => fake()->words(5, true),
'link' => fake()->url(),
'description' => fake()->sentence(),
'published' => fake()->boolean(75),
];

View file

@ -9,6 +9,7 @@ use App\Models\Range;
use App\Models\Submeat;
use App\Models\Subrange;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
class ProductFactory extends Factory
{
@ -17,16 +18,24 @@ class ProductFactory extends Factory
*
* @return array<string, mixed>
*/
public function definition()
public function definition(): array
{
$label = fake()->words(3, true);
$meatBoolean = fake()->boolean(50);
$rangeBoolean = fake()->boolean(50);
return [
'label' => fake()->words(3, true),
'seo_title' => fake()->sentence(),
'seo_description' => fake()->sentence(),
'label' => $label,
'claim_title' => fake()->words(3, true),
'slug' => Str::slug($label),
'picture' => '',
'picture_alt' => fake()->words(5, true),
'picture_title' => fake()->words(5, true),
'banner' => '',
'banner_alt' => fake()->words(5, true),
'banner_title' => fake()->words(5, true),
'packaging' => '',
'packaging_alt' => fake()->words(5, true),
'packaging_title' => fake()->words(5, true),
'description' => fake()->sentence(),

View file

@ -11,11 +11,12 @@ class ProductTypeFactory extends Factory
*
* @return array<string, mixed>
*/
public function definition()
public function definition(): array
{
return [
'label' => fake()->words(rand(1, 2), true),
'description' => fake()->sentence(),
'picture' => '',
'picture_alt' => fake()->sentence(),
'picture_title' => fake()->sentence(),
'button_status' => fake()->boolean(75),

View file

@ -23,10 +23,11 @@ class ProfessionFactory extends Factory
return [
'title' => fake()->firstName,
'picture_title' => fake()->words(5, true),
'picture' => '',
'picture_alt' => fake()->words(8, true),
'job_url' => fake()->url(),
'picture_title' => fake()->words(5, true),
'jobs_list' => $jobsList,
'job_url' => fake()->url(),
'published' => fake()->boolean(75),
];
}

View file

@ -12,7 +12,7 @@ class RangeFactory extends Factory
*
* @return array<string, mixed>
*/
public function definition()
public function definition(): array
{
$label = fake()->unique()->words(rand(1, 2), true);
return [
@ -20,13 +20,17 @@ class RangeFactory extends Factory
'subtitle' => fake()->text(10),
'slug' => Str::slug($label),
'description' => fake()->sentence(),
'banner' => '',
'banner_alt' => fake()->sentence(),
'banner_title' => fake()->sentence(),
'banner_ambiance' => '',
'banner_ambiance_alt' => fake()->sentence(),
'banner_ambiance_title' => fake()->sentence(),
'picture' => '',
'picture_alt' => fake()->sentence(),
'picture_title' => fake()->sentence(),
'color' => fake()->unique()->safeHexColor(),
'order' => 1,
'published' => fake()->boolean(75),
];
}

View file

@ -30,20 +30,24 @@ class RecipeFactory extends Factory
}
return [
'seo_title' => fake()->sentence(),
'seo_description' => fake()->sentence(),
'slug' => Str::slug($title),
'title' => $title,
'tips' => fake()->sentence(),
'picture' => '',
'picture_alt' => fake()->words(8, true),
'picture_title' => fake()->words(5, true),
'advice' => fake()->sentence(),
'preparation' => fake()->sentence(),
'ingredients_list' => $ingredientsList,
'preparation' => fake()->sentence(),
'advice' => fake()->sentence(),
'video_id' => fake()->boolean(50) ? \collect(Video::all())->random() : null,
'consumption_moment_id' => \collect(ConsumptionMoment::all())->random(),
'preparation_time' => fake()->numberBetween(1, 100),
'cooking_time' => fake()->numberBetween(1, 100),
'nb_guests' => fake()->numberBetween(1, 10),
'difficulty' => \collect(DifficultyEnum::toArray())->random()->value,
'highlight' => fake()->boolean(75),
'published' => fake()->boolean(75),
];
}

View file

@ -0,0 +1,32 @@
<?php
namespace Database\Factories;
use App\Enums\Shop\SellItemsType;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\SellItem>
*/
class SellItemFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
'name' => fake()->words(rand(1, 2), true),
'picture' => '',
'picture_alt' => fake()->sentence(),
'picture_title' => fake()->sentence(),
'price' => fake()->numberBetween(1, 100),
'arcadia_weight' => fake()->numberBetween(1, 100),
'arcadia_id' => fake()->unique()->numberBetween(100, 500),
'order' => 1,
'type' => \collect(SellItemsType::toArray())->random()->value,
];
}
}

View file

@ -0,0 +1,36 @@
<?php
namespace Database\Factories;
use App\Enums\StaticPageType;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\SellItem>
*/
class StaticPageFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
$title = fake()->unique()->words(rand(1, 2), true);
return [
'type' => \collect(StaticPageType::toArray())->random()->value,
'seo_title' => fake()->sentence(),
'seo_description' => fake()->sentence(),
'title' => $title,
'slug' => Str::slug($title),
'subtitle' => fake()->words(rand(1, 2), true),
'picture' => '',
'picture_alt' => fake()->sentence(),
'picture_title' => fake()->sentence(),
'content' => fake()->sentence(),
'data' => [],
];
}
}

View file

@ -2,6 +2,7 @@
namespace Database\Factories;
use App\Models\Meat;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
@ -12,7 +13,7 @@ class SubmeatFactory extends Factory
*
* @return array<string, mixed>
*/
public function definition()
public function definition(): array
{
$label = fake()->unique()->words(rand(1, 2), true);
return [
@ -20,8 +21,11 @@ class SubmeatFactory extends Factory
'subtitle' => fake()->text(10),
'slug' => Str::slug($label),
'description' => fake()->sentence(),
'picture' => '',
'picture_alt' => fake()->sentence(),
'picture_title' => fake()->sentence(),
'meat_id' => Meat::query()->where('published', true)->inRandomOrder()->value('id'),
'order' => 1,
'published' => fake()->boolean(75),
];
}

View file

@ -2,6 +2,7 @@
namespace Database\Factories;
use App\Models\Range;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
@ -12,7 +13,7 @@ class SubrangeFactory extends Factory
*
* @return array<string, mixed>
*/
public function definition()
public function definition(): array
{
$label = fake()->unique()->words(rand(1, 2), true);
return [
@ -20,8 +21,11 @@ class SubrangeFactory extends Factory
'subtitle' => fake()->text(10),
'slug' => Str::slug($label),
'description' => fake()->sentence(),
'picture' => '',
'picture_alt' => fake()->sentence(),
'picture_title' => fake()->sentence(),
'range_id' => Range::query()->where('published', true)->inRandomOrder()->value('id'),
'order' => 1,
'published' => fake()->boolean(75),
];
}

View file

@ -20,8 +20,9 @@ class SurveysAnswerFactory extends Factory
{
return [
'news_club_id' => NewsClub::query()->where('type', NewsClubTypeEnum::survey)->inRandomOrder()->value('id'),
'answer' => fake()->unique()->words(rand(1, 2), true),
'order' => 1,
'published' => fake()->boolean(75),
'answer' => fake()->unique()->words(rand(1, 2), true),
];
}
}

View file

@ -11,17 +11,19 @@ class TestimonialFactory extends Factory
*
* @return array<string, mixed>
*/
public function definition()
public function definition(): array
{
return [
'catchline' => fake()->text(25),
'content' => fake()->text(150),
'identity' => fake()->name(),
'job' => fake()->jobTitle(),
'picture' => '',
'picture_alt' => fake()->sentence(),
'picture_title' => fake()->sentence(),
'video_id' => fake()->boolean(25) ? '6B4O-_1CQoI' : '',
'published' => false,
'order' => 1,
'published' => fake()->boolean(75),
];
}
}

View file

@ -21,12 +21,11 @@ class UserFactory extends Factory
'first_name' => fake()->firstName,
'last_name' => fake()->lastName,
'email' => fake()->unique()->safeEmail(),
'email_verified_at' => now(),
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi',
'remember_token' => Str::random(10),
'role' => $randEnum->value,
'published' => $published,
'published_at' => ($published) ? now() : null,
'last_connection' => ($published) ? now() : null,
'published' => true,
'published_at' => now(),
];
}

View file

@ -11,11 +11,12 @@ class VideoFactory extends Factory
*
* @return array<string, mixed>
*/
public function definition()
public function definition(): array
{
return [
'title' => fake()->unique()->words(rand(1, 2), true),
'video_id' => '7rpgfetac0U',
'order' => 1,
'is_on_homepage' => fake()->boolean(25),
'published' => fake()->boolean(75),
];

View file

@ -0,0 +1,54 @@
<?php
use App\Enums\HistoricalMilestones\HistoricalMilestonePosition;
use App\Models\HistoricalMilestone;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up(): void
{
Schema::table('demarche_slides', function (Blueprint $table) {
$table->renameColumn('publish_at', 'published_at');
$table->renameColumn('unpublish_at', 'unpublished_at');
});
Schema::table('historical_milestones', function (Blueprint $table) {
$table->tinyInteger('picto_position')->nullable()->comment('Historical milestone picto position.')->after('picto_title');
$table->integer('order')->comment('Historical milestone order.')->after('published')->change();
});
HistoricalMilestone::query()->where('picto_placement', 'hg')->get()->map(function (HistoricalMilestone $historicalMilestoneModel) {
$historicalMilestoneModel->picto_position = HistoricalMilestonePosition::topLeft;
$historicalMilestoneModel->saveQuietly();
});
HistoricalMilestone::query()->where('picto_placement', 'hd')->get()->map(function (HistoricalMilestone $historicalMilestoneModel) {
$historicalMilestoneModel->picto_position = HistoricalMilestonePosition::topRight;
$historicalMilestoneModel->saveQuietly();
});
Schema::table('historical_milestones', function (Blueprint $table) {
$table->dropColumn('picto_placement');
});
Schema::table('main_slides', function (Blueprint $table) {
$table->renameColumn('publish_at', 'published_at');
$table->renameColumn('unpublish_at', 'unpublished_at');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down(): void
{
//
}
};

View file

@ -51,7 +51,7 @@ metadata:
spec:
storageClassName: "csi-cinder-classic"
accessModes:
- ReadWriteOnce
- ReadWriteOnce
resources:
requests:
storage: $APP_PVC_SIZE
@ -72,25 +72,25 @@ spec:
app: ${CI_PROJECT_PATH_SLUG}-app
spec:
containers:
- name: ${CI_PROJECT_PATH_SLUG}-container
image: $IMAGE_TAG
envFrom:
- configMapRef:
name: ${CI_PROJECT_PATH_SLUG}-config-map
volumeMounts:
- name: storage
mountPath: /app/srcs/storage
- name: ${CI_PROJECT_PATH_SLUG}-container
image: $IMAGE_TAG
envFrom:
- configMapRef:
name: ${CI_PROJECT_PATH_SLUG}-config-map
volumeMounts:
- name: storage
mountPath: /app/srcs/storage
imagePullSecrets:
- name: docker-registry-credentials
- name: docker-registry-credentials
securityContext:
runAsUser: 33
runAsGroup: 33
fsGroup: 33
fsGroupChangePolicy: "OnRootMismatch"
volumes:
- name: storage
persistentVolumeClaim:
claimName: ${CI_PROJECT_PATH_SLUG}-pvc-storage
- name: storage
persistentVolumeClaim:
claimName: ${CI_PROJECT_PATH_SLUG}-pvc-storage
---
apiVersion: v1
@ -101,8 +101,8 @@ spec:
selector:
app: ${CI_PROJECT_PATH_SLUG}-app
ports:
- port: 80
targetPort: 443
- port: 80
targetPort: 443
---
apiVersion: traefik.io/v1alpha1
@ -111,16 +111,16 @@ metadata:
name: ${CI_PROJECT_PATH_SLUG}-ingress-route
spec:
entryPoints:
- web
- websecure
- web
- websecure
routes:
- match: Host(`${APP_DOMAIN}`) || Host(`www.${APP_DOMAIN}`)
kind: Rule
services:
- name: ${CI_PROJECT_PATH_SLUG}-service
port: 80
middlewares:
- name: redirect-no-www-to-www
- match: Host(`${APP_DOMAIN}`) || Host(`www.${APP_DOMAIN}`)
kind: Rule
services:
- name: ${CI_PROJECT_PATH_SLUG}-service
port: 80
middlewares:
- name: redirect-no-www-to-www
tls:
secretName: ${CRT_TLS_NAME}
@ -131,6 +131,7 @@ metadata:
name: ${CI_PROJECT_PATH_SLUG}-cronjob
spec:
schedule: "* * * * *"
concurrencyPolicy: Forbid
jobTemplate:
spec:
template:
@ -138,35 +139,35 @@ spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- ${CI_PROJECT_PATH_SLUG}-app
topologyKey: "kubernetes.io/hostname"
namespaces: [$KUBE_NAMESPACE]
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- ${CI_PROJECT_PATH_SLUG}-app
topologyKey: "kubernetes.io/hostname"
namespaces: [$KUBE_NAMESPACE]
containers:
- name: ${CI_PROJECT_PATH_SLUG}-scheduled
image: $IMAGE_TAG
imagePullPolicy: IfNotPresent
command:
- "php"
args:
- "artisan"
- "schedule:run"
envFrom:
- configMapRef:
name: ${CI_PROJECT_PATH_SLUG}-config-map
volumeMounts:
- name: storage
mountPath: /app/srcs/storage
imagePullSecrets:
- name: docker-registry-credentials
volumes:
- name: ${CI_PROJECT_PATH_SLUG}-scheduled
image: $IMAGE_TAG
imagePullPolicy: IfNotPresent
command:
- "php"
args:
- "artisan"
- "schedule:run"
envFrom:
- configMapRef:
name: ${CI_PROJECT_PATH_SLUG}-config-map
volumeMounts:
- name: storage
persistentVolumeClaim:
claimName: ${CI_PROJECT_PATH_SLUG}-pvc-storage
mountPath: /app/srcs/storage
imagePullSecrets:
- name: docker-registry-credentials
volumes:
- name: storage
persistentVolumeClaim:
claimName: ${CI_PROJECT_PATH_SLUG}-pvc-storage
securityContext:
runAsUser: 33
runAsGroup: 33

View file

@ -1,31 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="vendor/autoload.php"
colors="true"
>
<testsuites>
<testsuite name="Unit">
<directory suffix="Test.php">./tests/Unit</directory>
</testsuite>
<testsuite name="Feature">
<directory suffix="Test.php">./tests/Feature</directory>
</testsuite>
</testsuites>
<coverage>
<include>
<directory suffix=".php">./app</directory>
</include>
</coverage>
<php>
<env name="APP_ENV" value="testing"/>
<env name="BCRYPT_ROUNDS" value="4"/>
<env name="CACHE_DRIVER" value="array"/>
<!-- <env name="DB_CONNECTION" value="sqlite"/> -->
<!-- <env name="DB_DATABASE" value=":memory:"/> -->
<env name="MAIL_MAILER" value="array"/>
<env name="QUEUE_CONNECTION" value="sync"/>
<env name="SESSION_DRIVER" value="array"/>
<env name="TELESCOPE_ENABLED" value="false"/>
</php>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.3/phpunit.xsd" bootstrap="vendor/autoload.php" colors="true">
<coverage includeUncoveredFiles="true">
<report>
<html outputDirectory="tests/coverage" />
</report>
</coverage>
<testsuites>
<testsuite name="Tests">
<directory suffix="Test.php">
./tests/Back
</directory>
</testsuite>
</testsuites>
<php>
<env name="APP_ENV" value="testing" />
<env name="BCRYPT_ROUNDS" value="4" />
<env name="CACHE_DRIVER" value="array" />
<env name="MAIL_MAILER" value="array" />
<env name="QUEUE_DRIVER" value="database" />
<env name="QUEUE_CONNECTION" value="database" />
<env name="SESSION_DRIVER" value="array" />
<env name="TELESCOPE_ENABLED" value="false" />
</php>
<source>
<include>
<directory suffix=".php">
./app
</directory>
</include>
</source>
</phpunit>

View file

@ -282,6 +282,7 @@ return [
'order' => 'order',
'packaging' => 'packaging',
'picto' => 'pictogram',
'picto_position' => 'pictogram position',
'preparation_time' => 'preparation time (in minutes)',
'preparation' => 'preparation',
'price' => 'price',

View file

@ -288,6 +288,7 @@ return [
'order' => 'ordre',
'packaging' => 'emballage',
'picto' => 'pictogramme',
'picto_position' => 'position du pictogramme',
'preparation_time' => 'temps de préparation (en minutes)',
'preparation' => 'préparation',
'price' => 'prix',

View file

@ -98,8 +98,8 @@
value="{{ $bootstrapTheme->value }}">
<label for="theme{{ $key }}" @class([
'dropdown-item btn btn-secondary py-2',
'active' => !is_null(Cache::get('theme'))
? $bootstrapTheme->value === intval(Cache::get('theme'))
'active' => !is_null(cache()->get('theme'))
? $bootstrapTheme->value === intval(cache()->get('theme'))
: $bootstrapTheme->value === BootstrapThemeEnum::light->value,
])>{{ str($bootstrapTheme->label)->ucFirst() }}</label>
@endforeach

View file

@ -821,33 +821,11 @@
</ul>
</div>
{{-- BREEDING --}}
<div class="dropdown">
<button data-bs-toggle="dropdown" type="button" aria-expanded="false" @class([
'btn btn-primary text-start w-100 dropdown-toggle mt-1',
'fw-bold active' =>
url()->current() ===
route(
'bo.static_pages.edit',
$breedingPoultryStaticPageModel->type->value()) ||
url()->current() ===
route(
'bo.static_pages.edit',
$breedingJobStaticPageModel->type->value()) ||
url()->current() ===
route(
'bo.static_pages.edit',
$breedingFoodStaticPageModel->type->value()) ||
url()->current() ===
route(
'bo.static_pages.edit',
$breedingHealthStaticPageModel->type->value()) ||
// FIXME: uncomment when breeder map feature is ready
// || url()->current() === route('bo.general_settings.edit', \App\Enums\Settings\SettingsType::breederMap->value())
request()->routeIs('bo.news_breedings.*'),
])>
<i @class([
'fa-solid fa-tractor fa-fw',
'fa-lg' =>
@if(isset($breedingPoultryStaticPageModel))
<div class="dropdown">
<button data-bs-toggle="dropdown" type="button" aria-expanded="false" @class([
'btn btn-primary text-start w-100 dropdown-toggle mt-1',
'fw-bold active' =>
url()->current() ===
route(
'bo.static_pages.edit',
@ -867,137 +845,163 @@
// FIXME: uncomment when breeder map feature is ready
// || url()->current() === route('bo.general_settings.edit', \App\Enums\Settings\SettingsType::breederMap->value())
request()->routeIs('bo.news_breedings.*'),
])></i>
{{ __('Elevages') }}
</button>
<ul class="dropdown-menu">
{{-- BREEDING PAGES --}}
@foreach ($breedingPages as $breedingPage)
])>
<i @class([
'fa-solid fa-tractor fa-fw',
'fa-lg' =>
url()->current() ===
route(
'bo.static_pages.edit',
$breedingPoultryStaticPageModel->type->value()) ||
url()->current() ===
route(
'bo.static_pages.edit',
$breedingJobStaticPageModel->type->value()) ||
url()->current() ===
route(
'bo.static_pages.edit',
$breedingFoodStaticPageModel->type->value()) ||
url()->current() ===
route(
'bo.static_pages.edit',
$breedingHealthStaticPageModel->type->value()) ||
// FIXME: uncomment when breeder map feature is ready
// || url()->current() === route('bo.general_settings.edit', \App\Enums\Settings\SettingsType::breederMap->value())
request()->routeIs('bo.news_breedings.*'),
])></i>
{{ __('Elevages') }}
</button>
<ul class="dropdown-menu">
{{-- BREEDING PAGES --}}
@foreach ($breedingPages as $breedingPage)
<li>
<a data-bs-toggle="tooltip" href="{{ route('bo.static_pages.edit', $breedingPage) }}"
title="{{ __('crud.helpers.update_model', ['model' => $breedingPage->type->label()]) }}"
@class([
'dropdown-item px-3 py-2',
'fw-bold text-bg-secondary' =>
url()->current() ===
route('bo.static_pages.edit', $breedingPage->type->value()),
])>
<i @class([
'fa-solid fa-file fa-fw',
'fa-lg' =>
url()->current() ===
route('bo.static_pages.edit', $breedingPage->type->value()),
])></i>
{{ sprintf('Page %s', $breedingPage->type->label()) }}
</a>
</li>
@endforeach
<li>
<a data-bs-toggle="tooltip" href="{{ route('bo.static_pages.edit', $breedingPage) }}"
title="{{ __('crud.helpers.update_model', ['model' => $breedingPage->type->label()]) }}"
<hr class="dropdown-divider">
</li>
{{-- NEWS BREEDING --}}
<li>
<a data-bs-toggle="tooltip" href="{{ route('bo.news_breedings.index') }}"
title="{{ __('crud.helpers.update_model', ['model' => trans_choice('models.classes.news_breeding', \INF)]) }}"
@class([
'dropdown-item px-3 py-2',
'fw-bold text-bg-secondary' =>
url()->current() ===
route('bo.static_pages.edit', $breedingPage->type->value()),
'fw-bold text-bg-secondary' => request()->routeIs('bo.news_breedings.*'),
])>
<i @class([
'fa-solid fa-file fa-fw',
'fa-lg' =>
url()->current() ===
route('bo.static_pages.edit', $breedingPage->type->value()),
'fa-solid fa-newspaper fa-fw',
'fa-lg' => request()->routeIs('bo.news_breedings.*'),
])></i>
{{ sprintf('Page %s', $breedingPage->type->label()) }}
{{ str(trans_choice('models.classes.news_breeding', \INF))->ucFirst() }}
</a>
</li>
@endforeach
<li>
<hr class="dropdown-divider">
</li>
{{-- NEWS BREEDING --}}
<li>
<a data-bs-toggle="tooltip" href="{{ route('bo.news_breedings.index') }}"
title="{{ __('crud.helpers.update_model', ['model' => trans_choice('models.classes.news_breeding', \INF)]) }}"
@class([
'dropdown-item px-3 py-2',
'fw-bold text-bg-secondary' => request()->routeIs('bo.news_breedings.*'),
])>
<i @class([
'fa-solid fa-newspaper fa-fw',
'fa-lg' => request()->routeIs('bo.news_breedings.*'),
])></i>
{{ str(trans_choice('models.classes.news_breeding', \INF))->ucFirst() }}
</a>
</li>
{{-- BREEDER MAP --}}
{{-- FIXME: uncomment when breeder map feature is ready --}}
{{-- <li>
<a data-bs-toggle="tooltip" href="{{ route('bo.general_settings.edit', $breederMapSettingModel) }}"
title="{{ __('crud.helpers.update_model', ['model' => $breederMapSettingModel->type->label()]) }}"
@class([
'dropdown-item px-3 py-2',
'fw-bold text-bg-secondary' => url()->current() === route('bo.general_settings.edit', \App\Enums\Settings\SettingsType::breederMap->value()),
])>
<i @class([
'fa-solid fa-map-location-dot fa-fw',
'fa-lg' => url()->current() === route('bo.general_settings.edit', \App\Enums\Settings\SettingsType::breederMap->value()),
])></i>
{{ $breederMapSettingModel->type->label() }}
</a>
</li> --}}
</ul>
</div>
{{-- BREEDER MAP --}}
{{-- FIXME: uncomment when breeder map feature is ready --}}
{{-- <li>
<a data-bs-toggle="tooltip" href="{{ route('bo.general_settings.edit', $breederMapSettingModel) }}"
title="{{ __('crud.helpers.update_model', ['model' => $breederMapSettingModel->type->label()]) }}"
@class([
'dropdown-item px-3 py-2',
'fw-bold text-bg-secondary' => url()->current() === route('bo.general_settings.edit', \App\Enums\Settings\SettingsType::breederMap->value()),
])>
<i @class([
'fa-solid fa-map-location-dot fa-fw',
'fa-lg' => url()->current() === route('bo.general_settings.edit', \App\Enums\Settings\SettingsType::breederMap->value()),
])></i>
{{ $breederMapSettingModel->type->label() }}
</a>
</li> --}}
</ul>
</div>
@endif
{{-- ACTUALITES --}}
<div class="dropdown">
<button data-bs-toggle="dropdown" type="button" aria-expanded="false" @class([
'btn btn-primary text-start w-100 dropdown-toggle mt-1',
'fw-bold active' =>
request()->routeIs('bo.news.*') ||
url()->current() ===
route(
'bo.static_pages.edit',
$newsStaticPageModel->type->value()) ||
request()->routeIs('bo.news_categories.*'),
])>
<i @class([
'fa-solid fa-newspaper fa-fw',
'fa-lg' =>
@if(isset($newsStaticPageModel))
<div class="dropdown">
<button data-bs-toggle="dropdown" type="button" aria-expanded="false" @class([
'btn btn-primary text-start w-100 dropdown-toggle mt-1',
'fw-bold active' =>
request()->routeIs('bo.news.*') ||
url()->current() ===
route(
'bo.static_pages.edit',
$newsStaticPageModel->type->value()) ||
request()->routeIs('bo.news_categories.*'),
])></i>
{{ __('Actualités') }}
</button>
<ul class="dropdown-menu">
{{-- ACTUS PAGE STATIC --}}
<li>
<a href="{{ route('bo.static_pages.edit', $newsStaticPageModel) }}" @class([
'dropdown-item px-3 py-2',
'fw-bold text-bg-secondary' =>
])>
<i @class([
'fa-solid fa-newspaper fa-fw',
'fa-lg' =>
request()->routeIs('bo.news.*') ||
url()->current() ===
route('bo.static_pages.edit', $newsStaticPageModel->type->value()),
])>
<i @class([
'fa-solid fa-file fa-fw',
'fa-lg' =>
route(
'bo.static_pages.edit',
$newsStaticPageModel->type->value()) ||
request()->routeIs('bo.news_categories.*'),
])></i>
{{ __('Actualités') }}
</button>
<ul class="dropdown-menu">
{{-- ACTUS PAGE STATIC --}}
<li>
<a href="{{ route('bo.static_pages.edit', $newsStaticPageModel) }}" @class([
'dropdown-item px-3 py-2',
'fw-bold text-bg-secondary' =>
url()->current() ===
route('bo.static_pages.edit', $newsStaticPageModel->type->value()),
])></i>
{{ str(__('Page Actualités'))->ucFirst() }}
</a>
</li>
{{-- ACTUS LE GAULOIS --}}
<li>
<a href="{{ route('bo.news.index') }}" @class([
'dropdown-item px-3 py-2',
'fw-bold text-bg-secondary' => request()->routeIs('bo.news.*'),
])>
<i @class([
'fa-solid fa-newspaper fa-fw',
'fa-lg' => request()->routeIs('bo.news.*'),
])></i>
{{ str(__('Actus le Gaulois'))->ucFirst() }}
</a>
</li>
{{-- ACTUS CATEGORY --}}
<li>
<a href="{{ route('bo.news_categories.index') }}" @class([
'dropdown-item px-3 py-2',
'fw-bold text-bg-secondary' => request()->routeIs('bo.news_categories.*'),
])>
<i @class([
'fa-solid fa-tags fa-fw',
'fa-lg' => request()->routeIs('bo.news_categories.*'),
])></i>
{{ str(__('Catégories des actualités'))->ucFirst() }}
</a>
</li>
</ul>
</div>
])>
<i @class([
'fa-solid fa-file fa-fw',
'fa-lg' =>
url()->current() ===
route('bo.static_pages.edit', $newsStaticPageModel->type->value()),
])></i>
{{ str(__('Page Actualités'))->ucFirst() }}
</a>
</li>
{{-- ACTUS LE GAULOIS --}}
<li>
<a href="{{ route('bo.news.index') }}" @class([
'dropdown-item px-3 py-2',
'fw-bold text-bg-secondary' => request()->routeIs('bo.news.*'),
])>
<i @class([
'fa-solid fa-newspaper fa-fw',
'fa-lg' => request()->routeIs('bo.news.*'),
])></i>
{{ str(__('Actus le Gaulois'))->ucFirst() }}
</a>
</li>
{{-- ACTUS CATEGORY --}}
<li>
<a href="{{ route('bo.news_categories.index') }}" @class([
'dropdown-item px-3 py-2',
'fw-bold text-bg-secondary' => request()->routeIs('bo.news_categories.*'),
])>
<i @class([
'fa-solid fa-tags fa-fw',
'fa-lg' => request()->routeIs('bo.news_categories.*'),
])></i>
{{ str(__('Catégories des actualités'))->ucFirst() }}
</a>
</li>
</ul>
</div>
@endif
{{-- CLUB --}}
<div class="dropdown">
<button data-bs-toggle="dropdown" type="button" aria-expanded="false" @class([
@ -1109,98 +1113,108 @@
</div>
<hr>
{{-- CONTACT --}}
<a data-bs-toggle="tooltip" href="{{ route('bo.static_pages.edit', $contactStaticPageModel) }}"
title="{{ __('crud.helpers.update_model', ['model' => $contactStaticPageModel->type->label()]) }}" role="button"
@class([
'btn btn-primary w-100 text-start',
'fw-bold active' =>
url()->current() ===
route('bo.static_pages.edit', $contactStaticPageModel->type->value()),
])>
<i @class([
'fa-solid fa-file fa-fw',
'fa-lg' =>
url()->current() ===
route('bo.static_pages.edit', $contactStaticPageModel->type->value()),
])></i>
{{ __($contactStaticPageModel->type->label()) }}
</a>
@if(isset($contactStaticPageModel))
<a data-bs-toggle="tooltip" href="{{ route('bo.static_pages.edit', $contactStaticPageModel) }}"
title="{{ __('crud.helpers.update_model', ['model' => $contactStaticPageModel->type->label()]) }}" role="button"
@class([
'btn btn-primary w-100 text-start',
'fw-bold active' =>
url()->current() ===
route('bo.static_pages.edit', $contactStaticPageModel->type->value()),
])>
<i @class([
'fa-solid fa-file fa-fw',
'fa-lg' =>
url()->current() ===
route('bo.static_pages.edit', $contactStaticPageModel->type->value()),
])></i>
{{ __($contactStaticPageModel->type->label()) }}
</a>
@endif
{{-- LEGALS CGU --}}
<a data-bs-toggle="tooltip" href="{{ route('bo.static_pages.edit', $legalsStaticPageModel) }}"
title="{{ __('crud.helpers.update_model', ['model' => $legalsStaticPageModel->type->label()]) }}" role="button"
@class([
'btn btn-primary w-100 text-start mt-1',
'fw-bold active' =>
url()->current() ===
route('bo.static_pages.edit', $legalsStaticPageModel->type->value()),
])>
<i @class([
'fa-solid fa-file fa-fw',
'fa-lg' =>
url()->current() ===
route('bo.static_pages.edit', $legalsStaticPageModel->type->value()),
])></i>
{{ __($legalsStaticPageModel->type->label()) }}
</a>
@if(isset($legalsStaticPageModel))
<a data-bs-toggle="tooltip" href="{{ route('bo.static_pages.edit', $legalsStaticPageModel) }}"
title="{{ __('crud.helpers.update_model', ['model' => $legalsStaticPageModel->type->label()]) }}" role="button"
@class([
'btn btn-primary w-100 text-start mt-1',
'fw-bold active' =>
url()->current() ===
route('bo.static_pages.edit', $legalsStaticPageModel->type->value()),
])>
<i @class([
'fa-solid fa-file fa-fw',
'fa-lg' =>
url()->current() ===
route('bo.static_pages.edit', $legalsStaticPageModel->type->value()),
])></i>
{{ __($legalsStaticPageModel->type->label()) }}
</a>
@endif
{{-- CONFIDENTIALITY --}}
<a data-bs-toggle="tooltip" href="{{ route('bo.static_pages.edit', $confidentialityStaticPageModel) }}"
title="{{ __('crud.helpers.update_model', ['model' => $confidentialityStaticPageModel->type->label()]) }}" role="button"
@class([
'btn btn-primary w-100 text-start mt-1',
'fw-bold active' =>
url()->current() ===
route(
'bo.static_pages.edit',
$confidentialityStaticPageModel->type->value()),
])>
<i @class([
'fa-solid fa-file fa-fw',
'fa-lg' =>
url()->current() ===
route(
'bo.static_pages.edit',
$confidentialityStaticPageModel->type->value()),
])></i>
{{ __($confidentialityStaticPageModel->type->label()) }}
</a>
@if(isset($confidentialityStaticPageModel))
<a data-bs-toggle="tooltip" href="{{ route('bo.static_pages.edit', $confidentialityStaticPageModel) }}"
title="{{ __('crud.helpers.update_model', ['model' => $confidentialityStaticPageModel->type->label()]) }}" role="button"
@class([
'btn btn-primary w-100 text-start mt-1',
'fw-bold active' =>
url()->current() ===
route(
'bo.static_pages.edit',
$confidentialityStaticPageModel->type->value()),
])>
<i @class([
'fa-solid fa-file fa-fw',
'fa-lg' =>
url()->current() ===
route(
'bo.static_pages.edit',
$confidentialityStaticPageModel->type->value()),
])></i>
{{ __($confidentialityStaticPageModel->type->label()) }}
</a>
@endif
{{-- TERMS AND CONDITIONS --}}
<a data-bs-toggle="tooltip" href="{{ route('bo.static_pages.edit', $sellingStaticPageModel) }}"
title="{{ __('crud.helpers.update_model', ['model' => $sellingStaticPageModel->type->label()]) }}" role="button"
@class([
'btn btn-primary w-100 text-start mt-1',
'fw-bold active' =>
url()->current() ===
route('bo.static_pages.edit', $sellingStaticPageModel->type->value()),
])>
<i @class([
'fa-solid fa-file fa-fw',
'fa-lg' =>
url()->current() ===
route('bo.static_pages.edit', $sellingStaticPageModel->type->value()),
])></i>
{{ __($sellingStaticPageModel->type->label()) }}
</a>
@if(isset($sellingStaticPageModel))
<a data-bs-toggle="tooltip" href="{{ route('bo.static_pages.edit', $sellingStaticPageModel) }}"
title="{{ __('crud.helpers.update_model', ['model' => $sellingStaticPageModel->type->label()]) }}" role="button"
@class([
'btn btn-primary w-100 text-start mt-1',
'fw-bold active' =>
url()->current() ===
route('bo.static_pages.edit', $sellingStaticPageModel->type->value()),
])>
<i @class([
'fa-solid fa-file fa-fw',
'fa-lg' =>
url()->current() ===
route('bo.static_pages.edit', $sellingStaticPageModel->type->value()),
])></i>
{{ __($sellingStaticPageModel->type->label()) }}
</a>
@endif
{{-- ACCESSIBILITY --}}
<a data-bs-toggle="tooltip" href="{{ route('bo.static_pages.edit', $accessibilityStaticPageModel) }}"
title="{{ __('crud.helpers.update_model', ['model' => $accessibilityStaticPageModel->type->label()]) }}" role="button"
@class([
'btn btn-primary w-100 text-start mt-1',
'fw-bold active' =>
url()->current() ===
route(
'bo.static_pages.edit',
$accessibilityStaticPageModel->type->value()),
])>
<i @class([
'fa-solid fa-file fa-fw',
'fa-lg' =>
url()->current() ===
route(
'bo.static_pages.edit',
$accessibilityStaticPageModel->type->value()),
])></i>
{{ __($accessibilityStaticPageModel->type->label()) }}
</a>
@if(isset($accessibilityStaticPageModel))
<a data-bs-toggle="tooltip" href="{{ route('bo.static_pages.edit', $accessibilityStaticPageModel) }}"
title="{{ __('crud.helpers.update_model', ['model' => $accessibilityStaticPageModel->type->label()]) }}" role="button"
@class([
'btn btn-primary w-100 text-start mt-1',
'fw-bold active' =>
url()->current() ===
route(
'bo.static_pages.edit',
$accessibilityStaticPageModel->type->value()),
])>
<i @class([
'fa-solid fa-file fa-fw',
'fa-lg' =>
url()->current() ===
route(
'bo.static_pages.edit',
$accessibilityStaticPageModel->type->value()),
])></i>
{{ __($accessibilityStaticPageModel->type->label()) }}
</a>
@endif
</div>
</nav>
@endauth

View file

@ -325,29 +325,29 @@
{{-- PUBLICATION DATES --}}
<div class="col-12 mb-3">
<div class="row mb-3">
{{-- PUBLISH_AT --}}
{{-- PUBLISHED_AT --}}
<div class="col">
<div class="form-group">
@include('bo.partials.inputs.timestamp-datetime', [
'label' => str(__('validation.custom.publish_at'))->ucFirst() . __(' (Europe/Paris)'),
'label' => str(__('validation.custom.published_at'))->ucFirst() . __(' (Europe/Paris)'),
'id' => 'demarcheSlidePublishedAt',
'name' => 'publish_at',
'name' => 'published_at',
'model' => $demarcheSlideModel ?? null,
'helper' => __('crud.helpers.publish_at', [
'helper' => __('crud.helpers.published_at', [
'model' => str(__('models.classes.demarche_slide'))->ucFirst(),
]),
])
</div>
</div>
{{-- UNPUBLISH_AT --}}
{{-- UNPUBLISHED_AT --}}
<div class="col">
<div class="form-group">
@include('bo.partials.inputs.timestamp-datetime', [
'label' => str(__('validation.custom.unpublish_at'))->ucfirst() . __(' (Europe/Paris)'),
'label' => str(__('validation.custom.unpublished_at'))->ucfirst() . __(' (Europe/Paris)'),
'id' => 'demarcheSlideUnPublishedAt',
'name' => 'unpublish_at',
'name' => 'unpublished_at',
'model' => $demarcheSlideModel ?? null,
'helper' => __('crud.helpers.unpublish_at', [
'helper' => __('crud.helpers.unpublished_at', [
'model' => str(__('models.classes.demarche_slide'))->ucFirst(),
]),
])

View file

@ -26,7 +26,13 @@
<span class="badge text-bg-secondary">{{ $discountModel->updated_at->isoFormat('LLLL') }}</span>
</td>
{{-- Keep empty for actions collumn --}}
<td class="text-center align-middle"></td>
<td class="text-center align-middle">
<a class="btn btn-sm btn-warning" data-bs-toggle="tooltip"
href="{{ route('bo.discounts.show', ['discount' => $discountModel]) }}"
title="{{ str(__('crud.actions.show'))->ucfirst() }}">
<i class="fa-solid fa-eye"></i>
</a>
</td>
</tr>
@endforeach
</tbody>

View file

@ -0,0 +1,82 @@
@extends('bo.layout', ['brParam' => $discountModel])
@section('title', __('Aperçu d\'une :model', ['model' => __('models.classes.claim')]))
@section('description', __('Aperçu d\'une :model déjà existante', ['model' => __('models.classes.claim')]))
@section('breadcrumb', request()->route()->getName())
@section('content')
<div class="d-flex justify-content-between flex-md-nowrap align-items-center border-bottom flex-wrap pb-3">
<div class="d-flex align-items-start flex-row">
<a class="btn btn-primary text-decoration-none m-0 me-2" data-bs-toggle="tooltip" data-bs-placement="top"
href="{{ route('bo.claims.index', ['sort_col' => 'created_at', 'sort_way' => 'desc']) }}"
title="{{ __('crud.helpers.list_all', ['model' => str(__('models.classes.claim'))->plural()]) }}">
<i class="fa-solid fa-arrow-left"></i>
</a>
@include('modules.breadcrumbs.breadcrumb-body', ['brParam' => $discountModel])
</div>
</div>
<div class="row">
<div class="col-12">
<div class="table-responsive mb-3">
<table class="table-hover m-0 table">
<tbody>
<tr class="border-bottom">
<td class="w-50 fw-bold text-center align-middle">{{ str(__('validation.attributes.name'))->ucFirst() }}</td>
<td class="w-50 text-center align-middle">
{{ $discountModel->name }}
</td>
</tr>
<tr class="border-bottom">
<td class="w-50 fw-bold text-center align-middle">{{ str(__('validation.custom.code'))->ucFirst() }}</td>
<td class="w-50 text-center align-middle">
{{ $discountModel->code }}
</td>
</tr>
<tr class="border-bottom">
<td class="w-50 fw-bold text-center align-middle">{{ str(__('validation.custom.value'))->ucFirst() }}</td>
<td class="w-50 text-center align-middle">
@money($discountModel->value)
</td>
</tr>
<tr class="border-bottom">
<td class="w-50 fw-bold text-center align-middle">{{ str(__('validation.attributes.created_at'))->ucFirst() }}</td>
<td class="w-50 text-center align-middle">
{{ str($discountModel->created_at->isoFormat('LLLL'))->ucFirst() }}
</td>
</tr>
<tr class="border-bottom">
<td class="w-50 fw-bold text-center align-middle">{{ str(__('validation.attributes.image'))->ucFirst() }}</td>
<td class="w-50 text-center align-middle">
<img class="img-fluid" src="{{ asset($discountModel->desktop_image_available) }}" alt="{{ __('Image disponible pour ordinateur') }}">
</td>
</tr>
<tr class="border-bottom">
<td class="w-50 fw-bold text-center align-middle">{{ str(__('validation.attributes.image'))->ucFirst() }}</td>
<td class="w-50 text-center align-middle">
<img class="img-fluid" src="{{ asset($discountModel->desktop_image_unavailable) }}" alt="{{ __('Image indisponible pour ordinateur') }}">
</td>
</tr>
<tr class="border-bottom">
<td class="w-50 fw-bold text-center align-middle">{{ str(__('validation.attributes.image'))->ucFirst() }}</td>
<td class="w-50 text-center align-middle">
<img class="img-fluid" src="{{ asset($discountModel->mobile_image_available) }}" alt="{{ __('Image disponible pour mobile') }}">
</td>
</tr>
<tr class="border-bottom">
<td class="w-50 fw-bold text-center align-middle">{{ str(__('validation.attributes.image'))->ucFirst() }}</td>
<td class="w-50 text-center align-middle">
<img class="img-fluid" src="{{ asset($discountModel->mobile_image_unavailable) }}" alt="{{ __('Image indisponible pour mobile') }}">
</td>
</tr>
<tr class="border-bottom">
<td class="w-50 fw-bold text-center align-middle">{{ str(__('validation.attributes.updated_at'))->ucFirst() }}</td>
<td class="w-50 text-center align-middle">
{{ str($discountModel->updated_at->isoFormat('LLLL'))->ucFirst() }}
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
@endsection

View file

@ -258,32 +258,24 @@
'preview' => true,
])
</div>
{{-- EMPLACEMENT --}}
<div class="col-12 col-md-6 mb-3">
<fieldset class="h-100 border p-3">
<legend>{{ str(__('validation.custom.emplacement'))->ucfirst() }}</legend>
<div class="row">
<div class="col-12">
@include('bo.partials.inputs.tinyint-enum', [
'id' => 'pictoPlacement',
'label' => sprintf(
'%s %s %s',
str(__('validation.custom.emplacement'))->ucfirst(),
__('validation.custom.of_the.male'),
__('validation.custom.picto')),
'name' => 'picto_placement',
'model' => $historicalMilestoneModel ?? null,
'required' => false,
'value' => $historicalMilestoneModel->picto_placement,
'associatedModels' => \App\Enums\HistoricalMilestonePosition::toArray(),
'helper' => __('crud.minicrud.select_entity', [
'entity' => sprintf('un seul et unique %s', __('validation.custom.emplacement')),
]),
])
</div>
</div>
</fieldset>
@include('bo.partials.inputs.tinyint-enum', [
'id' => 'pictoPlacement',
'label' => sprintf(
'%s %s %s',
str(__('validation.custom.emplacement'))->ucfirst(),
__('validation.custom.of_the.male'),
__('validation.custom.picto')),
'name' => 'picto_position',
'model' => $historicalMilestoneModel ?? null,
'required' => false,
'value' => $historicalMilestoneModel->picto_position,
'associatedModels' => \App\Enums\HistoricalMilestones\HistoricalMilestonePosition::toArray(),
'helper' => __('crud.minicrud.select_entity', [
'entity' => sprintf('un seul et unique %s', __('validation.custom.emplacement')),
]),
])
</div>
</div>
</fieldset>

View file

@ -555,33 +555,33 @@
{{-- PUBLICATION DATES --}}
<div class="col-12 mb-3">
<div class="row mb-3">
{{-- PUBLISH_AT --}}
{{-- PUBLISHED_AT --}}
<div class="col">
<div class="form-group">
@include('bo.partials.inputs.timestamp-datetime', [
'label' =>
str(__('validation.custom.publish_at'))->ucFirst() .
str(__('validation.custom.published_at'))->ucFirst() .
__(' (Europe/Paris)'),
'id' => 'mainSlidePublishedAt',
'name' => 'publish_at',
'name' => 'published_at',
'model' => $mainSlideModel ?? null,
'helper' => __('crud.helpers.publish_at', [
'helper' => __('crud.helpers.published_at', [
'model' => str(__('models.classes.main_slide'))->ucFirst(),
]),
])
</div>
</div>
{{-- UNPUBLISH_AT --}}
{{-- UNPUBLISHED_AT --}}
<div class="col">
<div class="form-group">
@include('bo.partials.inputs.timestamp-datetime', [
'label' =>
str(__('validation.custom.unpublish_at'))->ucfirst() .
str(__('validation.custom.unpublished_at'))->ucfirst() .
__(' (Europe/Paris)'),
'id' => 'mainSlideUnPublishedAt',
'name' => 'unpublish_at',
'name' => 'unpublished_at',
'model' => $mainSlideModel ?? null,
'helper' => __('crud.helpers.unpublish_at', [
'helper' => __('crud.helpers.unpublished_at', [
'model' => str(__('models.classes.main_slide'))->ucFirst(),
]),
])

View file

@ -53,19 +53,15 @@
{{ $mainSlideModel->title }}
</td>
</tr>
<tr class="border-bottom">
<td class="w-50 fw-bold text-center align-middle">{{ str(__('validation.attributes.text'))->ucFirst() }}</td>
<td class="w-50 text-center align-middle">
<div class="ck-content">
{!! clean($mainSlideModel->text) !!}
</div>
</td>
</tr>
<tr class="border-bottom">
<td class="w-50 fw-bold text-center align-middle">{{ str(__('validation.attributes.image'))->ucFirst() }}</td>
<td class="w-50 text-center align-middle">
<img class="img-fluid" src="{{ asset($mainSlideModel->picture) }}"
title="{{ $mainSlideModel->picture_title }}" alt="{{ $mainSlideModel->picture_alt }}">
@if($mainSlideModel->picture)
<img class="img-fluid" src="{{ asset($mainSlideModel->picture) }}"
title="{{ $mainSlideModel->picture_title }}" alt="{{ $mainSlideModel->picture_alt }}">
@else
<small class="text-body-secondary fst-italic">{{ __('Aucune image enregistrée') }}</small>
@endif
</td>
</tr>
<tr class="border-bottom">
@ -73,7 +69,7 @@
{{ str(__('validation.custom.publication'))->ucFirst() }}
</td>
<td class="w-50 text-center align-middle">
{{ $mainSlideModel->published
{{ $mainSlideModel->published_at
? str($mainSlideModel->published_at->isoFormat('LLLL'))->ucFirst()
: ($mainSlideModel->unpublished_at ?:
__('crud.other.model_not_published')) }}

View file

@ -109,8 +109,7 @@
<div class="col-12 mb-2">
<div class="form-check">
<input class="form-check-input bg-secondary-emphasis" id="info-newsletter" name="opt_in"
type="checkbox" value="{{ old('opt_in', $crmCustomer->opt_in ?? null) }}"
@checked($crmCustomer->opt_in)>
type="checkbox" @checked(old('opt_in', $crmCustomer->opt_in ?? false))>
<label class="form-check-label" for="info-newsletter">
<span class="fw-bold">
{{ __('J\'accepte de recevoir les newsletters du Club des Gaulois :') }}

View file

@ -196,7 +196,7 @@
</div>
<div class="col-7">
<div @class([
'bottom-left-shadow w-100',
'bottom-left-shadow w-fit',
$loop->iteration % 2 ? 'rotate-right' : 'rotate-left',
])>
@if (isset($historicalMilestoneModel->picto) && $historicalMilestoneModel->picto !== null)
@ -204,7 +204,7 @@
title="{{ $historicalMilestoneModel->picto_title }}"
alt="{{ $historicalMilestoneModel->picto_alt }}" @class([
'slider-picto position-absolute img-fluid z-1',
$historicalMilestoneModel->picto_placement === 'hg'
$historicalMilestoneModel->picto_position->equals(\App\Enums\HistoricalMilestones\HistoricalMilestonePosition::topLeft)
? 'slider-picto'
: 'slider-picto-reversed',
])>

View file

@ -10,6 +10,7 @@ use App\Models\Profession;
use App\Models\BrandAdvantage;
use App\Models\Claim;
use App\Models\ConsumptionMoment;
use App\Models\Discount;
use App\Models\MainSlide;
use App\Models\GeneralSetting;
use App\Models\HistoricalMilestone;
@ -748,6 +749,10 @@ Breadcrumbs::for('bo.discounts.index', function (Generator $trail) {
route('bo.discounts.index')
);
});
Breadcrumbs::for('bo.discounts.show', function (Generator $trail, Discount $discount) {
$trail->parent('bo.discounts.index');
$trail->push(Str::ucfirst(trans('crud.actions.view')), route('bo.discounts.show', $discount));
});
// * SELL ITEMS
Breadcrumbs::for('bo.sell_items.index', function (Generator $trail) {

View file

@ -546,7 +546,7 @@ Route::middleware(['throttle:web', 'admin-secure'])->prefix('bo')->name('bo.')->
])->name('surveys_answers.duplicate');
// * DISCOUNTS.
Route::get('/discounts', [DiscountController::class, 'index'])->name('discounts.index');
Route::resource('discounts', DiscountController::class);
Route::get('/discounts/update', [DiscountController::class, 'updateList'])->name('discounts.update');
// * SELL ITEMS.

View file

@ -0,0 +1,76 @@
<?php
namespace Tests\Back;
use App\Enums\Users\RoleEnum;
use App\Models\ActivityLog;
use App\Models\User as AuthModel;
use Tests\TestCase;
class ActivityLogTest extends TestCase
{
/**
* TESTS GUEST CANNOT ACCESS VIEWS.
*/
/** @return void */
public function testGuestCannotAccessActivityLogsIndexView(): void
{
$response = $this->get(route(
config('unit-tests.route.prefix') .
'activity_logs.' .
config('unit-tests.view.resources-index')
));
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotAccessActivityLogsReadView(): void
{
$model = ActivityLog::factory()->createOneQuietly();
$response = $this->get(route(
config('unit-tests.route.prefix') .
'activity_logs.' .
config('unit-tests.view.resources-read'),
$model->getKey()
));
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/**
* TESTS USER CONCEPTOR ACCESS VIEWS.
*/
/** @return void */
public function testUserConceptorCanAccessActivityLogsIndexView(): void
{
$authModel = AuthModel::factory()->createOneQuietly();
$authModel->update(['role' => RoleEnum::conceptor]);
$response = $this->actingAs($authModel, 'backend')->get(
route(config('unit-tests.route.prefix') . 'activity_logs.' . config('unit-tests.view.resources-index'))
);
$response->assertSuccessful();
$response->assertViewIs(
config('unit-tests.view.prefix') .
'pages.activity_logs.' .
config('unit-tests.view.resources-index')
);
}
/** @return void */
public function testUserConceptorCanAccessActivityLogsReadView(): void
{
$authModel = AuthModel::factory()->createOneQuietly();
$authModel->update(['role' => RoleEnum::conceptor]);
$model = ActivityLog::factory()->createOneQuietly();
$response = $this->actingAs($authModel, 'backend')->get(
route(config('unit-tests.route.prefix') . 'activity_logs.' . config('unit-tests.view.resources-read'), $model)
);
$response->assertSuccessful();
$response->assertViewIs(
config('unit-tests.view.prefix') .
'pages.activity_logs.' .
config('unit-tests.view.resources-read')
);
}
}

View file

@ -0,0 +1,227 @@
<?php
namespace Tests\Back;
use App\Enums\Approaches\ApproachTypeEnum;
use App\Enums\Users\RoleEnum;
use App\Models\Approach;
use App\Models\User as AuthModel;
use Illuminate\Support\Facades\Schema;
use Tests\TestCase;
class ApproachDemarcheTest extends TestCase
{
/**
* TESTS GUEST CANNOT ACCESS VIEWS.
*/
/** @return void */
public function testGuestCannotAccessApproachsIndexView(): void
{
$response = $this->get(route(
config('unit-tests.route.prefix') .
'approaches.' .
config('unit-tests.view.resources-index'),
['approach_type' => ApproachTypeEnum::demarche->value()]
));
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotAccessApproachsReadView(): void
{
$model = Approach::factory()->createOneQuietly();
$response = $this->get(route(
config('unit-tests.route.prefix') .
'approaches.' .
config('unit-tests.view.resources-read'),
$model->getKey()
));
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotAccessApproachsCreateView(): void
{
$response = $this->get(route(
config('unit-tests.route.prefix') .
'approaches.' .
config('unit-tests.view.resources-create'),
['approach_type' => ApproachTypeEnum::demarche->value()]
));
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotAccessApproachsUpdateView(): void
{
$model = Approach::factory()->createOneQuietly();
$response = $this->get(route(
config('unit-tests.route.prefix') .
'approaches.' .
config('unit-tests.view.resources-update'),
$model->getKey()
));
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/**
* TESTS GUEST CANNOT POST MODEL.
*/
/** @return void */
public function testGuestCannotCreateApproach(): void
{
$model = Approach::factory()->createOneQuietly();
$response = $this->post(
route(
config('unit-tests.route.prefix') . 'approaches.' . config('unit-tests.route.action-create'),
$model->getKey()
),
$model->toArray()
);
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotUpdateApproach(): void
{
$model = Approach::factory()->createOneQuietly();
$response = $this->patch(
route(
config('unit-tests.route.prefix') . 'approaches.' . config('unit-tests.route.action-update'),
$model->getKey()
),
$model->toArray()
);
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotDeleteApproach(): void
{
$model = Approach::factory()->createOneQuietly();
$response = $this->delete(
route(
config('unit-tests.route.prefix') . 'approaches.' . config('unit-tests.route.action-delete'),
$model->getKey()
),
$model->toArray()
);
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/**
* TESTS USER CONCEPTOR ACCESS VIEWS.
*/
/** @return void */
public function testUserConceptorCanAccessApproachsIndexView(): void
{
$authModel = AuthModel::factory()->createOneQuietly();
$authModel->update(['role' => RoleEnum::conceptor]);
$response = $this->actingAs($authModel, 'backend')->get(
route(
config('unit-tests.route.prefix') . 'approaches.' . config('unit-tests.view.resources-index'),
['approach_type' => ApproachTypeEnum::demarche->value()]
)
);
$response->assertSuccessful();
$response->assertViewIs(
config('unit-tests.view.prefix') .
'pages.approaches.' .
config('unit-tests.view.resources-index')
);
}
/** @return void */
public function testUserConceptorCanAccessApproachsReadView(): void
{
$authModel = AuthModel::factory()->createOneQuietly();
$authModel->update(['role' => RoleEnum::conceptor]);
$model = Approach::factory()->createOneQuietly();
$response = $this->actingAs($authModel, 'backend')->get(
route(config('unit-tests.route.prefix') . 'approaches.' . config('unit-tests.view.resources-read'), $model)
);
$response->assertSuccessful();
$response->assertViewIs(
config('unit-tests.view.prefix') .
'pages.approaches.' .
config('unit-tests.view.resources-read')
);
}
/** @return void */
public function testUserConceptorCanAccessApproachsCreateView(): void
{
$authModel = AuthModel::factory()->createOneQuietly();
$authModel->update(['role' => RoleEnum::conceptor]);
$response = $this->actingAs($authModel, 'backend')->get(
route(
config('unit-tests.route.prefix') . 'approaches.' . config('unit-tests.view.resources-create'),
['approach_type' => ApproachTypeEnum::demarche->value()]
)
);
$response->assertSuccessful();
$response->assertViewIs(
config('unit-tests.view.prefix') .
'pages.approaches.' .
config('unit-tests.view.resources-create')
);
}
/** @return void */
public function testUserConceptorCanAccessApproachsUpdateView(): void
{
$authModel = AuthModel::factory()->createOneQuietly();
$authModel->update(['role' => RoleEnum::conceptor]);
$model = Approach::factory()->createOneQuietly();
$response = $this->actingAs($authModel, 'backend')->get(
route(config('unit-tests.route.prefix') . 'approaches.' . config('unit-tests.view.resources-update'), $model)
);
$response->assertSuccessful();
$response->assertViewIs(
config('unit-tests.view.prefix') .
'pages.approaches.' .
config('unit-tests.view.resources-update')
);
}
/**
* TESTS CAN ACTIONS ON MODEL.
*/
/** @return void */
public function testCanCreateApproach(): void
{
$model = Approach::factory()->createOneQuietly();
$this->assertModelExists($model);
}
/** @return void */
public function testCanUpdateApproach(): void
{
$model = Approach::factory()->createOneQuietly();
$fieldTest = "";
foreach (config('unit-tests.list-fields') as $field) {
if (Schema::hasColumn($model->getTable(), $field)) {
$model->update([$field => "test"]);
$fieldTest = $field;
break;
}
}
$this->assertTrue($model->wasChanged());
$this->assertTrue(array_key_exists($fieldTest, $model->getChanges()));
$this->assertModelExists($model);
}
/** @return void */
public function testCanDeleteApproach(): void
{
$model = Approach::factory()->createOneQuietly();
$model->delete();
$this->assertModelMissing($model);
}
}

View file

@ -0,0 +1,227 @@
<?php
namespace Tests\Back;
use App\Enums\Approaches\ApproachTypeEnum;
use App\Enums\Users\RoleEnum;
use App\Models\Approach;
use App\Models\User as AuthModel;
use Illuminate\Support\Facades\Schema;
use Tests\TestCase;
class ApproachLabelTest extends TestCase
{
/**
* TESTS GUEST CANNOT ACCESS VIEWS.
*/
/** @return void */
public function testGuestCannotAccessApproachsIndexView(): void
{
$response = $this->get(route(
config('unit-tests.route.prefix') .
'approaches.' .
config('unit-tests.view.resources-index'),
['approach_type' => ApproachTypeEnum::label->value()]
));
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotAccessApproachsReadView(): void
{
$model = Approach::factory()->createOneQuietly();
$response = $this->get(route(
config('unit-tests.route.prefix') .
'approaches.' .
config('unit-tests.view.resources-read'),
$model->getKey()
));
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotAccessApproachsCreateView(): void
{
$response = $this->get(route(
config('unit-tests.route.prefix') .
'approaches.' .
config('unit-tests.view.resources-create'),
['approach_type' => ApproachTypeEnum::label->value()]
));
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotAccessApproachsUpdateView(): void
{
$model = Approach::factory()->createOneQuietly();
$response = $this->get(route(
config('unit-tests.route.prefix') .
'approaches.' .
config('unit-tests.view.resources-update'),
$model->getKey()
));
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/**
* TESTS GUEST CANNOT POST MODEL.
*/
/** @return void */
public function testGuestCannotCreateApproach(): void
{
$model = Approach::factory()->createOneQuietly();
$response = $this->post(
route(
config('unit-tests.route.prefix') . 'approaches.' . config('unit-tests.route.action-create'),
$model->getKey()
),
$model->toArray()
);
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotUpdateApproach(): void
{
$model = Approach::factory()->createOneQuietly();
$response = $this->patch(
route(
config('unit-tests.route.prefix') . 'approaches.' . config('unit-tests.route.action-update'),
$model->getKey()
),
$model->toArray()
);
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotDeleteApproach(): void
{
$model = Approach::factory()->createOneQuietly();
$response = $this->delete(
route(
config('unit-tests.route.prefix') . 'approaches.' . config('unit-tests.route.action-delete'),
$model->getKey()
),
$model->toArray()
);
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/**
* TESTS USER CONCEPTOR ACCESS VIEWS.
*/
/** @return void */
public function testUserConceptorCanAccessApproachsIndexView(): void
{
$authModel = AuthModel::factory()->createOneQuietly();
$authModel->update(['role' => RoleEnum::conceptor]);
$response = $this->actingAs($authModel, 'backend')->get(
route(
config('unit-tests.route.prefix') . 'approaches.' . config('unit-tests.view.resources-index'),
['approach_type' => ApproachTypeEnum::label->value()]
)
);
$response->assertSuccessful();
$response->assertViewIs(
config('unit-tests.view.prefix') .
'pages.approaches.' .
config('unit-tests.view.resources-index')
);
}
/** @return void */
public function testUserConceptorCanAccessApproachsReadView(): void
{
$authModel = AuthModel::factory()->createOneQuietly();
$authModel->update(['role' => RoleEnum::conceptor]);
$model = Approach::factory()->createOneQuietly();
$response = $this->actingAs($authModel, 'backend')->get(
route(config('unit-tests.route.prefix') . 'approaches.' . config('unit-tests.view.resources-read'), $model)
);
$response->assertSuccessful();
$response->assertViewIs(
config('unit-tests.view.prefix') .
'pages.approaches.' .
config('unit-tests.view.resources-read')
);
}
/** @return void */
public function testUserConceptorCanAccessApproachsCreateView(): void
{
$authModel = AuthModel::factory()->createOneQuietly();
$authModel->update(['role' => RoleEnum::conceptor]);
$response = $this->actingAs($authModel, 'backend')->get(
route(
config('unit-tests.route.prefix') . 'approaches.' . config('unit-tests.view.resources-create'),
['approach_type' => ApproachTypeEnum::label->value()]
)
);
$response->assertSuccessful();
$response->assertViewIs(
config('unit-tests.view.prefix') .
'pages.approaches.' .
config('unit-tests.view.resources-create')
);
}
/** @return void */
public function testUserConceptorCanAccessApproachsUpdateView(): void
{
$authModel = AuthModel::factory()->createOneQuietly();
$authModel->update(['role' => RoleEnum::conceptor]);
$model = Approach::factory()->createOneQuietly();
$response = $this->actingAs($authModel, 'backend')->get(
route(config('unit-tests.route.prefix') . 'approaches.' . config('unit-tests.view.resources-update'), $model)
);
$response->assertSuccessful();
$response->assertViewIs(
config('unit-tests.view.prefix') .
'pages.approaches.' .
config('unit-tests.view.resources-update')
);
}
/**
* TESTS CAN ACTIONS ON MODEL.
*/
/** @return void */
public function testCanCreateApproach(): void
{
$model = Approach::factory()->createOneQuietly();
$this->assertModelExists($model);
}
/** @return void */
public function testCanUpdateApproach(): void
{
$model = Approach::factory()->createOneQuietly();
$fieldTest = "";
foreach (config('unit-tests.list-fields') as $field) {
if (Schema::hasColumn($model->getTable(), $field)) {
$model->update([$field => "test"]);
$fieldTest = $field;
break;
}
}
$this->assertTrue($model->wasChanged());
$this->assertTrue(array_key_exists($fieldTest, $model->getChanges()));
$this->assertModelExists($model);
}
/** @return void */
public function testCanDeleteApproach(): void
{
$model = Approach::factory()->createOneQuietly();
$model->delete();
$this->assertModelMissing($model);
}
}

View file

@ -0,0 +1,218 @@
<?php
namespace Tests\Back;
use App\Enums\Users\RoleEnum;
use App\Models\BrandAdvantage;
use App\Models\User as AuthModel;
use Illuminate\Support\Facades\Schema;
use Tests\TestCase;
class BrandAdvantageTest extends TestCase
{
/**
* TESTS GUEST CANNOT ACCESS VIEWS.
*/
/** @return void */
public function testGuestCannotAccessBrandAdvantagesIndexView(): void
{
$response = $this->get(route(
config('unit-tests.route.prefix') .
'brand_advantages.' .
config('unit-tests.view.resources-index')
));
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotAccessBrandAdvantagesReadView(): void
{
$model = BrandAdvantage::factory()->createOneQuietly();
$response = $this->get(route(
config('unit-tests.route.prefix') .
'brand_advantages.' .
config('unit-tests.view.resources-read'),
$model->getKey()
));
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotAccessBrandAdvantagesCreateView(): void
{
$response = $this->get(route(
config('unit-tests.route.prefix') .
'brand_advantages.' .
config('unit-tests.view.resources-create')
));
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotAccessBrandAdvantagesUpdateView(): void
{
$model = BrandAdvantage::factory()->createOneQuietly();
$response = $this->get(route(
config('unit-tests.route.prefix') .
'brand_advantages.' .
config('unit-tests.view.resources-update'),
$model->getKey()
));
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/**
* TESTS GUEST CANNOT POST MODEL.
*/
/** @return void */
public function testGuestCannotCreateBrandAdvantage(): void
{
$model = BrandAdvantage::factory()->createOneQuietly();
$response = $this->post(
route(
config('unit-tests.route.prefix') . 'brand_advantages.' . config('unit-tests.route.action-create'),
$model->getKey()
),
$model->toArray()
);
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotUpdateBrandAdvantage(): void
{
$model = BrandAdvantage::factory()->createOneQuietly();
$response = $this->patch(
route(
config('unit-tests.route.prefix') . 'brand_advantages.' . config('unit-tests.route.action-update'),
$model->getKey()
),
$model->toArray()
);
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotDeleteBrandAdvantage(): void
{
$model = BrandAdvantage::factory()->createOneQuietly();
$response = $this->delete(
route(
config('unit-tests.route.prefix') . 'brand_advantages.' . config('unit-tests.route.action-delete'),
$model->getKey()
),
$model->toArray()
);
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/**
* TESTS USER CONCEPTOR ACCESS VIEWS.
*/
/** @return void */
public function testUserConceptorCanAccessBrandAdvantagesIndexView(): void
{
$authModel = AuthModel::factory()->createOneQuietly();
$authModel->update(['role' => RoleEnum::conceptor]);
$response = $this->actingAs($authModel, 'backend')->get(
route(config('unit-tests.route.prefix') . 'brand_advantages.' . config('unit-tests.view.resources-index'))
);
$response->assertSuccessful();
$response->assertViewIs(
config('unit-tests.view.prefix') .
'pages.brand_advantages.' .
config('unit-tests.view.resources-index')
);
}
/** @return void */
public function testUserConceptorCanAccessBrandAdvantagesReadView(): void
{
$authModel = AuthModel::factory()->createOneQuietly();
$authModel->update(['role' => RoleEnum::conceptor]);
$model = BrandAdvantage::factory()->createOneQuietly();
$response = $this->actingAs($authModel, 'backend')->get(
route(config('unit-tests.route.prefix') . 'brand_advantages.' . config('unit-tests.view.resources-read'), $model)
);
$response->assertSuccessful();
$response->assertViewIs(
config('unit-tests.view.prefix') .
'pages.brand_advantages.' .
config('unit-tests.view.resources-read')
);
}
/** @return void */
public function testUserConceptorCanAccessBrandAdvantagesCreateView(): void
{
$authModel = AuthModel::factory()->createOneQuietly();
$authModel->update(['role' => RoleEnum::conceptor]);
$response = $this->actingAs($authModel, 'backend')->get(
route(config('unit-tests.route.prefix') . 'brand_advantages.' . config('unit-tests.view.resources-create'))
);
$response->assertSuccessful();
$response->assertViewIs(
config('unit-tests.view.prefix') .
'pages.brand_advantages.' .
config('unit-tests.view.resources-create')
);
}
/** @return void */
public function testUserConceptorCanAccessBrandAdvantagesUpdateView(): void
{
$authModel = AuthModel::factory()->createOneQuietly();
$authModel->update(['role' => RoleEnum::conceptor]);
$model = BrandAdvantage::factory()->createOneQuietly();
$response = $this->actingAs($authModel, 'backend')->get(
route(config('unit-tests.route.prefix') . 'brand_advantages.' . config('unit-tests.view.resources-update'), $model)
);
$response->assertSuccessful();
$response->assertViewIs(
config('unit-tests.view.prefix') .
'pages.brand_advantages.' .
config('unit-tests.view.resources-update')
);
}
/**
* TESTS CAN ACTIONS ON MODEL.
*/
/** @return void */
public function testCanCreateBrandAdvantage(): void
{
$model = BrandAdvantage::factory()->createOneQuietly();
$this->assertModelExists($model);
}
/** @return void */
public function testCanUpdateBrandAdvantage(): void
{
$model = BrandAdvantage::factory()->createOneQuietly();
$fieldTest = "";
foreach (config('unit-tests.list-fields') as $field) {
if (Schema::hasColumn($model->getTable(), $field)) {
$model->update([$field => "test"]);
$fieldTest = $field;
break;
}
}
$this->assertTrue($model->wasChanged());
$this->assertTrue(array_key_exists($fieldTest, $model->getChanges()));
$this->assertModelExists($model);
}
/** @return void */
public function testCanDeleteBrandAdvantage(): void
{
$model = BrandAdvantage::factory()->createOneQuietly();
$model->delete();
$this->assertModelMissing($model);
}
}

218
tests/Back/ClaimTest.php Normal file
View file

@ -0,0 +1,218 @@
<?php
namespace Tests\Back;
use App\Enums\Users\RoleEnum;
use App\Models\Claim;
use App\Models\User as AuthModel;
use Illuminate\Support\Facades\Schema;
use Tests\TestCase;
class ClaimTest extends TestCase
{
/**
* TESTS GUEST CANNOT ACCESS VIEWS.
*/
/** @return void */
public function testGuestCannotAccessClaimsIndexView(): void
{
$response = $this->get(route(
config('unit-tests.route.prefix') .
'claims.' .
config('unit-tests.view.resources-index')
));
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotAccessClaimsReadView(): void
{
$model = Claim::factory()->createOneQuietly();
$response = $this->get(route(
config('unit-tests.route.prefix') .
'claims.' .
config('unit-tests.view.resources-read'),
$model->getKey()
));
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotAccessClaimsCreateView(): void
{
$response = $this->get(route(
config('unit-tests.route.prefix') .
'claims.' .
config('unit-tests.view.resources-create')
));
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotAccessClaimsUpdateView(): void
{
$model = Claim::factory()->createOneQuietly();
$response = $this->get(route(
config('unit-tests.route.prefix') .
'claims.' .
config('unit-tests.view.resources-update'),
$model->getKey()
));
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/**
* TESTS GUEST CANNOT POST MODEL.
*/
/** @return void */
public function testGuestCannotCreateClaim(): void
{
$model = Claim::factory()->createOneQuietly();
$response = $this->post(
route(
config('unit-tests.route.prefix') . 'claims.' . config('unit-tests.route.action-create'),
$model->getKey()
),
$model->toArray()
);
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotUpdateClaim(): void
{
$model = Claim::factory()->createOneQuietly();
$response = $this->patch(
route(
config('unit-tests.route.prefix') . 'claims.' . config('unit-tests.route.action-update'),
$model->getKey()
),
$model->toArray()
);
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotDeleteClaim(): void
{
$model = Claim::factory()->createOneQuietly();
$response = $this->delete(
route(
config('unit-tests.route.prefix') . 'claims.' . config('unit-tests.route.action-delete'),
$model->getKey()
),
$model->toArray()
);
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/**
* TESTS USER CONCEPTOR ACCESS VIEWS.
*/
/** @return void */
public function testUserConceptorCanAccessClaimsIndexView(): void
{
$authModel = AuthModel::factory()->createOneQuietly();
$authModel->update(['role' => RoleEnum::conceptor]);
$response = $this->actingAs($authModel, 'backend')->get(
route(config('unit-tests.route.prefix') . 'claims.' . config('unit-tests.view.resources-index'))
);
$response->assertSuccessful();
$response->assertViewIs(
config('unit-tests.view.prefix') .
'pages.claims.' .
config('unit-tests.view.resources-index')
);
}
/** @return void */
public function testUserConceptorCanAccessClaimsReadView(): void
{
$authModel = AuthModel::factory()->createOneQuietly();
$authModel->update(['role' => RoleEnum::conceptor]);
$model = Claim::factory()->createOneQuietly();
$response = $this->actingAs($authModel, 'backend')->get(
route(config('unit-tests.route.prefix') . 'claims.' . config('unit-tests.view.resources-read'), $model)
);
$response->assertSuccessful();
$response->assertViewIs(
config('unit-tests.view.prefix') .
'pages.claims.' .
config('unit-tests.view.resources-read')
);
}
/** @return void */
public function testUserConceptorCanAccessClaimsCreateView(): void
{
$authModel = AuthModel::factory()->createOneQuietly();
$authModel->update(['role' => RoleEnum::conceptor]);
$response = $this->actingAs($authModel, 'backend')->get(
route(config('unit-tests.route.prefix') . 'claims.' . config('unit-tests.view.resources-create'))
);
$response->assertSuccessful();
$response->assertViewIs(
config('unit-tests.view.prefix') .
'pages.claims.' .
config('unit-tests.view.resources-create')
);
}
/** @return void */
public function testUserConceptorCanAccessClaimsUpdateView(): void
{
$authModel = AuthModel::factory()->createOneQuietly();
$authModel->update(['role' => RoleEnum::conceptor]);
$model = Claim::factory()->createOneQuietly();
$response = $this->actingAs($authModel, 'backend')->get(
route(config('unit-tests.route.prefix') . 'claims.' . config('unit-tests.view.resources-update'), $model)
);
$response->assertSuccessful();
$response->assertViewIs(
config('unit-tests.view.prefix') .
'pages.claims.' .
config('unit-tests.view.resources-update')
);
}
/**
* TESTS CAN ACTIONS ON MODEL.
*/
/** @return void */
public function testCanCreateClaim(): void
{
$model = Claim::factory()->createOneQuietly();
$this->assertModelExists($model);
}
/** @return void */
public function testCanUpdateClaim(): void
{
$model = Claim::factory()->createOneQuietly();
$fieldTest = "";
foreach (config('unit-tests.list-fields') as $field) {
if (Schema::hasColumn($model->getTable(), $field)) {
$model->update([$field => "test"]);
$fieldTest = $field;
break;
}
}
$this->assertTrue($model->wasChanged());
$this->assertTrue(array_key_exists($fieldTest, $model->getChanges()));
$this->assertModelExists($model);
}
/** @return void */
public function testCanDeleteClaim(): void
{
$model = Claim::factory()->createOneQuietly();
$model->delete();
$this->assertModelMissing($model);
}
}

View file

@ -0,0 +1,218 @@
<?php
namespace Tests\Back;
use App\Enums\Users\RoleEnum;
use App\Models\ConsumptionMoment;
use App\Models\User as AuthModel;
use Illuminate\Support\Facades\Schema;
use Tests\TestCase;
class ConsumptionMomentTest extends TestCase
{
/**
* TESTS GUEST CANNOT ACCESS VIEWS.
*/
/** @return void */
public function testGuestCannotAccessConsumptionMomentsIndexView(): void
{
$response = $this->get(route(
config('unit-tests.route.prefix') .
'consumption_moments.' .
config('unit-tests.view.resources-index')
));
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotAccessConsumptionMomentsReadView(): void
{
$model = ConsumptionMoment::factory()->createOneQuietly();
$response = $this->get(route(
config('unit-tests.route.prefix') .
'consumption_moments.' .
config('unit-tests.view.resources-read'),
$model->getKey()
));
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotAccessConsumptionMomentsCreateView(): void
{
$response = $this->get(route(
config('unit-tests.route.prefix') .
'consumption_moments.' .
config('unit-tests.view.resources-create')
));
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotAccessConsumptionMomentsUpdateView(): void
{
$model = ConsumptionMoment::factory()->createOneQuietly();
$response = $this->get(route(
config('unit-tests.route.prefix') .
'consumption_moments.' .
config('unit-tests.view.resources-update'),
$model->getKey()
));
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/**
* TESTS GUEST CANNOT POST MODEL.
*/
/** @return void */
public function testGuestCannotCreateConsumptionMoment(): void
{
$model = ConsumptionMoment::factory()->createOneQuietly();
$response = $this->post(
route(
config('unit-tests.route.prefix') . 'consumption_moments.' . config('unit-tests.route.action-create'),
$model->getKey()
),
$model->toArray()
);
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotUpdateConsumptionMoment(): void
{
$model = ConsumptionMoment::factory()->createOneQuietly();
$response = $this->patch(
route(
config('unit-tests.route.prefix') . 'consumption_moments.' . config('unit-tests.route.action-update'),
$model->getKey()
),
$model->toArray()
);
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotDeleteConsumptionMoment(): void
{
$model = ConsumptionMoment::factory()->createOneQuietly();
$response = $this->delete(
route(
config('unit-tests.route.prefix') . 'consumption_moments.' . config('unit-tests.route.action-delete'),
$model->getKey()
),
$model->toArray()
);
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/**
* TESTS USER CONCEPTOR ACCESS VIEWS.
*/
/** @return void */
public function testUserConceptorCanAccessConsumptionMomentsIndexView(): void
{
$authModel = AuthModel::factory()->createOneQuietly();
$authModel->update(['role' => RoleEnum::conceptor]);
$response = $this->actingAs($authModel, 'backend')->get(
route(config('unit-tests.route.prefix') . 'consumption_moments.' . config('unit-tests.view.resources-index'))
);
$response->assertSuccessful();
$response->assertViewIs(
config('unit-tests.view.prefix') .
'pages.consumption_moments.' .
config('unit-tests.view.resources-index')
);
}
/** @return void */
public function testUserConceptorCanAccessConsumptionMomentsReadView(): void
{
$authModel = AuthModel::factory()->createOneQuietly();
$authModel->update(['role' => RoleEnum::conceptor]);
$model = ConsumptionMoment::factory()->createOneQuietly();
$response = $this->actingAs($authModel, 'backend')->get(
route(config('unit-tests.route.prefix') . 'consumption_moments.' . config('unit-tests.view.resources-read'), $model)
);
$response->assertSuccessful();
$response->assertViewIs(
config('unit-tests.view.prefix') .
'pages.consumption_moments.' .
config('unit-tests.view.resources-read')
);
}
/** @return void */
public function testUserConceptorCanAccessConsumptionMomentsCreateView(): void
{
$authModel = AuthModel::factory()->createOneQuietly();
$authModel->update(['role' => RoleEnum::conceptor]);
$response = $this->actingAs($authModel, 'backend')->get(
route(config('unit-tests.route.prefix') . 'consumption_moments.' . config('unit-tests.view.resources-create'))
);
$response->assertSuccessful();
$response->assertViewIs(
config('unit-tests.view.prefix') .
'pages.consumption_moments.' .
config('unit-tests.view.resources-create')
);
}
/** @return void */
public function testUserConceptorCanAccessConsumptionMomentsUpdateView(): void
{
$authModel = AuthModel::factory()->createOneQuietly();
$authModel->update(['role' => RoleEnum::conceptor]);
$model = ConsumptionMoment::factory()->createOneQuietly();
$response = $this->actingAs($authModel, 'backend')->get(
route(config('unit-tests.route.prefix') . 'consumption_moments.' . config('unit-tests.view.resources-update'), $model)
);
$response->assertSuccessful();
$response->assertViewIs(
config('unit-tests.view.prefix') .
'pages.consumption_moments.' .
config('unit-tests.view.resources-update')
);
}
/**
* TESTS CAN ACTIONS ON MODEL.
*/
/** @return void */
public function testCanCreateConsumptionMoment(): void
{
$model = ConsumptionMoment::factory()->createOneQuietly();
$this->assertModelExists($model);
}
/** @return void */
public function testCanUpdateConsumptionMoment(): void
{
$model = ConsumptionMoment::factory()->createOneQuietly();
$fieldTest = "";
foreach (config('unit-tests.list-fields') as $field) {
if (Schema::hasColumn($model->getTable(), $field)) {
$model->update([$field => "test"]);
$fieldTest = $field;
break;
}
}
$this->assertTrue($model->wasChanged());
$this->assertTrue(array_key_exists($fieldTest, $model->getChanges()));
$this->assertModelExists($model);
}
/** @return void */
public function testCanDeleteConsumptionMoment(): void
{
$model = ConsumptionMoment::factory()->createOneQuietly();
$model->delete();
$this->assertModelMissing($model);
}
}

View file

@ -0,0 +1,218 @@
<?php
namespace Tests\Back;
use App\Enums\Users\RoleEnum;
use App\Models\DemarcheSlide;
use App\Models\User as AuthModel;
use Illuminate\Support\Facades\Schema;
use Tests\TestCase;
class DemarcheSlideTest extends TestCase
{
/**
* TESTS GUEST CANNOT ACCESS VIEWS.
*/
/** @return void */
public function testGuestCannotAccessDemarcheSlidesIndexView(): void
{
$response = $this->get(route(
config('unit-tests.route.prefix') .
'demarche_slides.' .
config('unit-tests.view.resources-index')
));
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotAccessDemarcheSlidesReadView(): void
{
$model = DemarcheSlide::factory()->createOneQuietly();
$response = $this->get(route(
config('unit-tests.route.prefix') .
'demarche_slides.' .
config('unit-tests.view.resources-read'),
$model->getKey()
));
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotAccessDemarcheSlidesCreateView(): void
{
$response = $this->get(route(
config('unit-tests.route.prefix') .
'demarche_slides.' .
config('unit-tests.view.resources-create')
));
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotAccessDemarcheSlidesUpdateView(): void
{
$model = DemarcheSlide::factory()->createOneQuietly();
$response = $this->get(route(
config('unit-tests.route.prefix') .
'demarche_slides.' .
config('unit-tests.view.resources-update'),
$model->getKey()
));
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/**
* TESTS GUEST CANNOT POST MODEL.
*/
/** @return void */
public function testGuestCannotCreateDemarcheSlide(): void
{
$model = DemarcheSlide::factory()->createOneQuietly();
$response = $this->post(
route(
config('unit-tests.route.prefix') . 'demarche_slides.' . config('unit-tests.route.action-create'),
$model->getKey()
),
$model->toArray()
);
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotUpdateDemarcheSlide(): void
{
$model = DemarcheSlide::factory()->createOneQuietly();
$response = $this->patch(
route(
config('unit-tests.route.prefix') . 'demarche_slides.' . config('unit-tests.route.action-update'),
$model->getKey()
),
$model->toArray()
);
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotDeleteDemarcheSlide(): void
{
$model = DemarcheSlide::factory()->createOneQuietly();
$response = $this->delete(
route(
config('unit-tests.route.prefix') . 'demarche_slides.' . config('unit-tests.route.action-delete'),
$model->getKey()
),
$model->toArray()
);
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/**
* TESTS USER CONCEPTOR ACCESS VIEWS.
*/
/** @return void */
public function testUserConceptorCanAccessDemarcheSlidesIndexView(): void
{
$authModel = AuthModel::factory()->createOneQuietly();
$authModel->update(['role' => RoleEnum::conceptor]);
$response = $this->actingAs($authModel, 'backend')->get(
route(config('unit-tests.route.prefix') . 'demarche_slides.' . config('unit-tests.view.resources-index'))
);
$response->assertSuccessful();
$response->assertViewIs(
config('unit-tests.view.prefix') .
'pages.demarche_slides.' .
config('unit-tests.view.resources-index')
);
}
/** @return void */
public function testUserConceptorCanAccessDemarcheSlidesReadView(): void
{
$authModel = AuthModel::factory()->createOneQuietly();
$authModel->update(['role' => RoleEnum::conceptor]);
$model = DemarcheSlide::factory()->createOneQuietly();
$response = $this->actingAs($authModel, 'backend')->get(
route(config('unit-tests.route.prefix') . 'demarche_slides.' . config('unit-tests.view.resources-read'), $model)
);
$response->assertSuccessful();
$response->assertViewIs(
config('unit-tests.view.prefix') .
'pages.demarche_slides.' .
config('unit-tests.view.resources-read')
);
}
/** @return void */
public function testUserConceptorCanAccessDemarcheSlidesCreateView(): void
{
$authModel = AuthModel::factory()->createOneQuietly();
$authModel->update(['role' => RoleEnum::conceptor]);
$response = $this->actingAs($authModel, 'backend')->get(
route(config('unit-tests.route.prefix') . 'demarche_slides.' . config('unit-tests.view.resources-create'))
);
$response->assertSuccessful();
$response->assertViewIs(
config('unit-tests.view.prefix') .
'pages.demarche_slides.' .
config('unit-tests.view.resources-create')
);
}
/** @return void */
public function testUserConceptorCanAccessDemarcheSlidesUpdateView(): void
{
$authModel = AuthModel::factory()->createOneQuietly();
$authModel->update(['role' => RoleEnum::conceptor]);
$model = DemarcheSlide::factory()->createOneQuietly();
$response = $this->actingAs($authModel, 'backend')->get(
route(config('unit-tests.route.prefix') . 'demarche_slides.' . config('unit-tests.view.resources-update'), $model)
);
$response->assertSuccessful();
$response->assertViewIs(
config('unit-tests.view.prefix') .
'pages.demarche_slides.' .
config('unit-tests.view.resources-update')
);
}
/**
* TESTS CAN ACTIONS ON MODEL.
*/
/** @return void */
public function testCanCreateDemarcheSlide(): void
{
$model = DemarcheSlide::factory()->createOneQuietly();
$this->assertModelExists($model);
}
/** @return void */
public function testCanUpdateDemarcheSlide(): void
{
$model = DemarcheSlide::factory()->createOneQuietly();
$fieldTest = "";
foreach (config('unit-tests.list-fields') as $field) {
if (Schema::hasColumn($model->getTable(), $field)) {
$model->update([$field => "test"]);
$fieldTest = $field;
break;
}
}
$this->assertTrue($model->wasChanged());
$this->assertTrue(array_key_exists($fieldTest, $model->getChanges()));
$this->assertModelExists($model);
}
/** @return void */
public function testCanDeleteDemarcheSlide(): void
{
$model = DemarcheSlide::factory()->createOneQuietly();
$model->delete();
$this->assertModelMissing($model);
}
}

View file

@ -0,0 +1,76 @@
<?php
namespace Tests\Back;
use App\Enums\Users\RoleEnum;
use App\Models\Discount;
use App\Models\User as AuthModel;
use Tests\TestCase;
class DiscountTest extends TestCase
{
/**
* TESTS GUEST CANNOT ACCESS VIEWS.
*/
/** @return void */
public function testGuestCannotAccessDiscountsIndexView(): void
{
$response = $this->get(route(
config('unit-tests.route.prefix') .
'discounts.' .
config('unit-tests.view.resources-index')
));
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotAccessDiscountsReadView(): void
{
$model = Discount::factory()->createOneQuietly();
$response = $this->get(route(
config('unit-tests.route.prefix') .
'discounts.' .
config('unit-tests.view.resources-read'),
$model->getKey()
));
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/**
* TESTS USER CONCEPTOR ACCESS VIEWS.
*/
/** @return void */
public function testUserConceptorCanAccessDiscountsIndexView(): void
{
$authModel = AuthModel::factory()->createOneQuietly();
$authModel->update(['role' => RoleEnum::conceptor]);
$response = $this->actingAs($authModel, 'backend')->get(
route(config('unit-tests.route.prefix') . 'discounts.' . config('unit-tests.view.resources-index'))
);
$response->assertSuccessful();
$response->assertViewIs(
config('unit-tests.view.prefix') .
'pages.discounts.' .
config('unit-tests.view.resources-index')
);
}
/** @return void */
public function testUserConceptorCanAccessDiscountsReadView(): void
{
$authModel = AuthModel::factory()->createOneQuietly();
$authModel->update(['role' => RoleEnum::conceptor]);
$model = Discount::factory()->createOneQuietly();
$response = $this->actingAs($authModel, 'backend')->get(
route(config('unit-tests.route.prefix') . 'discounts.' . config('unit-tests.view.resources-read'), $model)
);
$response->assertSuccessful();
$response->assertViewIs(
config('unit-tests.view.prefix') .
'pages.discounts.' .
config('unit-tests.view.resources-read')
);
}
}

View file

@ -0,0 +1,218 @@
<?php
namespace Tests\Back;
use App\Enums\Users\RoleEnum;
use App\Models\HistoricalMilestone;
use App\Models\User as AuthModel;
use Illuminate\Support\Facades\Schema;
use Tests\TestCase;
class HistoricalMilestoneTest extends TestCase
{
/**
* TESTS GUEST CANNOT ACCESS VIEWS.
*/
/** @return void */
public function testGuestCannotAccessHistoricalMilestonesIndexView(): void
{
$response = $this->get(route(
config('unit-tests.route.prefix') .
'historical_milestones.' .
config('unit-tests.view.resources-index')
));
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotAccessHistoricalMilestonesReadView(): void
{
$model = HistoricalMilestone::factory()->createOneQuietly();
$response = $this->get(route(
config('unit-tests.route.prefix') .
'historical_milestones.' .
config('unit-tests.view.resources-read'),
$model->getKey()
));
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotAccessHistoricalMilestonesCreateView(): void
{
$response = $this->get(route(
config('unit-tests.route.prefix') .
'historical_milestones.' .
config('unit-tests.view.resources-create')
));
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotAccessHistoricalMilestonesUpdateView(): void
{
$model = HistoricalMilestone::factory()->createOneQuietly();
$response = $this->get(route(
config('unit-tests.route.prefix') .
'historical_milestones.' .
config('unit-tests.view.resources-update'),
$model->getKey()
));
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/**
* TESTS GUEST CANNOT POST MODEL.
*/
/** @return void */
public function testGuestCannotCreateHistoricalMilestone(): void
{
$model = HistoricalMilestone::factory()->createOneQuietly();
$response = $this->post(
route(
config('unit-tests.route.prefix') . 'historical_milestones.' . config('unit-tests.route.action-create'),
$model->getKey()
),
$model->toArray()
);
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotUpdateHistoricalMilestone(): void
{
$model = HistoricalMilestone::factory()->createOneQuietly();
$response = $this->patch(
route(
config('unit-tests.route.prefix') . 'historical_milestones.' . config('unit-tests.route.action-update'),
$model->getKey()
),
$model->toArray()
);
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotDeleteHistoricalMilestone(): void
{
$model = HistoricalMilestone::factory()->createOneQuietly();
$response = $this->delete(
route(
config('unit-tests.route.prefix') . 'historical_milestones.' . config('unit-tests.route.action-delete'),
$model->getKey()
),
$model->toArray()
);
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/**
* TESTS USER CONCEPTOR ACCESS VIEWS.
*/
/** @return void */
public function testUserConceptorCanAccessHistoricalMilestonesIndexView(): void
{
$authModel = AuthModel::factory()->createOneQuietly();
$authModel->update(['role' => RoleEnum::conceptor]);
$response = $this->actingAs($authModel, 'backend')->get(
route(config('unit-tests.route.prefix') . 'historical_milestones.' . config('unit-tests.view.resources-index'))
);
$response->assertSuccessful();
$response->assertViewIs(
config('unit-tests.view.prefix') .
'pages.historical_milestones.' .
config('unit-tests.view.resources-index')
);
}
/** @return void */
public function testUserConceptorCanAccessHistoricalMilestonesReadView(): void
{
$authModel = AuthModel::factory()->createOneQuietly();
$authModel->update(['role' => RoleEnum::conceptor]);
$model = HistoricalMilestone::factory()->createOneQuietly();
$response = $this->actingAs($authModel, 'backend')->get(
route(config('unit-tests.route.prefix') . 'historical_milestones.' . config('unit-tests.view.resources-read'), $model)
);
$response->assertSuccessful();
$response->assertViewIs(
config('unit-tests.view.prefix') .
'pages.historical_milestones.' .
config('unit-tests.view.resources-read')
);
}
/** @return void */
public function testUserConceptorCanAccessHistoricalMilestonesCreateView(): void
{
$authModel = AuthModel::factory()->createOneQuietly();
$authModel->update(['role' => RoleEnum::conceptor]);
$response = $this->actingAs($authModel, 'backend')->get(
route(config('unit-tests.route.prefix') . 'historical_milestones.' . config('unit-tests.view.resources-create'))
);
$response->assertSuccessful();
$response->assertViewIs(
config('unit-tests.view.prefix') .
'pages.historical_milestones.' .
config('unit-tests.view.resources-create')
);
}
/** @return void */
public function testUserConceptorCanAccessHistoricalMilestonesUpdateView(): void
{
$authModel = AuthModel::factory()->createOneQuietly();
$authModel->update(['role' => RoleEnum::conceptor]);
$model = HistoricalMilestone::factory()->createOneQuietly();
$response = $this->actingAs($authModel, 'backend')->get(
route(config('unit-tests.route.prefix') . 'historical_milestones.' . config('unit-tests.view.resources-update'), $model)
);
$response->assertSuccessful();
$response->assertViewIs(
config('unit-tests.view.prefix') .
'pages.historical_milestones.' .
config('unit-tests.view.resources-update')
);
}
/**
* TESTS CAN ACTIONS ON MODEL.
*/
/** @return void */
public function testCanCreateHistoricalMilestone(): void
{
$model = HistoricalMilestone::factory()->createOneQuietly();
$this->assertModelExists($model);
}
/** @return void */
public function testCanUpdateHistoricalMilestone(): void
{
$model = HistoricalMilestone::factory()->createOneQuietly();
$fieldTest = "";
foreach (config('unit-tests.list-fields') as $field) {
if (Schema::hasColumn($model->getTable(), $field)) {
$model->update([$field => "test"]);
$fieldTest = $field;
break;
}
}
$this->assertTrue($model->wasChanged());
$this->assertTrue(array_key_exists($fieldTest, $model->getChanges()));
$this->assertModelExists($model);
}
/** @return void */
public function testCanDeleteHistoricalMilestone(): void
{
$model = HistoricalMilestone::factory()->createOneQuietly();
$model->delete();
$this->assertModelMissing($model);
}
}

View file

@ -0,0 +1,218 @@
<?php
namespace Tests\Back;
use App\Enums\Users\RoleEnum;
use App\Models\KeyNumber;
use App\Models\User as AuthModel;
use Illuminate\Support\Facades\Schema;
use Tests\TestCase;
class KeyNumberTest extends TestCase
{
/**
* TESTS GUEST CANNOT ACCESS VIEWS.
*/
/** @return void */
public function testGuestCannotAccessKeyNumbersIndexView(): void
{
$response = $this->get(route(
config('unit-tests.route.prefix') .
'key_numbers.' .
config('unit-tests.view.resources-index')
));
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotAccessKeyNumbersReadView(): void
{
$model = KeyNumber::factory()->createOneQuietly();
$response = $this->get(route(
config('unit-tests.route.prefix') .
'key_numbers.' .
config('unit-tests.view.resources-read'),
$model->getKey()
));
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotAccessKeyNumbersCreateView(): void
{
$response = $this->get(route(
config('unit-tests.route.prefix') .
'key_numbers.' .
config('unit-tests.view.resources-create')
));
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotAccessKeyNumbersUpdateView(): void
{
$model = KeyNumber::factory()->createOneQuietly();
$response = $this->get(route(
config('unit-tests.route.prefix') .
'key_numbers.' .
config('unit-tests.view.resources-update'),
$model->getKey()
));
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/**
* TESTS GUEST CANNOT POST MODEL.
*/
/** @return void */
public function testGuestCannotCreateKeyNumber(): void
{
$model = KeyNumber::factory()->createOneQuietly();
$response = $this->post(
route(
config('unit-tests.route.prefix') . 'key_numbers.' . config('unit-tests.route.action-create'),
$model->getKey()
),
$model->toArray()
);
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotUpdateKeyNumber(): void
{
$model = KeyNumber::factory()->createOneQuietly();
$response = $this->patch(
route(
config('unit-tests.route.prefix') . 'key_numbers.' . config('unit-tests.route.action-update'),
$model->getKey()
),
$model->toArray()
);
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotDeleteKeyNumber(): void
{
$model = KeyNumber::factory()->createOneQuietly();
$response = $this->delete(
route(
config('unit-tests.route.prefix') . 'key_numbers.' . config('unit-tests.route.action-delete'),
$model->getKey()
),
$model->toArray()
);
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/**
* TESTS USER CONCEPTOR ACCESS VIEWS.
*/
/** @return void */
public function testUserConceptorCanAccessKeyNumbersIndexView(): void
{
$authModel = AuthModel::factory()->createOneQuietly();
$authModel->update(['role' => RoleEnum::conceptor]);
$response = $this->actingAs($authModel, 'backend')->get(
route(config('unit-tests.route.prefix') . 'key_numbers.' . config('unit-tests.view.resources-index'))
);
$response->assertSuccessful();
$response->assertViewIs(
config('unit-tests.view.prefix') .
'pages.key_numbers.' .
config('unit-tests.view.resources-index')
);
}
/** @return void */
public function testUserConceptorCanAccessKeyNumbersReadView(): void
{
$authModel = AuthModel::factory()->createOneQuietly();
$authModel->update(['role' => RoleEnum::conceptor]);
$model = KeyNumber::factory()->createOneQuietly();
$response = $this->actingAs($authModel, 'backend')->get(
route(config('unit-tests.route.prefix') . 'key_numbers.' . config('unit-tests.view.resources-read'), $model)
);
$response->assertSuccessful();
$response->assertViewIs(
config('unit-tests.view.prefix') .
'pages.key_numbers.' .
config('unit-tests.view.resources-read')
);
}
/** @return void */
public function testUserConceptorCanAccessKeyNumbersCreateView(): void
{
$authModel = AuthModel::factory()->createOneQuietly();
$authModel->update(['role' => RoleEnum::conceptor]);
$response = $this->actingAs($authModel, 'backend')->get(
route(config('unit-tests.route.prefix') . 'key_numbers.' . config('unit-tests.view.resources-create'))
);
$response->assertSuccessful();
$response->assertViewIs(
config('unit-tests.view.prefix') .
'pages.key_numbers.' .
config('unit-tests.view.resources-create')
);
}
/** @return void */
public function testUserConceptorCanAccessKeyNumbersUpdateView(): void
{
$authModel = AuthModel::factory()->createOneQuietly();
$authModel->update(['role' => RoleEnum::conceptor]);
$model = KeyNumber::factory()->createOneQuietly();
$response = $this->actingAs($authModel, 'backend')->get(
route(config('unit-tests.route.prefix') . 'key_numbers.' . config('unit-tests.view.resources-update'), $model)
);
$response->assertSuccessful();
$response->assertViewIs(
config('unit-tests.view.prefix') .
'pages.key_numbers.' .
config('unit-tests.view.resources-update')
);
}
/**
* TESTS CAN ACTIONS ON MODEL.
*/
/** @return void */
public function testCanCreateKeyNumber(): void
{
$model = KeyNumber::factory()->createOneQuietly();
$this->assertModelExists($model);
}
/** @return void */
public function testCanUpdateKeyNumber(): void
{
$model = KeyNumber::factory()->createOneQuietly();
$fieldTest = "";
foreach (config('unit-tests.list-fields') as $field) {
if (Schema::hasColumn($model->getTable(), $field)) {
$model->update([$field => "test"]);
$fieldTest = $field;
break;
}
}
$this->assertTrue($model->wasChanged());
$this->assertTrue(array_key_exists($fieldTest, $model->getChanges()));
$this->assertModelExists($model);
}
/** @return void */
public function testCanDeleteKeyNumber(): void
{
$model = KeyNumber::factory()->createOneQuietly();
$model->delete();
$this->assertModelMissing($model);
}
}

View file

@ -0,0 +1,218 @@
<?php
namespace Tests\Back;
use App\Enums\Users\RoleEnum;
use App\Models\MainSlide;
use App\Models\User as AuthModel;
use Illuminate\Support\Facades\Schema;
use Tests\TestCase;
class MainSlideTest extends TestCase
{
/**
* TESTS GUEST CANNOT ACCESS VIEWS.
*/
/** @return void */
public function testGuestCannotAccessMainSlidesIndexView(): void
{
$response = $this->get(route(
config('unit-tests.route.prefix') .
'main_slides.' .
config('unit-tests.view.resources-index')
));
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotAccessMainSlidesReadView(): void
{
$model = MainSlide::factory()->createOneQuietly();
$response = $this->get(route(
config('unit-tests.route.prefix') .
'main_slides.' .
config('unit-tests.view.resources-read'),
$model->getKey()
));
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotAccessMainSlidesCreateView(): void
{
$response = $this->get(route(
config('unit-tests.route.prefix') .
'main_slides.' .
config('unit-tests.view.resources-create')
));
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotAccessMainSlidesUpdateView(): void
{
$model = MainSlide::factory()->createOneQuietly();
$response = $this->get(route(
config('unit-tests.route.prefix') .
'main_slides.' .
config('unit-tests.view.resources-update'),
$model->getKey()
));
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/**
* TESTS GUEST CANNOT POST MODEL.
*/
/** @return void */
public function testGuestCannotCreateMainSlide(): void
{
$model = MainSlide::factory()->createOneQuietly();
$response = $this->post(
route(
config('unit-tests.route.prefix') . 'main_slides.' . config('unit-tests.route.action-create'),
$model->getKey()
),
$model->toArray()
);
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotUpdateMainSlide(): void
{
$model = MainSlide::factory()->createOneQuietly();
$response = $this->patch(
route(
config('unit-tests.route.prefix') . 'main_slides.' . config('unit-tests.route.action-update'),
$model->getKey()
),
$model->toArray()
);
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/** @return void */
public function testGuestCannotDeleteMainSlide(): void
{
$model = MainSlide::factory()->createOneQuietly();
$response = $this->delete(
route(
config('unit-tests.route.prefix') . 'main_slides.' . config('unit-tests.route.action-delete'),
$model->getKey()
),
$model->toArray()
);
$response->assertRedirect(route(config('unit-tests.route.prefix') . 'login'));
}
/**
* TESTS USER CONCEPTOR ACCESS VIEWS.
*/
/** @return void */
public function testUserConceptorCanAccessMainSlidesIndexView(): void
{
$authModel = AuthModel::factory()->createOneQuietly();
$authModel->update(['role' => RoleEnum::conceptor]);
$response = $this->actingAs($authModel, 'backend')->get(
route(config('unit-tests.route.prefix') . 'main_slides.' . config('unit-tests.view.resources-index'))
);
$response->assertSuccessful();
$response->assertViewIs(
config('unit-tests.view.prefix') .
'pages.main_slides.' .
config('unit-tests.view.resources-index')
);
}
/** @return void */
public function testUserConceptorCanAccessMainSlidesReadView(): void
{
$authModel = AuthModel::factory()->createOneQuietly();
$authModel->update(['role' => RoleEnum::conceptor]);
$model = MainSlide::factory()->createOneQuietly();
$response = $this->actingAs($authModel, 'backend')->get(
route(config('unit-tests.route.prefix') . 'main_slides.' . config('unit-tests.view.resources-read'), $model)
);
$response->assertSuccessful();
$response->assertViewIs(
config('unit-tests.view.prefix') .
'pages.main_slides.' .
config('unit-tests.view.resources-read')
);
}
/** @return void */
public function testUserConceptorCanAccessMainSlidesCreateView(): void
{
$authModel = AuthModel::factory()->createOneQuietly();
$authModel->update(['role' => RoleEnum::conceptor]);
$response = $this->actingAs($authModel, 'backend')->get(
route(config('unit-tests.route.prefix') . 'main_slides.' . config('unit-tests.view.resources-create'))
);
$response->assertSuccessful();
$response->assertViewIs(
config('unit-tests.view.prefix') .
'pages.main_slides.' .
config('unit-tests.view.resources-create')
);
}
/** @return void */
public function testUserConceptorCanAccessMainSlidesUpdateView(): void
{
$authModel = AuthModel::factory()->createOneQuietly();
$authModel->update(['role' => RoleEnum::conceptor]);
$model = MainSlide::factory()->createOneQuietly();
$response = $this->actingAs($authModel, 'backend')->get(
route(config('unit-tests.route.prefix') . 'main_slides.' . config('unit-tests.view.resources-update'), $model)
);
$response->assertSuccessful();
$response->assertViewIs(
config('unit-tests.view.prefix') .
'pages.main_slides.' .
config('unit-tests.view.resources-update')
);
}
/**
* TESTS CAN ACTIONS ON MODEL.
*/
/** @return void */
public function testCanCreateMainSlide(): void
{
$model = MainSlide::factory()->createOneQuietly();
$this->assertModelExists($model);
}
/** @return void */
public function testCanUpdateMainSlide(): void
{
$model = MainSlide::factory()->createOneQuietly();
$fieldTest = "";
foreach (config('unit-tests.list-fields') as $field) {
if (Schema::hasColumn($model->getTable(), $field)) {
$model->update([$field => "test"]);
$fieldTest = $field;
break;
}
}
$this->assertTrue($model->wasChanged());
$this->assertTrue(array_key_exists($fieldTest, $model->getChanges()));
$this->assertModelExists($model);
}
/** @return void */
public function testCanDeleteMainSlide(): void
{
$model = MainSlide::factory()->createOneQuietly();
$model->delete();
$this->assertModelMissing($model);
}
}

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