ADD delivery calendar part2
This commit is contained in:
parent
1753871799
commit
e31f33d9bf
28
app/Enums/OverrideScope.php
Normal file
28
app/Enums/OverrideScope.php
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Enums;
|
||||||
|
|
||||||
|
enum OverrideScope: string
|
||||||
|
{
|
||||||
|
case General = 'general'; // Általános – adott beszállítóra, minden régióra és profitcenterre
|
||||||
|
case Region = 'region'; // Régió-specifikus – adott régióra vonatkozó felülbírálás
|
||||||
|
case ProfitCenter = 'profit_center'; // Profitcenter-specifikus – csak 1 konkrét profitcenterre
|
||||||
|
|
||||||
|
public function label(): string
|
||||||
|
{
|
||||||
|
return match($this) {
|
||||||
|
self::General => 'Általános (minden telephely)',
|
||||||
|
self::Region => 'Régió-specifikus',
|
||||||
|
self::ProfitCenter => 'Profitcenter-specifikus',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public function color(): string
|
||||||
|
{
|
||||||
|
return match($this) {
|
||||||
|
self::General => 'gray',
|
||||||
|
self::Region => 'warning',
|
||||||
|
self::ProfitCenter => 'info',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,10 +2,12 @@
|
|||||||
|
|
||||||
namespace App\Filament\Resources\DeliveryCalendarOverrides\Schemas;
|
namespace App\Filament\Resources\DeliveryCalendarOverrides\Schemas;
|
||||||
|
|
||||||
|
use App\Enums\OverrideScope;
|
||||||
use Filament\Forms\Components\DatePicker;
|
use Filament\Forms\Components\DatePicker;
|
||||||
use Filament\Forms\Components\Select;
|
use Filament\Forms\Components\Select;
|
||||||
use Filament\Forms\Components\TextInput;
|
use Filament\Forms\Components\TextInput;
|
||||||
use Filament\Forms\Components\Toggle;
|
use Filament\Forms\Components\Toggle;
|
||||||
|
use Filament\Schemas\Components\Utilities\Get;
|
||||||
use Filament\Schemas\Schema;
|
use Filament\Schemas\Schema;
|
||||||
|
|
||||||
class DeliveryCalendarOverrideForm
|
class DeliveryCalendarOverrideForm
|
||||||
@ -19,6 +21,26 @@ public static function configure(Schema $schema): Schema
|
|||||||
->relationship('supplier', 'name')
|
->relationship('supplier', 'name')
|
||||||
->searchable()
|
->searchable()
|
||||||
->required(),
|
->required(),
|
||||||
|
Select::make('override_scope')
|
||||||
|
->label('Felülbírálás szintje')
|
||||||
|
->options(collect(OverrideScope::cases())->mapWithKeys(
|
||||||
|
fn(OverrideScope $scope) => [$scope->value => $scope->label()]
|
||||||
|
))
|
||||||
|
->default(OverrideScope::General->value)
|
||||||
|
->required()
|
||||||
|
->live(),
|
||||||
|
Select::make('delivery_schedule_id')
|
||||||
|
->label('Szállítási sablon')
|
||||||
|
->relationship('deliverySchedule', 'name')
|
||||||
|
->searchable()
|
||||||
|
->visible(fn(Get $get) => $get('override_scope') === OverrideScope::Region->value)
|
||||||
|
->required(fn(Get $get) => $get('override_scope') === OverrideScope::Region->value),
|
||||||
|
Select::make('profit_center_id')
|
||||||
|
->label('Profitcenter')
|
||||||
|
->relationship('profitCenter', 'name')
|
||||||
|
->searchable()
|
||||||
|
->visible(fn(Get $get) => $get('override_scope') === OverrideScope::ProfitCenter->value)
|
||||||
|
->required(fn(Get $get) => $get('override_scope') === OverrideScope::ProfitCenter->value),
|
||||||
DatePicker::make('date')
|
DatePicker::make('date')
|
||||||
->label('Dátum')
|
->label('Dátum')
|
||||||
->required()
|
->required()
|
||||||
|
|||||||
@ -2,11 +2,15 @@
|
|||||||
|
|
||||||
namespace App\Filament\Resources\DeliveryCalendarOverrides\Tables;
|
namespace App\Filament\Resources\DeliveryCalendarOverrides\Tables;
|
||||||
|
|
||||||
|
use App\Enums\OverrideScope;
|
||||||
use Filament\Actions\BulkActionGroup;
|
use Filament\Actions\BulkActionGroup;
|
||||||
use Filament\Actions\DeleteBulkAction;
|
use Filament\Actions\DeleteBulkAction;
|
||||||
use Filament\Actions\EditAction;
|
use Filament\Actions\EditAction;
|
||||||
use Filament\Actions\ForceDeleteBulkAction;
|
use Filament\Actions\ForceDeleteBulkAction;
|
||||||
use Filament\Actions\RestoreBulkAction;
|
use Filament\Actions\RestoreBulkAction;
|
||||||
|
use Filament\Tables\Columns\IconColumn;
|
||||||
|
use Filament\Tables\Columns\TextColumn;
|
||||||
|
use Filament\Tables\Filters\SelectFilter;
|
||||||
use Filament\Tables\Filters\TrashedFilter;
|
use Filament\Tables\Filters\TrashedFilter;
|
||||||
use Filament\Tables\Table;
|
use Filament\Tables\Table;
|
||||||
|
|
||||||
@ -16,22 +20,42 @@ public static function configure(Table $table): Table
|
|||||||
{
|
{
|
||||||
return $table
|
return $table
|
||||||
->columns([
|
->columns([
|
||||||
\Filament\Tables\Columns\TextColumn::make('supplier.name')
|
TextColumn::make('supplier.name')
|
||||||
->label('Beszállító')
|
->label('Beszállító')
|
||||||
->searchable()
|
->searchable()
|
||||||
->sortable(),
|
->sortable(),
|
||||||
\Filament\Tables\Columns\TextColumn::make('date')
|
TextColumn::make('override_scope')
|
||||||
->label('Dátum')
|
->label('Szint')
|
||||||
->date()
|
->badge()
|
||||||
|
->formatStateUsing(fn(OverrideScope $state) => $state->label())
|
||||||
|
->color(fn(OverrideScope $state) => $state->color())
|
||||||
->sortable(),
|
->sortable(),
|
||||||
\Filament\Tables\Columns\IconColumn::make('is_delivery_day')
|
TextColumn::make('deliverySchedule.name')
|
||||||
|
->label('Szállítási sablon')
|
||||||
|
->placeholder('—')
|
||||||
|
->toggleable(),
|
||||||
|
TextColumn::make('profitCenter.name')
|
||||||
|
->label('Profitcenter')
|
||||||
|
->placeholder('—')
|
||||||
|
->toggleable(),
|
||||||
|
TextColumn::make('date')
|
||||||
|
->label('Dátum')
|
||||||
|
->date('Y-m-d')
|
||||||
|
->sortable(),
|
||||||
|
IconColumn::make('is_delivery_day')
|
||||||
->boolean()
|
->boolean()
|
||||||
->label('Szállítási nap'),
|
->label('Szállítási nap'),
|
||||||
\Filament\Tables\Columns\TextColumn::make('description')
|
TextColumn::make('description')
|
||||||
->label('Megjegyzés')
|
->label('Megjegyzés')
|
||||||
->limit(30),
|
->limit(30)
|
||||||
|
->toggleable(isToggledHiddenByDefault: true),
|
||||||
])
|
])
|
||||||
->filters([
|
->filters([
|
||||||
|
SelectFilter::make('override_scope')
|
||||||
|
->label('Felülbírálás szintje')
|
||||||
|
->options(collect(OverrideScope::cases())->mapWithKeys(
|
||||||
|
fn(OverrideScope $scope) => [$scope->value => $scope->label()]
|
||||||
|
)),
|
||||||
TrashedFilter::make(),
|
TrashedFilter::make(),
|
||||||
])
|
])
|
||||||
->recordActions([
|
->recordActions([
|
||||||
|
|||||||
342
app/Filament/Widgets/DeliveryCalendarWidget.php
Normal file
342
app/Filament/Widgets/DeliveryCalendarWidget.php
Normal file
@ -0,0 +1,342 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Filament\Widgets;
|
||||||
|
|
||||||
|
use App\Enums\OverrideScope;
|
||||||
|
use App\Models\ProfitCenterSupplierSchedule;
|
||||||
|
use App\Models\DeliveryCalendarOverride;
|
||||||
|
use App\Models\WorkCalendar;
|
||||||
|
use App\Enums\WorkDayType;
|
||||||
|
use App\Services\DeliveryCalendarService;
|
||||||
|
use App\Services\WorkCalendarService;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
use Saade\FilamentFullCalendar\Widgets\FullCalendarWidget;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Filament\Actions\Action;
|
||||||
|
use Filament\Forms\Components\Hidden;
|
||||||
|
use Filament\Forms\Components\Placeholder;
|
||||||
|
use Filament\Forms\Components\Toggle;
|
||||||
|
use Filament\Forms\Components\TextInput;
|
||||||
|
|
||||||
|
class DeliveryCalendarWidget extends FullCalendarWidget
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var ProfitCenterSupplierSchedule|null
|
||||||
|
*/
|
||||||
|
public Model | int | string | null $record = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inaktív (nem választható) napok listája.
|
||||||
|
*
|
||||||
|
* @var array<string>
|
||||||
|
*/
|
||||||
|
protected array $inactiveDates = [];
|
||||||
|
|
||||||
|
public function mount(): void
|
||||||
|
{
|
||||||
|
if (!$this->record) {
|
||||||
|
$this->record = ProfitCenterSupplierSchedule::first();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function fetchEvents(array $info): array
|
||||||
|
{
|
||||||
|
if (!$this->record) {
|
||||||
|
$this->record = ProfitCenterSupplierSchedule::first();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$this->record) {
|
||||||
|
return $this->getDemoEvents($info);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var DeliveryCalendarService $service */
|
||||||
|
$service = app(DeliveryCalendarService::class);
|
||||||
|
/** @var WorkCalendarService $workService */
|
||||||
|
$workService = app(WorkCalendarService::class);
|
||||||
|
|
||||||
|
$start = Carbon::parse($info['start']);
|
||||||
|
$end = Carbon::parse($info['end']);
|
||||||
|
|
||||||
|
$events = [];
|
||||||
|
|
||||||
|
// 1. Szállítási napok – zöld háttér
|
||||||
|
$deliveryDates = $service->getAvailableDeliveryDates(
|
||||||
|
$this->record->profitCenter,
|
||||||
|
$this->record->supplier,
|
||||||
|
$start,
|
||||||
|
$end
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ($deliveryDates as $date) {
|
||||||
|
$events[] = [
|
||||||
|
'id' => 'delivery-' . $date->format('Y-m-d'),
|
||||||
|
'title' => '',
|
||||||
|
'start' => $date->format('Y-m-d'),
|
||||||
|
'end' => $date->addDay()->format('Y-m-d'),
|
||||||
|
'allDay' => true,
|
||||||
|
'display' => 'background',
|
||||||
|
'backgroundColor' => '#4CAF50',
|
||||||
|
'extendedProps' => ['type' => 'delivery'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Munkaszüneti napok – piros háttér
|
||||||
|
$workCalendarEntries = $workService->getCalendarEntries($start, $end);
|
||||||
|
foreach ($workCalendarEntries as $entry) {
|
||||||
|
if ($entry->type === WorkDayType::Holiday) {
|
||||||
|
$events[] = [
|
||||||
|
'id' => 'holiday-' . $entry->date->format('Y-m-d'),
|
||||||
|
'title' => '',
|
||||||
|
'start' => $entry->date->format('Y-m-d'),
|
||||||
|
'end' => $entry->date->copy()->addDay()->format('Y-m-d'),
|
||||||
|
'allDay' => true,
|
||||||
|
'display' => 'background',
|
||||||
|
'backgroundColor' => '#EF4444',
|
||||||
|
'extendedProps' => ['type' => 'holiday'],
|
||||||
|
];
|
||||||
|
} elseif ($entry->type === WorkDayType::WorkingDay) {
|
||||||
|
// 3. Áthelyezett munkanapok – narancssárga háttér
|
||||||
|
$events[] = [
|
||||||
|
'id' => 'transferred-' . $entry->date->format('Y-m-d'),
|
||||||
|
'title' => '',
|
||||||
|
'start' => $entry->date->format('Y-m-d'),
|
||||||
|
'end' => $entry->date->copy()->addDay()->format('Y-m-d'),
|
||||||
|
'allDay' => true,
|
||||||
|
'display' => 'background',
|
||||||
|
'backgroundColor' => '#F59E0B',
|
||||||
|
'extendedProps' => ['type' => 'transferred'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. Hétvégék – szürke háttér (inaktív napok)
|
||||||
|
$current = $start->copy();
|
||||||
|
while ($current->lte($end)) {
|
||||||
|
if ($current->isWeekend()) {
|
||||||
|
$events[] = [
|
||||||
|
'id' => 'weekend-' . $current->format('Y-m-d'),
|
||||||
|
'title' => '',
|
||||||
|
'start' => $current->format('Y-m-d'),
|
||||||
|
'end' => $current->copy()->addDay()->format('Y-m-d'),
|
||||||
|
'allDay' => true,
|
||||||
|
'display' => 'background',
|
||||||
|
'backgroundColor' => '#E5E7EB',
|
||||||
|
'extendedProps' => ['type' => 'inactive'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
$current->addDay();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $events;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Demo események generálása, ha nincs valós adat.
|
||||||
|
*
|
||||||
|
* @param array{start: string, end: string} $info
|
||||||
|
* @return array<int, array<string, mixed>>
|
||||||
|
*/
|
||||||
|
protected function getDemoEvents(array $info): array
|
||||||
|
{
|
||||||
|
$start = Carbon::parse($info['start']);
|
||||||
|
$end = Carbon::parse($info['end']);
|
||||||
|
$events = [];
|
||||||
|
|
||||||
|
$current = $start->copy();
|
||||||
|
while ($current->lte($end)) {
|
||||||
|
$dayOfWeek = $current->dayOfWeek;
|
||||||
|
$dayOfMonth = $current->day;
|
||||||
|
$dateStr = $current->format('Y-m-d');
|
||||||
|
$nextDateStr = $current->copy()->addDay()->format('Y-m-d');
|
||||||
|
|
||||||
|
if ($current->isWeekend()) {
|
||||||
|
// Hétvégék – szürke háttér (inaktív)
|
||||||
|
$events[] = [
|
||||||
|
'id' => 'weekend-' . $dateStr,
|
||||||
|
'title' => '',
|
||||||
|
'start' => $dateStr,
|
||||||
|
'end' => $nextDateStr,
|
||||||
|
'allDay' => true,
|
||||||
|
'display' => 'background',
|
||||||
|
'backgroundColor' => '#E5E7EB',
|
||||||
|
'extendedProps' => ['type' => 'inactive'],
|
||||||
|
];
|
||||||
|
} elseif ($dayOfWeek === Carbon::MONDAY || $dayOfWeek === Carbon::WEDNESDAY || $dayOfWeek === Carbon::FRIDAY) {
|
||||||
|
// Hétfő, szerda, péntek – zöld háttér (szállítási napok)
|
||||||
|
$events[] = [
|
||||||
|
'id' => 'delivery-' . $dateStr,
|
||||||
|
'title' => '',
|
||||||
|
'start' => $dateStr,
|
||||||
|
'end' => $nextDateStr,
|
||||||
|
'allDay' => true,
|
||||||
|
'display' => 'background',
|
||||||
|
'backgroundColor' => '#4CAF50',
|
||||||
|
'extendedProps' => ['type' => 'delivery'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Néhány speciális nap bemutatóként
|
||||||
|
if ($dayOfMonth === 15) {
|
||||||
|
// Minden hónap 15-e – narancssárga (áthelyezett munkanap)
|
||||||
|
$events[] = [
|
||||||
|
'id' => 'special-orange-' . $dateStr,
|
||||||
|
'title' => '',
|
||||||
|
'start' => $dateStr,
|
||||||
|
'end' => $nextDateStr,
|
||||||
|
'allDay' => true,
|
||||||
|
'display' => 'background',
|
||||||
|
'backgroundColor' => '#F59E0B',
|
||||||
|
'extendedProps' => ['type' => 'transferred'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($dayOfMonth === 1) {
|
||||||
|
// Minden hónap 1-je – piros (ünnepnap)
|
||||||
|
$events[] = [
|
||||||
|
'id' => 'special-red-' . $dateStr,
|
||||||
|
'title' => '',
|
||||||
|
'start' => $dateStr,
|
||||||
|
'end' => $nextDateStr,
|
||||||
|
'allDay' => true,
|
||||||
|
'display' => 'background',
|
||||||
|
'backgroundColor' => '#EF4444',
|
||||||
|
'extendedProps' => ['type' => 'holiday'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($dayOfMonth === 10 || $dayOfMonth === 20) {
|
||||||
|
// 10-e és 20-a – kék (megrendelési határidő)
|
||||||
|
$events[] = [
|
||||||
|
'id' => 'special-blue-' . $dateStr,
|
||||||
|
'title' => '',
|
||||||
|
'start' => $dateStr,
|
||||||
|
'end' => $nextDateStr,
|
||||||
|
'allDay' => true,
|
||||||
|
'display' => 'background',
|
||||||
|
'backgroundColor' => '#3B82F6',
|
||||||
|
'extendedProps' => ['type' => 'deadline'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$current->addDay();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $events;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onDateSelect(string $start, ?string $end, bool $allDay, ?array $view, ?array $resource): void
|
||||||
|
{
|
||||||
|
$this->mountAction('manageOverride', [
|
||||||
|
'date' => Carbon::parse($start)->format('Y-m-d'),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onEventClick(array $event): void
|
||||||
|
{
|
||||||
|
$date = data_get($event, 'start');
|
||||||
|
|
||||||
|
if (!$date) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->mountAction('manageOverride', [
|
||||||
|
'date' => Carbon::parse($date)->format('Y-m-d'),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function headerActions(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
Action::make('manageOverride')
|
||||||
|
->label('Felülbírálás kezelése')
|
||||||
|
->modalHeading(fn (array $arguments) => "Szállítás felülbírálása" . (isset($arguments['date']) ? ": " . $arguments['date'] : ""))
|
||||||
|
->form(fn (array $arguments) => [
|
||||||
|
Placeholder::make('info')
|
||||||
|
->hiddenLabel()
|
||||||
|
->content('A háttérben látható naptárban egyszerre több hónapot is áttekinthet. Itt egy konkrét nap módosítását végezheti el.'),
|
||||||
|
\Filament\Forms\Components\DatePicker::make('date')
|
||||||
|
->label('Dátum')
|
||||||
|
->required()
|
||||||
|
->default($arguments['date'] ?? null)
|
||||||
|
->disabled(fn () => isset($arguments['date']))
|
||||||
|
->dehydrated(),
|
||||||
|
Toggle::make('is_delivery_day')
|
||||||
|
->label('Szállítási nap?')
|
||||||
|
->default(function () use ($arguments) {
|
||||||
|
$date = $arguments['date'] ?? null;
|
||||||
|
if (!$date) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$override = DeliveryCalendarOverride::where('supplier_id', $this->record->supplier_id)
|
||||||
|
->whereDate('date', $date)
|
||||||
|
->where('override_scope', OverrideScope::ProfitCenter->value)
|
||||||
|
->where('profit_center_id', $this->record->profit_center_id)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if ($override) {
|
||||||
|
return $override->is_delivery_day;
|
||||||
|
}
|
||||||
|
|
||||||
|
return app(DeliveryCalendarService::class)->isDeliveryDay(
|
||||||
|
$this->record->profitCenter,
|
||||||
|
$this->record->supplier,
|
||||||
|
Carbon::parse($date)
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
TextInput::make('description')
|
||||||
|
->label('Indoklás / Megjegyzés')
|
||||||
|
->default(fn () => isset($arguments['date'])
|
||||||
|
? DeliveryCalendarOverride::where('supplier_id', $this->record->supplier_id)
|
||||||
|
->whereDate('date', $arguments['date'])
|
||||||
|
->where('override_scope', OverrideScope::ProfitCenter->value)
|
||||||
|
->where('profit_center_id', $this->record->profit_center_id)
|
||||||
|
->first()?->description
|
||||||
|
: null
|
||||||
|
),
|
||||||
|
])
|
||||||
|
->action(function (array $data) {
|
||||||
|
DeliveryCalendarOverride::updateOrCreate(
|
||||||
|
[
|
||||||
|
'supplier_id' => $this->record->supplier_id,
|
||||||
|
'override_scope' => OverrideScope::ProfitCenter->value,
|
||||||
|
'profit_center_id' => $this->record->profit_center_id,
|
||||||
|
'date' => $data['date'],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'is_delivery_day' => (bool) $data['is_delivery_day'],
|
||||||
|
'description' => $data['description'],
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->refreshRecords();
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function config(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'initialView' => 'multiMonthYear',
|
||||||
|
'views' => [
|
||||||
|
'multiMonthYear' => [
|
||||||
|
'duration' => ['months' => 6],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'multiMonthMaxColumns' => 6,
|
||||||
|
'headerToolbar' => [
|
||||||
|
'left' => 'prev,next today',
|
||||||
|
'center' => 'title',
|
||||||
|
'right' => 'multiMonthYear',
|
||||||
|
],
|
||||||
|
'locale' => 'hu',
|
||||||
|
'firstDay' => 1,
|
||||||
|
'height' => 'auto',
|
||||||
|
'contentHeight' => 'auto',
|
||||||
|
'selectable' => true,
|
||||||
|
'editable' => false,
|
||||||
|
'dayMaxEvents' => false,
|
||||||
|
'fixedWeekCount' => false,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Enums\OverrideScope;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
|
|
||||||
@ -14,10 +15,21 @@ class DeliveryCalendarOverride extends BaseAuditable
|
|||||||
protected $casts = [
|
protected $casts = [
|
||||||
'date' => 'date',
|
'date' => 'date',
|
||||||
'is_delivery_day' => 'boolean',
|
'is_delivery_day' => 'boolean',
|
||||||
|
'override_scope' => OverrideScope::class,
|
||||||
];
|
];
|
||||||
|
|
||||||
public function supplier(): BelongsTo
|
public function supplier(): BelongsTo
|
||||||
{
|
{
|
||||||
return $this->belongsTo(Supplier::class);
|
return $this->belongsTo(Supplier::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function profitCenter(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(ProfitCenter::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function deliverySchedule(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(DeliverySchedule::class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -57,6 +57,8 @@ public function boot(): void
|
|||||||
});
|
});
|
||||||
|
|
||||||
\Livewire\Livewire::component('app.filament.pages.price-list-processor', \App\Filament\Pages\PriceListProcessor::class);
|
\Livewire\Livewire::component('app.filament.pages.price-list-processor', \App\Filament\Pages\PriceListProcessor::class);
|
||||||
|
\Livewire\Livewire::component('app.filament.pages.calendar-test', \App\Filament\Pages\CalendarTest::class);
|
||||||
|
\Livewire\Livewire::component('app.filament.widgets.delivery-calendar-widget', \App\Filament\Widgets\DeliveryCalendarWidget::class);
|
||||||
/*
|
/*
|
||||||
\Livewire\Livewire::component('filament.livewire.notifications', \Filament\Livewire\Notifications::class);
|
\Livewire\Livewire::component('filament.livewire.notifications', \Filament\Livewire\Notifications::class);
|
||||||
\Livewire\Livewire::component('filament.livewire.database-notifications', \Filament\Livewire\DatabaseNotifications::class);
|
\Livewire\Livewire::component('filament.livewire.database-notifications', \Filament\Livewire\DatabaseNotifications::class);
|
||||||
|
|||||||
@ -2,11 +2,12 @@
|
|||||||
|
|
||||||
namespace App\Services;
|
namespace App\Services;
|
||||||
|
|
||||||
|
use App\Enums\OverrideScope;
|
||||||
use App\Models\DeliveryCalendarOverride;
|
use App\Models\DeliveryCalendarOverride;
|
||||||
use App\Models\ProfitCenter;
|
use App\Models\ProfitCenter;
|
||||||
use App\Models\ProfitCenterSupplierSchedule;
|
use App\Models\ProfitCenterSupplierSchedule;
|
||||||
use App\Models\Supplier;
|
use App\Models\Supplier;
|
||||||
use Carbon\Carbon;
|
use Illuminate\Support\Carbon;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
class DeliveryCalendarService extends ServiceBase
|
class DeliveryCalendarService extends ServiceBase
|
||||||
@ -18,32 +19,64 @@ public function __construct(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Eldönti, hogy egy adott Profit Center, Beszállító és Dátum kombináció esetén van-e szállítás.
|
* Eldönti, hogy egy adott Profit Center, Beszállító és Dátum kombináció esetén van-e szállítás.
|
||||||
|
*
|
||||||
|
* A felülbírálás kiértékelése 3 szinten történik (legspecifikusabbtól az általánosig):
|
||||||
|
* 1. Profitcenter-specifikus override (csak erre az 1 PC-re)
|
||||||
|
* 2. Régió-specifikus override (a PC városához/régiójához tartozó)
|
||||||
|
* 3. Általános override (az összes PC-re vonatkozó)
|
||||||
|
* Ha egyetlen szinten sem található override, folytatódik a normál kiértékelés.
|
||||||
*/
|
*/
|
||||||
public function isDeliveryDay(ProfitCenter $pc, Supplier $supplier, Carbon $date): bool
|
public function isDeliveryDay(ProfitCenter $pc, Supplier $supplier, Carbon $date): bool
|
||||||
{
|
{
|
||||||
$date = $date->startOfDay();
|
$date = $date->startOfDay();
|
||||||
|
|
||||||
// 1. Prioritás: Beszállítói felülbírálás (Override)
|
// 1. Prioritás: Profitcenter-specifikus felülbírálás
|
||||||
$override = DeliveryCalendarOverride::where('supplier_id', $supplier->id)
|
$override = DeliveryCalendarOverride::where('supplier_id', $supplier->id)
|
||||||
->whereDate('date', $date)
|
->whereDate('date', $date)
|
||||||
|
->where('override_scope', OverrideScope::ProfitCenter->value)
|
||||||
|
->where('profit_center_id', $pc->id)
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
if ($override) {
|
if ($override) {
|
||||||
return $override->is_delivery_day;
|
return $override->is_delivery_day;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Prioritás: Hivatalos ünnepnap (WorkCalendar)
|
// PC-hez rendelt szállítási sablon lekérése (2. és 5. prioritáshoz egyaránt szükséges)
|
||||||
// Ha aznap nem hivatalos munkanap van, akkor nincs szállítás (kivéve ha az 1. pont felülbírálta).
|
|
||||||
if (! $this->workCalendarService->isWorkDay($date)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. Prioritás: Heti sablon (Schedule)
|
|
||||||
$assignment = ProfitCenterSupplierSchedule::where('profit_center_id', $pc->id)
|
$assignment = ProfitCenterSupplierSchedule::where('profit_center_id', $pc->id)
|
||||||
->where('supplier_id', $supplier->id)
|
->where('supplier_id', $supplier->id)
|
||||||
->with('deliverySchedule')
|
->with('deliverySchedule')
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
|
// 2. Prioritás: DeliverySchedule-specifikus felülbírálás (a PC-hez rendelt szállítási sablon alapján)
|
||||||
|
if ($assignment && $assignment->delivery_schedule_id) {
|
||||||
|
$override = DeliveryCalendarOverride::where('supplier_id', $supplier->id)
|
||||||
|
->whereDate('date', $date)
|
||||||
|
->where('override_scope', OverrideScope::Region->value)
|
||||||
|
->where('delivery_schedule_id', $assignment->delivery_schedule_id)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if ($override) {
|
||||||
|
return $override->is_delivery_day;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Prioritás: Általános felülbírálás (minden PC-re vonatkozik)
|
||||||
|
$override = DeliveryCalendarOverride::where('supplier_id', $supplier->id)
|
||||||
|
->whereDate('date', $date)
|
||||||
|
->where('override_scope', OverrideScope::General->value)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if ($override) {
|
||||||
|
return $override->is_delivery_day;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. Prioritás: Hivatalos ünnepnap (WorkCalendar)
|
||||||
|
// Ha aznap nem hivatalos munkanap van, akkor nincs szállítás (kivéve ha az 1-3. pont felülbírálta).
|
||||||
|
if (! $this->workCalendarService->isWorkDay($date)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. Prioritás: Heti sablon (Schedule)
|
||||||
if (! $assignment || ! $assignment->deliverySchedule || ! $assignment->deliverySchedule->is_active) {
|
if (! $assignment || ! $assignment->deliverySchedule || ! $assignment->deliverySchedule->is_active) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,9 @@
|
|||||||
|
|
||||||
namespace Database\Factories;
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Enums\OverrideScope;
|
||||||
use App\Models\DeliveryCalendarOverride;
|
use App\Models\DeliveryCalendarOverride;
|
||||||
|
use App\Models\DeliverySchedule;
|
||||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -19,9 +21,39 @@ public function definition(): array
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'supplier_id' => \App\Models\Supplier::factory(),
|
'supplier_id' => \App\Models\Supplier::factory(),
|
||||||
|
'override_scope' => OverrideScope::General,
|
||||||
|
'delivery_schedule_id' => null,
|
||||||
|
'profit_center_id' => null,
|
||||||
'date' => $this->faker->date(),
|
'date' => $this->faker->date(),
|
||||||
'is_delivery_day' => $this->faker->boolean(),
|
'is_delivery_day' => $this->faker->boolean(),
|
||||||
'description' => $this->faker->sentence(),
|
'description' => $this->faker->sentence(),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function general(): static
|
||||||
|
{
|
||||||
|
return $this->state([
|
||||||
|
'override_scope' => OverrideScope::General,
|
||||||
|
'delivery_schedule_id' => null,
|
||||||
|
'profit_center_id' => null,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function forDeliverySchedule(DeliverySchedule $schedule): static
|
||||||
|
{
|
||||||
|
return $this->state([
|
||||||
|
'override_scope' => OverrideScope::Region,
|
||||||
|
'delivery_schedule_id' => $schedule->id,
|
||||||
|
'profit_center_id' => null,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function forProfitCenter(\App\Models\ProfitCenter $profitCenter): static
|
||||||
|
{
|
||||||
|
return $this->state([
|
||||||
|
'override_scope' => OverrideScope::ProfitCenter,
|
||||||
|
'delivery_schedule_id' => null,
|
||||||
|
'profit_center_id' => $profitCenter->id,
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('delivery_calendar_overrides', function (Blueprint $table) {
|
||||||
|
$table->string('override_scope')->default('general')->after('supplier_id');
|
||||||
|
$table->string('region')->nullable()->after('override_scope');
|
||||||
|
$table->foreignId('profit_center_id')->nullable()->constrained()->nullOnDelete()->after('region');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('delivery_calendar_overrides', function (Blueprint $table) {
|
||||||
|
$table->dropForeign(['profit_center_id']);
|
||||||
|
$table->dropColumn(['override_scope', 'region', 'profit_center_id']);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('delivery_calendar_overrides', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('region');
|
||||||
|
$table->foreignId('delivery_schedule_id')->nullable()->constrained()->nullOnDelete()->after('override_scope');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('delivery_calendar_overrides', function (Blueprint $table) {
|
||||||
|
$table->dropForeign(['delivery_schedule_id']);
|
||||||
|
$table->dropColumn('delivery_schedule_id');
|
||||||
|
$table->string('region')->nullable()->after('override_scope');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -19,6 +19,7 @@
|
|||||||
['displayName' => 'Profitcenter ütemezés', 'link' => \App\Filament\Resources\ProfitCenterSupplierSchedules\ProfitCenterSupplierScheduleResource::getUrl()],
|
['displayName' => 'Profitcenter ütemezés', 'link' => \App\Filament\Resources\ProfitCenterSupplierSchedules\ProfitCenterSupplierScheduleResource::getUrl()],
|
||||||
['displayName' => 'Munkanaptárak', 'link' => \App\Filament\Resources\WorkCalendars\WorkCalendarResource::getUrl()],
|
['displayName' => 'Munkanaptárak', 'link' => \App\Filament\Resources\WorkCalendars\WorkCalendarResource::getUrl()],
|
||||||
]],
|
]],
|
||||||
|
['name' => 'calendarTest', 'displayName' => 'Naptár Teszt', 'icon' => 'idopontok', 'link' => \App\Filament\Pages\CalendarTest::getUrl(), 'roles' => ['root','developer','admin']],
|
||||||
];
|
];
|
||||||
@endphp
|
@endphp
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use App\Enums\OverrideScope;
|
||||||
use App\Models\DeliveryCalendarOverride;
|
use App\Models\DeliveryCalendarOverride;
|
||||||
use App\Models\DeliverySchedule;
|
use App\Models\DeliverySchedule;
|
||||||
use App\Models\ProfitCenter;
|
use App\Models\ProfitCenter;
|
||||||
@ -21,16 +22,13 @@
|
|||||||
$schedule = DeliverySchedule::factory()->create([
|
$schedule = DeliverySchedule::factory()->create([
|
||||||
'monday' => true,
|
'monday' => true,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
ProfitCenterSupplierSchedule::factory()->create([
|
ProfitCenterSupplierSchedule::factory()->create([
|
||||||
'profit_center_id' => $pc->id,
|
'profit_center_id' => $pc->id,
|
||||||
'supplier_id' => $supplier->id,
|
'supplier_id' => $supplier->id,
|
||||||
'delivery_schedule_id' => $schedule->id,
|
'delivery_schedule_id' => $schedule->id,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$service = app(DeliveryCalendarService::class);
|
$service = app(DeliveryCalendarService::class);
|
||||||
$monday = Carbon::parse('2026-04-13'); // Monday
|
$monday = Carbon::parse('2026-04-13'); // Monday
|
||||||
|
|
||||||
expect($service->isDeliveryDay($pc, $supplier, $monday))->toBeTrue();
|
expect($service->isDeliveryDay($pc, $supplier, $monday))->toBeTrue();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -41,16 +39,13 @@
|
|||||||
'monday' => true,
|
'monday' => true,
|
||||||
'tuesday' => false,
|
'tuesday' => false,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
ProfitCenterSupplierSchedule::factory()->create([
|
ProfitCenterSupplierSchedule::factory()->create([
|
||||||
'profit_center_id' => $pc->id,
|
'profit_center_id' => $pc->id,
|
||||||
'supplier_id' => $supplier->id,
|
'supplier_id' => $supplier->id,
|
||||||
'delivery_schedule_id' => $schedule->id,
|
'delivery_schedule_id' => $schedule->id,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$service = app(DeliveryCalendarService::class);
|
$service = app(DeliveryCalendarService::class);
|
||||||
$tuesday = Carbon::parse('2026-04-14'); // Tuesday
|
$tuesday = Carbon::parse('2026-04-14'); // Tuesday
|
||||||
|
|
||||||
expect($service->isDeliveryDay($pc, $supplier, $tuesday))->toBeFalse();
|
expect($service->isDeliveryDay($pc, $supplier, $tuesday))->toBeFalse();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -58,84 +53,193 @@
|
|||||||
$pc = ProfitCenter::factory()->create();
|
$pc = ProfitCenter::factory()->create();
|
||||||
$supplier = Supplier::factory()->create();
|
$supplier = Supplier::factory()->create();
|
||||||
$schedule = DeliverySchedule::factory()->create(['monday' => true]);
|
$schedule = DeliverySchedule::factory()->create(['monday' => true]);
|
||||||
|
|
||||||
ProfitCenterSupplierSchedule::factory()->create([
|
ProfitCenterSupplierSchedule::factory()->create([
|
||||||
'profit_center_id' => $pc->id,
|
'profit_center_id' => $pc->id,
|
||||||
'supplier_id' => $supplier->id,
|
'supplier_id' => $supplier->id,
|
||||||
'delivery_schedule_id' => $schedule->id,
|
'delivery_schedule_id' => $schedule->id,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$monday = Carbon::parse('2026-04-13'); // Monday
|
$monday = Carbon::parse('2026-04-13'); // Monday
|
||||||
|
|
||||||
// Mark this Monday as a holiday
|
// Mark this Monday as a holiday
|
||||||
WorkCalendar::create([
|
WorkCalendar::create([
|
||||||
'date' => '2026-04-13',
|
'date' => '2026-04-13',
|
||||||
'type' => WorkDayType::Holiday,
|
'type' => WorkDayType::Holiday,
|
||||||
'data_source' => DataSource::Manual,
|
'data_source' => DataSource::Manual,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$service = app(DeliveryCalendarService::class);
|
$service = app(DeliveryCalendarService::class);
|
||||||
|
|
||||||
expect($service->isDeliveryDay($pc, $supplier, $monday))->toBeFalse();
|
expect($service->isDeliveryDay($pc, $supplier, $monday))->toBeFalse();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('respects supplier overrides over holidays', function () {
|
it('respects general supplier override over holidays', function () {
|
||||||
$pc = ProfitCenter::factory()->create();
|
$pc = ProfitCenter::factory()->create();
|
||||||
$supplier = Supplier::factory()->create();
|
$supplier = Supplier::factory()->create();
|
||||||
$schedule = DeliverySchedule::factory()->create(['monday' => true]);
|
$schedule = DeliverySchedule::factory()->create(['monday' => true]);
|
||||||
|
|
||||||
ProfitCenterSupplierSchedule::factory()->create([
|
ProfitCenterSupplierSchedule::factory()->create([
|
||||||
'profit_center_id' => $pc->id,
|
'profit_center_id' => $pc->id,
|
||||||
'supplier_id' => $supplier->id,
|
'supplier_id' => $supplier->id,
|
||||||
'delivery_schedule_id' => $schedule->id,
|
'delivery_schedule_id' => $schedule->id,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$monday = Carbon::parse('2026-04-13'); // Monday
|
$monday = Carbon::parse('2026-04-13'); // Monday
|
||||||
|
|
||||||
// Mark this Monday as a holiday
|
|
||||||
WorkCalendar::create([
|
WorkCalendar::create([
|
||||||
'date' => '2026-04-13',
|
'date' => '2026-04-13',
|
||||||
'type' => WorkDayType::Holiday,
|
'type' => WorkDayType::Holiday,
|
||||||
'data_source' => DataSource::Manual,
|
'data_source' => DataSource::Manual,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Create an override to allow delivery despite the holiday
|
|
||||||
DeliveryCalendarOverride::create([
|
DeliveryCalendarOverride::create([
|
||||||
'supplier_id' => $supplier->id,
|
'supplier_id' => $supplier->id,
|
||||||
|
'override_scope' => OverrideScope::General->value,
|
||||||
'date' => '2026-04-13',
|
'date' => '2026-04-13',
|
||||||
'is_delivery_day' => true,
|
'is_delivery_day' => true,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$service = app(DeliveryCalendarService::class);
|
$service = app(DeliveryCalendarService::class);
|
||||||
|
|
||||||
expect($service->isDeliveryDay($pc, $supplier, $monday))->toBeTrue();
|
expect($service->isDeliveryDay($pc, $supplier, $monday))->toBeTrue();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('respects supplier overrides to block delivery on a normal day', function () {
|
it('respects general supplier override to block delivery on a normal day', function () {
|
||||||
$pc = ProfitCenter::factory()->create();
|
$pc = ProfitCenter::factory()->create();
|
||||||
$supplier = Supplier::factory()->create();
|
$supplier = Supplier::factory()->create();
|
||||||
$schedule = DeliverySchedule::factory()->create(['monday' => true]);
|
$schedule = DeliverySchedule::factory()->create(['monday' => true]);
|
||||||
|
|
||||||
ProfitCenterSupplierSchedule::factory()->create([
|
ProfitCenterSupplierSchedule::factory()->create([
|
||||||
'profit_center_id' => $pc->id,
|
'profit_center_id' => $pc->id,
|
||||||
'supplier_id' => $supplier->id,
|
'supplier_id' => $supplier->id,
|
||||||
'delivery_schedule_id' => $schedule->id,
|
'delivery_schedule_id' => $schedule->id,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$monday = Carbon::parse('2026-04-13'); // Monday
|
$monday = Carbon::parse('2026-04-13'); // Monday
|
||||||
|
|
||||||
// Create an override to block delivery
|
|
||||||
DeliveryCalendarOverride::create([
|
DeliveryCalendarOverride::create([
|
||||||
'supplier_id' => $supplier->id,
|
'supplier_id' => $supplier->id,
|
||||||
|
'override_scope' => OverrideScope::General->value,
|
||||||
'date' => '2026-04-13',
|
'date' => '2026-04-13',
|
||||||
'is_delivery_day' => false,
|
'is_delivery_day' => false,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$service = app(DeliveryCalendarService::class);
|
$service = app(DeliveryCalendarService::class);
|
||||||
|
|
||||||
expect($service->isDeliveryDay($pc, $supplier, $monday))->toBeFalse();
|
expect($service->isDeliveryDay($pc, $supplier, $monday))->toBeFalse();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('respects delivery-schedule-specific override over general override', function () {
|
||||||
|
$pc = ProfitCenter::factory()->create();
|
||||||
|
$supplier = Supplier::factory()->create();
|
||||||
|
$schedule = DeliverySchedule::factory()->create(['monday' => true]);
|
||||||
|
ProfitCenterSupplierSchedule::factory()->create([
|
||||||
|
'profit_center_id' => $pc->id,
|
||||||
|
'supplier_id' => $supplier->id,
|
||||||
|
'delivery_schedule_id' => $schedule->id,
|
||||||
|
]);
|
||||||
|
$monday = Carbon::parse('2026-04-13');
|
||||||
|
// Általános tiltás
|
||||||
|
DeliveryCalendarOverride::create([
|
||||||
|
'supplier_id' => $supplier->id,
|
||||||
|
'override_scope' => OverrideScope::General->value,
|
||||||
|
'date' => '2026-04-13',
|
||||||
|
'is_delivery_day' => false,
|
||||||
|
]);
|
||||||
|
// Szállítási sablon-specifikus engedélyezés
|
||||||
|
DeliveryCalendarOverride::create([
|
||||||
|
'supplier_id' => $supplier->id,
|
||||||
|
'override_scope' => OverrideScope::Region->value,
|
||||||
|
'delivery_schedule_id' => $schedule->id,
|
||||||
|
'date' => '2026-04-13',
|
||||||
|
'is_delivery_day' => true,
|
||||||
|
]);
|
||||||
|
$service = app(DeliveryCalendarService::class);
|
||||||
|
// A sablon-specifikus győz az általánossal szemben
|
||||||
|
expect($service->isDeliveryDay($pc, $supplier, $monday))->toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('delivery-schedule override does not affect profit centers with different schedule', function () {
|
||||||
|
$supplier = Supplier::factory()->create();
|
||||||
|
$scheduleA = DeliverySchedule::factory()->create(['monday' => true]);
|
||||||
|
$scheduleB = DeliverySchedule::factory()->create(['monday' => true]);
|
||||||
|
$pcA = ProfitCenter::factory()->create();
|
||||||
|
$pcB = ProfitCenter::factory()->create();
|
||||||
|
ProfitCenterSupplierSchedule::factory()->create([
|
||||||
|
'profit_center_id' => $pcA->id,
|
||||||
|
'supplier_id' => $supplier->id,
|
||||||
|
'delivery_schedule_id' => $scheduleA->id,
|
||||||
|
]);
|
||||||
|
ProfitCenterSupplierSchedule::factory()->create([
|
||||||
|
'profit_center_id' => $pcB->id,
|
||||||
|
'supplier_id' => $supplier->id,
|
||||||
|
'delivery_schedule_id' => $scheduleB->id,
|
||||||
|
]);
|
||||||
|
$monday = Carbon::parse('2026-04-13');
|
||||||
|
// Csak az A sablont tiltjuk
|
||||||
|
DeliveryCalendarOverride::create([
|
||||||
|
'supplier_id' => $supplier->id,
|
||||||
|
'override_scope' => OverrideScope::Region->value,
|
||||||
|
'delivery_schedule_id' => $scheduleA->id,
|
||||||
|
'date' => '2026-04-13',
|
||||||
|
'is_delivery_day' => false,
|
||||||
|
]);
|
||||||
|
$service = app(DeliveryCalendarService::class);
|
||||||
|
expect($service->isDeliveryDay($pcA, $supplier, $monday))->toBeFalse();
|
||||||
|
expect($service->isDeliveryDay($pcB, $supplier, $monday))->toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('respects profit-center-specific override over region and general overrides', function () {
|
||||||
|
$pc = ProfitCenter::factory()->create(['city' => 'Budapest']);
|
||||||
|
$supplier = Supplier::factory()->create();
|
||||||
|
$schedule = DeliverySchedule::factory()->create(['monday' => true]);
|
||||||
|
ProfitCenterSupplierSchedule::factory()->create([
|
||||||
|
'profit_center_id' => $pc->id,
|
||||||
|
'supplier_id' => $supplier->id,
|
||||||
|
'delivery_schedule_id' => $schedule->id,
|
||||||
|
]);
|
||||||
|
$monday = Carbon::parse('2026-04-13');
|
||||||
|
// Általános tiltás
|
||||||
|
DeliveryCalendarOverride::create([
|
||||||
|
'supplier_id' => $supplier->id,
|
||||||
|
'override_scope' => OverrideScope::General->value,
|
||||||
|
'date' => '2026-04-13',
|
||||||
|
'is_delivery_day' => false,
|
||||||
|
]);
|
||||||
|
// Sablon-specifikus tiltás is
|
||||||
|
DeliveryCalendarOverride::create([
|
||||||
|
'supplier_id' => $supplier->id,
|
||||||
|
'override_scope' => OverrideScope::Region->value,
|
||||||
|
'delivery_schedule_id' => $schedule->id,
|
||||||
|
'date' => '2026-04-13',
|
||||||
|
'is_delivery_day' => false,
|
||||||
|
]);
|
||||||
|
// De erre a konkrét PC-re engedélyezve van
|
||||||
|
DeliveryCalendarOverride::create([
|
||||||
|
'supplier_id' => $supplier->id,
|
||||||
|
'override_scope' => OverrideScope::ProfitCenter->value,
|
||||||
|
'profit_center_id' => $pc->id,
|
||||||
|
'date' => '2026-04-13',
|
||||||
|
'is_delivery_day' => true,
|
||||||
|
]);
|
||||||
|
$service = app(DeliveryCalendarService::class);
|
||||||
|
expect($service->isDeliveryDay($pc, $supplier, $monday))->toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('profit-center-specific override only affects the targeted profit center', function () {
|
||||||
|
$pc1 = ProfitCenter::factory()->create(['city' => 'Budapest']);
|
||||||
|
$pc2 = ProfitCenter::factory()->create(['city' => 'Budapest']);
|
||||||
|
$supplier = Supplier::factory()->create();
|
||||||
|
$schedule = DeliverySchedule::factory()->create(['monday' => true]);
|
||||||
|
ProfitCenterSupplierSchedule::factory()->create([
|
||||||
|
'profit_center_id' => $pc1->id,
|
||||||
|
'supplier_id' => $supplier->id,
|
||||||
|
'delivery_schedule_id' => $schedule->id,
|
||||||
|
]);
|
||||||
|
ProfitCenterSupplierSchedule::factory()->create([
|
||||||
|
'profit_center_id' => $pc2->id,
|
||||||
|
'supplier_id' => $supplier->id,
|
||||||
|
'delivery_schedule_id' => $schedule->id,
|
||||||
|
]);
|
||||||
|
$monday = Carbon::parse('2026-04-13');
|
||||||
|
// Csak pc1-re van tiltás
|
||||||
|
DeliveryCalendarOverride::create([
|
||||||
|
'supplier_id' => $supplier->id,
|
||||||
|
'override_scope' => OverrideScope::ProfitCenter->value,
|
||||||
|
'profit_center_id' => $pc1->id,
|
||||||
|
'date' => '2026-04-13',
|
||||||
|
'is_delivery_day' => false,
|
||||||
|
]);
|
||||||
|
$service = app(DeliveryCalendarService::class);
|
||||||
|
expect($service->isDeliveryDay($pc1, $supplier, $monday))->toBeFalse();
|
||||||
|
expect($service->isDeliveryDay($pc2, $supplier, $monday))->toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
it('calculates available delivery dates in a range', function () {
|
it('calculates available delivery dates in a range', function () {
|
||||||
$pc = ProfitCenter::factory()->create();
|
$pc = ProfitCenter::factory()->create();
|
||||||
$supplier = Supplier::factory()->create();
|
$supplier = Supplier::factory()->create();
|
||||||
@ -144,19 +248,15 @@
|
|||||||
'wednesday' => true,
|
'wednesday' => true,
|
||||||
'friday' => true,
|
'friday' => true,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
ProfitCenterSupplierSchedule::factory()->create([
|
ProfitCenterSupplierSchedule::factory()->create([
|
||||||
'profit_center_id' => $pc->id,
|
'profit_center_id' => $pc->id,
|
||||||
'supplier_id' => $supplier->id,
|
'supplier_id' => $supplier->id,
|
||||||
'delivery_schedule_id' => $schedule->id,
|
'delivery_schedule_id' => $schedule->id,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$start = Carbon::parse('2026-04-13'); // Monday
|
$start = Carbon::parse('2026-04-13'); // Monday
|
||||||
$end = Carbon::parse('2026-04-19'); // Sunday
|
$end = Carbon::parse('2026-04-19'); // Sunday
|
||||||
|
|
||||||
$service = app(DeliveryCalendarService::class);
|
$service = app(DeliveryCalendarService::class);
|
||||||
$dates = $service->getAvailableDeliveryDates($pc, $supplier, $start, $end);
|
$dates = $service->getAvailableDeliveryDates($pc, $supplier, $start, $end);
|
||||||
|
|
||||||
// Should be Mon, Wed, Fri
|
// Should be Mon, Wed, Fri
|
||||||
expect($dates)->toHaveCount(3);
|
expect($dates)->toHaveCount(3);
|
||||||
$dateStrings = $dates->map(fn($d) => $d->toDateString());
|
$dateStrings = $dates->map(fn($d) => $d->toDateString());
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user