with([ 'prices' => fn ($query) => $query ->orderBy('created_at') ->with('rawMaterial:id,unit'), ]) ->when($tableQuery['search'] !== '', function (Builder $query) use ($tableQuery): void { $search = $tableQuery['search']; $query->where(function (Builder $query) use ($search): void { $query->where('name', 'like', "%{$search}%") ->orWhereHas('prices', fn (Builder $query) => $query->where('variant', 'like', "%{$search}%")); }); }) ->when( $isActive !== '', fn (Builder $query) => $query->where('is_active', $isActive === '1') ); $this->applySorting($query, $tableQuery['sort'], $tableQuery['direction']); return $query ->paginate(10) ->withQueryString(); } /** * @param array $validated */ public function create(array $validated): void { DB::transaction(function () use ($validated): void { $rawMaterial = RawMaterial::create([ 'name' => $validated['name'], 'unit' => $validated['unit'], ]); foreach ($validated['prices'] as $priceData) { $this->createPrice($rawMaterial, $priceData); } }); } /** * @param array $validated */ public function update(RawMaterial $rawMaterial, array $validated): void { DB::transaction(function () use ($validated, $rawMaterial): void { $rawMaterial->name = $validated['name']; $rawMaterial->unit = $validated['unit']; $rawMaterial->save(); $submittedPriceIds = collect($validated['prices']) ->pluck('id') ->filter() ->map(fn ($id) => (int) $id) ->all(); $rawMaterial->prices() ->whereNotIn('id', $submittedPriceIds) ->get() ->each(fn (RawMaterialPrice $price) => $price->delete()); foreach ($validated['prices'] as $priceData) { if (! empty($priceData['id'])) { $price = $rawMaterial->prices()->findOrFail($priceData['id']); $price->variant = $priceData['variant']; $price->price = $priceData['price']; $price->stock = $priceData['stock']; $price->save(); continue; } $this->createPrice($rawMaterial, $priceData); } }); } public function toggleStatus(RawMaterial $rawMaterial, bool $isActive): void { $rawMaterial->is_active = $isActive; $rawMaterial->save(); } public function delete(RawMaterial $rawMaterial): void { DB::transaction(function () use ($rawMaterial): void { $rawMaterial->prices()->delete(); $rawMaterial->delete(); }); } private function applySorting(Builder $query, string $sort, string $direction): void { if (in_array($sort, ['name', 'unit', 'is_active'], true)) { $query->orderBy($sort, $direction); return; } $query->latest(); } /** * @param array $priceData */ private function createPrice(RawMaterial $rawMaterial, array $priceData): RawMaterialPrice { return $rawMaterial->prices()->create([ 'variant' => $priceData['variant'], 'price' => $priceData['price'], 'stock' => $priceData['stock'], ]); } }