251 lines
9.6 KiB
PHP
251 lines
9.6 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Models\Harvest;
|
|
use App\Models\VineyardRow;
|
|
use App\Models\VarietyVariation;
|
|
use App\Models\Wine;
|
|
use App\Models\WineProduction;
|
|
use App\Models\GrapeVariety;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Auth;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
class HarvestController extends Controller
|
|
{
|
|
/**
|
|
* Display a listing of harvests.
|
|
*/
|
|
public function index()
|
|
{
|
|
$harvests = Harvest::with('vineyardRow.varietyVariation.grapeVariety', 'varietyVariation.grapeVariety', 'user', 'plannedTask')
|
|
->orderBy('date', 'desc')
|
|
->paginate(15);
|
|
|
|
return view('harvests.index', compact('harvests'));
|
|
}
|
|
|
|
/**
|
|
* Show the form for creating a new harvest.
|
|
*/
|
|
public function create()
|
|
{
|
|
$vineyardRows = VineyardRow::with('varietyVariation.grapeVariety')->get();
|
|
$varietyVariations = VarietyVariation::with('grapeVariety')->get();
|
|
|
|
return view('harvests.create', compact('vineyardRows', 'varietyVariations'));
|
|
}
|
|
|
|
/**
|
|
* Store a newly created harvest in storage.
|
|
*/
|
|
public function store(Request $request)
|
|
{
|
|
$validated = $request->validate([
|
|
'vineyard_row_id' => 'required|exists:vineyard_rows,id',
|
|
'variety_variation_id' => 'required|exists:variety_variations,id',
|
|
'weight' => 'required|numeric|min:0',
|
|
'sugar_content' => 'nullable|numeric|min:0|max:50',
|
|
'date' => 'required|date',
|
|
'quality' => 'nullable|in:excellent,good,fair,poor',
|
|
'grape_condition' => 'nullable|string|max:255',
|
|
'notes' => 'nullable|string',
|
|
'weather_conditions' => 'nullable|string',
|
|
'harvest_time' => 'nullable|date_format:H:i',
|
|
]);
|
|
|
|
$validated['user_id'] = Auth::id();
|
|
|
|
$harvest = Harvest::create($validated);
|
|
|
|
return redirect()->route('harvests.show', $harvest)
|
|
->with('success', 'Harvest recorded successfully.');
|
|
}
|
|
|
|
/**
|
|
* Display the specified harvest.
|
|
*/
|
|
public function show(Harvest $harvest)
|
|
{
|
|
$harvest->load('vineyardRow.varietyVariation.grapeVariety', 'varietyVariation.grapeVariety', 'user', 'wines', 'plannedTask');
|
|
|
|
return view('harvests.show', compact('harvest'));
|
|
}
|
|
|
|
/**
|
|
* Show the form for editing the specified harvest.
|
|
*/
|
|
public function edit(Harvest $harvest)
|
|
{
|
|
$vineyardRows = VineyardRow::with('varietyVariation.grapeVariety')->get();
|
|
$varietyVariations = VarietyVariation::with('grapeVariety')->get();
|
|
|
|
return view('harvests.edit', compact('harvest', 'vineyardRows', 'varietyVariations'));
|
|
}
|
|
|
|
/**
|
|
* Update the specified harvest in storage.
|
|
*/
|
|
public function update(Request $request, Harvest $harvest)
|
|
{
|
|
$validated = $request->validate([
|
|
'vineyard_row_id' => 'required|exists:vineyard_rows,id',
|
|
'variety_variation_id' => 'required|exists:variety_variations,id',
|
|
'weight' => 'required|numeric|min:0',
|
|
'sugar_content' => 'nullable|numeric|min:0|max:50',
|
|
'date' => 'required|date',
|
|
'quality' => 'nullable|in:excellent,good,fair,poor',
|
|
'grape_condition' => 'nullable|string|max:255',
|
|
'notes' => 'nullable|string',
|
|
'weather_conditions' => 'nullable|string',
|
|
'harvest_time' => 'nullable|date_format:H:i',
|
|
]);
|
|
|
|
$harvest->update($validated);
|
|
|
|
return redirect()->route('harvests.show', $harvest)
|
|
->with('success', 'Harvest updated successfully.');
|
|
}
|
|
|
|
/**
|
|
* Remove the specified harvest from storage.
|
|
*/
|
|
public function destroy(Harvest $harvest)
|
|
{
|
|
// Check if there are wines in the cellar made from this harvest
|
|
if ($harvest->hasWinesInCellar()) {
|
|
return redirect()->route('winemaker.harvests.index')
|
|
->with('error', 'Cannot delete harvest: There are still wines in the cellar made from this harvest. Wait until all wines are sold out.');
|
|
}
|
|
|
|
$harvest->delete();
|
|
|
|
return redirect()->route('winemaker.harvests.index')
|
|
->with('success', 'Harvest record deleted successfully.');
|
|
}
|
|
|
|
/**
|
|
* Display harvests for winemaker (with wine production status).
|
|
* Only shows completed harvests (with actual harvest data).
|
|
*/
|
|
public function winemakerIndex()
|
|
{
|
|
$harvests = Harvest::with(['vineyardRow', 'varietyVariation.grapeVariety', 'user', 'wines', 'plannedTask'])
|
|
->where('weight', '>', 0) // Only show harvests with actual weight (completed harvests)
|
|
->where(function ($query) {
|
|
$query->whereHas('plannedTask', function ($sub) {
|
|
$sub->whereNotNull('execution_date');
|
|
})->orWhereDoesntHave('plannedTask');
|
|
})
|
|
->orderByRaw(
|
|
'COALESCE((select execution_date from planned_tasks where planned_tasks.taskable_type = ? and planned_tasks.taskable_id = harvests.id limit 1), harvests.date) desc',
|
|
[Harvest::class]
|
|
)
|
|
->paginate(15);
|
|
|
|
return view('winemaker.harvests.index', compact('harvests'));
|
|
}
|
|
|
|
/**
|
|
* Show the form for bottling wine from a harvest.
|
|
*/
|
|
public function bottleForm($id)
|
|
{
|
|
$harvest = Harvest::with(['vineyardRow', 'varietyVariation.grapeVariety', 'user', 'plannedTask'])
|
|
->findOrFail($id);
|
|
|
|
return view('winemaker.harvests.bottle', compact('harvest'));
|
|
}
|
|
|
|
/**
|
|
* Store a new wine from harvest (bottling process).
|
|
*/
|
|
public function bottleStore(Request $request)
|
|
{
|
|
$validated = $request->validate([
|
|
'harvest_id' => 'required|exists:harvests,id',
|
|
'weight_to_use' => 'required|numeric|min:0.01',
|
|
'wine_name' => 'required|string|max:255',
|
|
'vintage' => 'required|integer|min:1900|max:' . (date('Y') + 1),
|
|
'wine_type' => 'required|in:red,white,rose',
|
|
'sweetness' => 'required|in:dry,semi_dry,semi_sweet,sweet',
|
|
'alcohol_percentage' => 'required|numeric|min:0|max:20',
|
|
'bottles_produced' => 'required|integer|min:1',
|
|
'bottle_volume' => 'nullable|numeric|min:0.1|max:10',
|
|
'production_date' => 'required|date',
|
|
'bottling_date' => 'nullable|date',
|
|
'status' => 'required|in:in_production,aging,ready,sold_out',
|
|
'price_per_bottle' => 'nullable|numeric|min:0',
|
|
'description' => 'nullable|string',
|
|
'image' => 'nullable|image|mimes:jpeg,jpg,png,webp|max:2048',
|
|
]);
|
|
|
|
try {
|
|
DB::beginTransaction();
|
|
|
|
// Get the harvest
|
|
$harvest = Harvest::with('varietyVariation.grapeVariety')->findOrFail($validated['harvest_id']);
|
|
|
|
// Validate weight to use doesn't exceed available weight
|
|
if ($validated['weight_to_use'] > $harvest->remaining_weight) {
|
|
return back()
|
|
->withInput()
|
|
->with('error', 'Cannot use ' . $validated['weight_to_use'] . ' kg. Only ' . number_format($harvest->remaining_weight, 2) . ' kg available.');
|
|
}
|
|
|
|
// Get or find the grape variety
|
|
$grapeVariety = $harvest->varietyVariation->grapeVariety;
|
|
|
|
// Handle image upload
|
|
$imagePath = null;
|
|
if ($request->hasFile('image')) {
|
|
$imagePath = $request->file('image')->store('wines', 'public');
|
|
|
|
}
|
|
|
|
// Create the wine
|
|
$wine = Wine::create([
|
|
'wine_name' => $validated['wine_name'],
|
|
'vintage' => $validated['vintage'],
|
|
'grape_variety_id' => $grapeVariety->id,
|
|
'wine_type' => $validated['wine_type'],
|
|
'sweetness' => $validated['sweetness'],
|
|
'alcohol_percentage' => $validated['alcohol_percentage'],
|
|
'bottles_produced' => $validated['bottles_produced'],
|
|
'bottles_in_stock' => $validated['bottles_produced'], // Initially all bottles are in stock
|
|
'bottle_volume' => $validated['bottle_volume'] ?? 0.75,
|
|
'production_date' => $validated['production_date'],
|
|
'bottling_date' => $validated['bottling_date'],
|
|
'status' => $validated['status'],
|
|
'price_per_bottle' => $validated['price_per_bottle'],
|
|
'description' => $validated['description'],
|
|
'image_url' => $imagePath,
|
|
]);
|
|
|
|
// Create wine production record (link harvest to wine with specified weight)
|
|
WineProduction::create([
|
|
'wine_id' => $wine->id,
|
|
'harvest_id' => $harvest->id,
|
|
'consumed_weight' => $validated['weight_to_use'], // Use specified weight
|
|
'blend_percentage' => 100.00, // 100% from this harvest
|
|
]);
|
|
|
|
DB::commit();
|
|
|
|
$message = 'Wine bottled successfully from harvest #' . $harvest->id . ' using ' . number_format($validated['weight_to_use'], 2) . ' kg';
|
|
if ($harvest->remaining_weight - $validated['weight_to_use'] > 0.01) {
|
|
$message .= '. Remaining: ' . number_format($harvest->remaining_weight - $validated['weight_to_use'], 2) . ' kg';
|
|
}
|
|
|
|
return redirect()->route('winemaker.cellar.index')
|
|
->with('success', $message);
|
|
|
|
} catch (\Exception $e) {
|
|
DB::rollBack();
|
|
return back()
|
|
->withInput()
|
|
->with('error', 'Failed to bottle wine: ' . $e->getMessage());
|
|
}
|
|
}
|
|
}
|