whereNull('execution_date') ->where('planned_date', '>=', now()->subDays(7)) ->where('planned_date', '<=', now()->addDays(7)) ->orderBy('planned_date') ->get(); // Load parent Treatment records for treatment types (to access vineyard row data) foreach ($plannedTasksRaw as $task) { if (in_array($task->taskable_type, [ 'App\Models\Spraying', 'App\Models\Watering', 'App\Models\Fertilization', 'App\Models\Pruning' ]) && $task->taskable) { $task->treatment = Treatment::with('vineyardRow')->find($task->taskable->treatment_id); } } // Group planned tasks by type, date, and note $plannedTasks = $plannedTasksRaw->groupBy(function($task) { return $task->type . '|' . $task->planned_date->format('Y-m-d') . '|' . ($task->note ?? ''); })->map(function($group) { $first = $group->first(); $first->vineyard_rows = $group->map(function($task) { if ($task->taskable_type === VineyardRow::class) { return $task->taskable; } // For Treatment types, use the parent Treatment record if (isset($task->treatment) && $task->treatment) { return $task->treatment->vineyardRow; } // For Harvest, load the vineyardRow if it exists if ($task->taskable && method_exists($task->taskable, 'vineyardRow')) { return $task->taskable->vineyardRow; } return null; })->filter()->values(); // Map task IDs to their vineyard rows $first->task_rows = $group->map(function($task) { $row = null; if ($task->taskable_type === VineyardRow::class) { $row = $task->taskable; } elseif (isset($task->treatment) && $task->treatment) { $row = $task->treatment->vineyardRow; } elseif ($task->taskable && method_exists($task->taskable, 'vineyardRow')) { $row = $task->taskable->vineyardRow; } return $row ? [ 'task_id' => $task->planned_task_id, 'row_id' => $row->id, 'row' => $row, ] : null; })->filter()->values(); $first->task_count = $group->count(); return $first; })->values(); // Sort all planned tasks chronologically $allPlannedTasks = $plannedTasks->sortBy('planned_date')->values(); // ======================================== // COMPLETED ACTIONS // ======================================== $completedActivities = collect(); // 1. Completed treatments and tasks (including completed Harvests) $completedTasksRaw = PlannedTask::with(['taskable']) ->whereNotNull('execution_date') ->where('execution_date', '>=', now()->subDays(30)) ->orderBy('execution_date', 'desc') ->get(); // Load parent Treatment records for treatment types foreach ($completedTasksRaw as $task) { if (in_array($task->taskable_type, [ 'App\Models\Spraying', 'App\Models\Watering', 'App\Models\Fertilization', 'App\Models\Pruning' ]) && $task->taskable) { $task->treatment = Treatment::with('vineyardRow')->find($task->taskable->treatment_id); } } // Group completed tasks by type, execution date, and note $completedTasks = $completedTasksRaw->groupBy(function($task) { return $task->type . '|' . $task->execution_date->format('Y-m-d') . '|' . ($task->note ?? ''); })->map(function($group) { $first = $group->first(); $first->vineyard_rows = $group->map(function($task) { if ($task->taskable_type === VineyardRow::class) { return $task->taskable; } // For Treatment types, use the parent Treatment record if (isset($task->treatment) && $task->treatment) { return $task->treatment->vineyardRow; } // For Harvest, load the vineyardRow if it exists if ($task->taskable && method_exists($task->taskable, 'vineyardRow')) { return $task->taskable->vineyardRow; } return null; })->filter()->values(); $first->task_count = $group->count(); $first->activity_type = 'task'; $first->activity_date = $first->execution_date; return $first; })->values(); $completedActivities = $completedActivities->concat($completedTasks); // 2. Recent wine productions (bottling/blending) - DISABLED FOR RECENT ACTIVITY // Note: Bottling and blending activities are only shown in "All Completed Activities" // They are excluded from the recent activity timeline on the dashboard /* $recentProductions = WineProduction::with(['wine.grapeVariety', 'harvest.vineyardRow.varietyVariation']) ->where('created_at', '>=', now()->subDays(30)) ->orderBy('created_at', 'desc') ->get(); // Group by wine to detect blends $productionsByWine = $recentProductions->groupBy('wine_id'); foreach ($productionsByWine as $wineId => $productions) { $wine = $productions->first()->wine; if (!$wine) continue; $activity = (object)[ 'activity_type' => 'production', 'activity_date' => $productions->first()->created_at, 'wine' => $wine, 'productions' => $productions, 'is_blend' => $productions->count() > 1, 'total_weight' => $productions->sum('consumed_weight'), ]; $completedActivities->push($activity); } */ // 3. Recent harvests (not from planned tasks) - DISABLED // Note: Only showing "Harvest completed" from PlannedTask, not "Harvest Recorded" // Harvest recorded activities are excluded from recent activity timeline /* $recentHarvests = Harvest::with(['vineyardRow.varietyVariation.grapeVariety']) ->where('date', '>=', now()->subDays(30)) ->orderBy('date', 'desc') ->get() ->map(function($harvest) { // Check if this harvest is already represented in completed tasks $existingTask = PlannedTask::where('taskable_type', Harvest::class) ->where('taskable_id', $harvest->id) ->whereNotNull('execution_date') ->exists(); if ($existingTask) { return null; // Skip to avoid duplicates } return (object)[ 'activity_type' => 'harvest', 'activity_date' => $harvest->date, 'harvest' => $harvest, ]; }) ->filter(); $completedActivities = $completedActivities->concat($recentHarvests); */ // Sort all completed activities by date (most recent first) $completedActivities = $completedActivities ->sortByDesc('activity_date') ->take(20) ->values(); // ======================================== // STATISTICS // ======================================== // Wine statistics $wineStats = [ 'total_bottles' => Wine::sum('bottles_in_stock') ?? 0, 'by_status' => Wine::select('status', DB::raw('count(*) as count')) ->groupBy('status') ->pluck('count', 'status') ->toArray(), ]; // Harvest statistics $totalHarvestWeight = Harvest::sum('weight') ?? 0; $totalConsumedWeight = WineProduction::sum('consumed_weight') ?? 0; $harvestStats = [ 'total_harvest' => $totalHarvestWeight, 'consumed' => $totalConsumedWeight, 'available_weight' => max(0, $totalHarvestWeight - $totalConsumedWeight), ]; // Vineyard statistics $vineyardStats = [ 'total_rows' => VineyardRow::count(), 'active_rows' => VineyardRow::where('status', 'active')->count(), 'total_area' => VineyardRow::sum('area') ?? 0, ]; return view('winemaker.dashboard.index', compact( 'allPlannedTasks', 'completedActivities', 'wineStats', 'harvestStats', 'vineyardStats' )); } /** * Display all planned tasks. */ public function allPlannedTasks() { // Get all planned tasks (not yet executed) - including overdue tasks $plannedTasksRaw = PlannedTask::with(['taskable']) ->whereNull('execution_date') ->orderBy('planned_date') ->get(); // Load parent Treatment records for treatment types foreach ($plannedTasksRaw as $task) { if (in_array($task->taskable_type, [ 'App\Models\Spraying', 'App\Models\Watering', 'App\Models\Fertilization', 'App\Models\Pruning' ]) && $task->taskable) { $task->treatment = Treatment::with('vineyardRow')->find($task->taskable->treatment_id); } } // Group planned tasks by type, date, and note $plannedTasks = $plannedTasksRaw->groupBy(function($task) { return $task->type . '|' . $task->planned_date->format('Y-m-d') . '|' . ($task->note ?? ''); })->map(function($group) { $first = $group->first(); $first->vineyard_rows = $group->map(function($task) { if ($task->taskable_type === VineyardRow::class) { return $task->taskable; } // For Treatment types, use the parent Treatment record if (isset($task->treatment) && $task->treatment) { return $task->treatment->vineyardRow; } // For Harvest, load the vineyardRow if it exists if ($task->taskable && method_exists($task->taskable, 'vineyardRow')) { return $task->taskable->vineyardRow; } return null; })->filter()->values(); // Map task IDs to their vineyard rows $first->task_rows = $group->map(function($task) { $row = null; if ($task->taskable_type === VineyardRow::class) { $row = $task->taskable; } elseif (isset($task->treatment) && $task->treatment) { $row = $task->treatment->vineyardRow; } elseif ($task->taskable && method_exists($task->taskable, 'vineyardRow')) { $row = $task->taskable->vineyardRow; } return $row ? [ 'task_id' => $task->planned_task_id, 'row_id' => $row->id, 'row' => $row, ] : null; })->filter()->values(); $first->task_count = $group->count(); return $first; })->values(); // Sort all planned tasks chronologically $allPlannedTasks = $plannedTasks->sortBy('planned_date')->values(); return view('winemaker.dashboard.planned-tasks', compact('allPlannedTasks')); } /** * Display all completed activities. */ public function allCompletedActivities() { $completedActivities = collect(); // 1. Completed treatments and tasks $completedTasksRaw = PlannedTask::with(['taskable']) ->whereNotNull('execution_date') ->orderBy('execution_date', 'desc') ->get(); // Load parent Treatment records for treatment types foreach ($completedTasksRaw as $task) { if (in_array($task->taskable_type, [ 'App\Models\Spraying', 'App\Models\Watering', 'App\Models\Fertilization', 'App\Models\Pruning' ]) && $task->taskable) { $task->treatment = Treatment::with('vineyardRow')->find($task->taskable->treatment_id); } } // Group completed tasks by type, execution date, and note $completedTasks = $completedTasksRaw->groupBy(function($task) { return $task->type . '|' . $task->execution_date->format('Y-m-d') . '|' . ($task->note ?? ''); })->map(function($group) { $first = $group->first(); $first->vineyard_rows = $group->map(function($task) { if ($task->taskable_type === VineyardRow::class) { return $task->taskable; } // For Treatment types, use the parent Treatment record if (isset($task->treatment) && $task->treatment) { return $task->treatment->vineyardRow; } // For Harvest, load the vineyardRow if it exists if ($task->taskable && method_exists($task->taskable, 'vineyardRow')) { return $task->taskable->vineyardRow; } return null; })->filter()->values(); $first->task_count = $group->count(); $first->activity_type = 'task'; $first->activity_date = $first->execution_date; return $first; })->values(); $completedActivities = $completedActivities->concat($completedTasks); // 2. All wine productions (bottling/blending) $allProductions = WineProduction::with(['wine.grapeVariety', 'harvest.vineyardRow.varietyVariation']) ->orderBy('created_at', 'desc') ->get(); // Group by wine to detect blends $productionsByWine = $allProductions->groupBy('wine_id'); foreach ($productionsByWine as $wineId => $productions) { $wine = $productions->first()->wine; if (!$wine) continue; $activity = (object)[ 'activity_type' => 'production', 'activity_date' => $productions->first()->created_at, 'wine' => $wine, 'productions' => $productions, 'is_blend' => $productions->count() > 1, 'total_weight' => $productions->sum('consumed_weight'), ]; $completedActivities->push($activity); } // 3. All harvests (not from planned tasks) $allHarvests = Harvest::with(['vineyardRow.varietyVariation.grapeVariety', 'plannedTask']) ->orderBy('date', 'desc') ->get() ->map(function($harvest) { $existingTask = PlannedTask::where('taskable_type', Harvest::class) ->where('taskable_id', $harvest->id) ->whereNotNull('execution_date') ->exists(); if ($existingTask) { return null; } // Use execution_date from plannedTask if available, otherwise use harvest date $activityDate = ($harvest->plannedTask && $harvest->plannedTask->execution_date) ? $harvest->plannedTask->execution_date : $harvest->date; return (object)[ 'activity_type' => 'harvest', 'activity_date' => $activityDate, 'harvest' => $harvest, ]; }) ->filter(); $completedActivities = $completedActivities->concat($allHarvests); // Sort all completed activities by date (most recent first) $completedActivities = $completedActivities ->sortByDesc('activity_date') ->values(); return view('winemaker.dashboard.completed-activities', compact('completedActivities')); } }