diff --git a/app/Console/Commands/ProcessFeedSchedule.php b/app/Console/Commands/ProcessFeedSchedule.php index f87ab63..74e9956 100644 --- a/app/Console/Commands/ProcessFeedSchedule.php +++ b/app/Console/Commands/ProcessFeedSchedule.php @@ -30,17 +30,17 @@ public function handle(): int } foreach ($schedules as $schedule) { - $feed = $schedule->feed; - if ($feed) { - $decrement = min($schedule->quantity, $feed->stock); + foreach ($schedule->feeds as $feed) { + $quantity = $feed->pivot->quantity; + $decrement = min($quantity, $feed->stock); $feed->decrement('stock', $decrement); - } - FeedDelivery::create([ - 'feed_id' => $schedule->feed_id, - 'quantity' => $schedule->quantity, - 'delivered_at' => now(), - ]); + FeedDelivery::create([ + 'feed_id' => $feed->id, + 'quantity' => $quantity, + 'delivered_at' => now(), + ]); + } } $this->info('Processed '.$schedules->count()." feed schedules for time: {$time}"); diff --git a/app/Filament/Resources/Manage/FeedSchedules/FeedScheduleResource.php b/app/Filament/Resources/Manage/FeedSchedules/FeedScheduleResource.php index 879154c..c3acad0 100644 --- a/app/Filament/Resources/Manage/FeedSchedules/FeedScheduleResource.php +++ b/app/Filament/Resources/Manage/FeedSchedules/FeedScheduleResource.php @@ -9,10 +9,12 @@ use App\Filament\Actions\Cheerful\RestoreAction; use App\Filament\Actions\DefaultBulkActions; use App\Filament\Columns\TimestampColumns; -use App\Filament\Resources\Master\Units\Pages\ManageFeedSchedules; +use App\Filament\Resources\Manage\FeedSchedules\Pages\ManageFeedSchedules; +use App\Models\Feed; use App\Models\FeedSchedule; use BackedEnum; use Filament\Actions\BulkActionGroup; +use Filament\Forms\Components\Repeater; use Filament\Forms\Components\Select; use Filament\Forms\Components\TextInput; use Filament\Resources\Resource; @@ -25,6 +27,7 @@ use HusamTariq\FilamentTimePicker\Forms\Components\TimePickerField; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\SoftDeletingScope; +use Illuminate\Support\Facades\Auth; use UnitEnum; class FeedScheduleResource extends Resource @@ -47,13 +50,6 @@ public static function form(Schema $schema): Schema { return $schema ->components([ - Select::make('feed_id') - ->label('Pakan') - ->relationship('feed', 'name') - ->required() - ->searchable() - ->preload(), - TimePickerField::make('scheduled_at') ->label('Jadwal') ->placeholder('Pilih Jadwal') @@ -61,14 +57,31 @@ public static function form(Schema $schema): Schema ->cancelLabel('Batal') ->required(), - TextInput::make('quantity') - ->label('Kuantitas') - ->placeholder('0') - ->autocomplete(false) - ->required() - ->currencyMask(thousandSeparator: '.', decimalSeparator: ',', precision: 0) - ->dehydrateStateUsing(fn ($state) => (int) str()->replace(',', '', (string) ($state ?? 0))) - ->helperText('Satuan kuantitas pakan sesuai dengan satuan yang ada di menu pakan.'), + Repeater::make('feedFeedSchedules') + ->label('Data Pakan') + ->relationship('feedFeedSchedules') + ->schema([ + Select::make('feed_id') + ->label('Pakan') + ->options(Feed::query()->pluck('name', 'id')) + ->searchable() + ->preload() + ->required() + ->distinct() + ->live(), + + TextInput::make('quantity') + ->label('Kuantitas') + ->placeholder('0') + ->autocomplete(false) + ->required() + ->currencyMask(thousandSeparator: '.', decimalSeparator: ',', precision: 0) + ->dehydrateStateUsing(fn ($state) => (int) str()->replace('.', '', (string) ($state ?? 0))) + ->suffix(fn ($get) => Feed::find($get('feed_id'))?->unit?->alias), + ]) + ->columns(2) + ->minItems(1) + ->addActionLabel('Tambah Pakan'), ]) ->columns(1); } @@ -77,26 +90,22 @@ public static function table(Table $table): Table { return $table ->columns([ - TextColumn::make('feed.name') - ->label('Pakan') - ->sortable(), - - TextColumn::make('quantity') - ->label('Kuantitas') - ->numeric(decimalPlaces: 0) - ->suffix(fn (FeedSchedule $record): string => ' '.$record->feed?->unit?->alias), - TextColumn::make('scheduled_at') ->label('Jadwal') ->dateTime('H:i') ->sortable(), + TextColumn::make('feeds') + ->label('Daftar Pakan') + ->badge() + ->formatStateUsing(fn (Feed $state): string => "{$state->name} ({$state->pivot->quantity} {$state->unit?->alias})"), + ...TimestampColumns::make(), ]) ->filters([ TrashedFilter::make() ->native(false) - ->visible(fn (): bool => auth()->user()->hasRole(RoleEnum::DEVELOPER)), + ->visible(fn (): bool => Auth::user()?->hasRole(RoleEnum::DEVELOPER) ?? false), ]) ->recordActions([ EditAction::make() @@ -119,6 +128,11 @@ public static function table(Table $table): Table ->deferFilters(false); } + public static function getEloquentQuery(): Builder + { + return parent::getEloquentQuery()->with(['feeds.unit']); + } + public static function getPages(): array { return [ diff --git a/app/Filament/Resources/Manage/FeedSchedules/Pages/ManageFeedSchedules.php b/app/Filament/Resources/Manage/FeedSchedules/Pages/ManageFeedSchedules.php index 7117976..82fb6c1 100644 --- a/app/Filament/Resources/Manage/FeedSchedules/Pages/ManageFeedSchedules.php +++ b/app/Filament/Resources/Manage/FeedSchedules/Pages/ManageFeedSchedules.php @@ -1,6 +1,6 @@ hasMany(FeedPurchase::class); } - public function schedules(): HasMany + public function schedules(): BelongsToMany { - return $this->hasMany(FeedSchedule::class); + return $this->belongsToMany(FeedSchedule::class, 'feed_feed_schedule') + ->using(FeedFeedSchedule::class) + ->withPivot('quantity') + ->withTimestamps(); } public function deliveries(): HasMany diff --git a/app/Models/FeedFeedSchedule.php b/app/Models/FeedFeedSchedule.php new file mode 100644 index 0000000..3da342e --- /dev/null +++ b/app/Models/FeedFeedSchedule.php @@ -0,0 +1,25 @@ +belongsTo(Feed::class); + } + + public function feedSchedule(): BelongsTo + { + return $this->belongsTo(FeedSchedule::class); + } +} diff --git a/app/Models/FeedSchedule.php b/app/Models/FeedSchedule.php index 0652a1e..b9c0b4f 100644 --- a/app/Models/FeedSchedule.php +++ b/app/Models/FeedSchedule.php @@ -4,7 +4,8 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; -use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\BelongsToMany; +use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\SoftDeletes; class FeedSchedule extends Model @@ -20,8 +21,16 @@ protected function casts(): array ]; } - public function feed(): BelongsTo + public function feeds(): BelongsToMany { - return $this->belongsTo(Feed::class); + return $this->belongsToMany(Feed::class, 'feed_feed_schedule') + ->using(FeedFeedSchedule::class) + ->withPivot('quantity') + ->withTimestamps(); + } + + public function feedFeedSchedules(): HasMany + { + return $this->hasMany(FeedFeedSchedule::class); } } diff --git a/database/migrations/2026_02_26_000001_create_feed_schedules_table.php b/database/migrations/2026_02_26_000001_create_feed_schedules_table.php index 78513bf..2e116d1 100644 --- a/database/migrations/2026_02_26_000001_create_feed_schedules_table.php +++ b/database/migrations/2026_02_26_000001_create_feed_schedules_table.php @@ -13,8 +13,6 @@ public function up(): void { Schema::create('feed_schedules', function (Blueprint $table) { $table->id(); - $table->foreignId('feed_id')->constrained()->cascadeOnDelete(); - $table->unsignedInteger('quantity'); $table->time('scheduled_at'); $table->timestamp('created_at')->useCurrent(); $table->timestamp('updated_at')->nullable()->useCurrentOnUpdate(); diff --git a/database/migrations/2026_02_26_125306_create_feed_feed_schedule_table.php b/database/migrations/2026_02_26_125306_create_feed_feed_schedule_table.php new file mode 100644 index 0000000..48a6ef5 --- /dev/null +++ b/database/migrations/2026_02_26_125306_create_feed_feed_schedule_table.php @@ -0,0 +1,31 @@ +id(); + $table->foreignId('feed_schedule_id')->constrained()->cascadeOnDelete(); + $table->foreignId('feed_id')->constrained()->cascadeOnDelete(); + $table->unsignedInteger('quantity'); + $table->timestamp('created_at')->useCurrent(); + $table->timestamp('updated_at')->nullable()->useCurrentOnUpdate(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('feed_feed_schedule'); + } +};