where('unit_id', $unitId) ->where('visible', true) ->orderBy('name') ->get(); } public function getAllByUnit(int $unitId): Collection { return ClassPackageUnit::with('products.product') ->where('unit_id', $unitId) ->orderBy('name') ->get(); } public function findById(int $id): ?ClassPackageUnit { return ClassPackageUnit::with('products.product')->find($id); } public function create(array $data): ClassPackageUnit { $materials = $data['materials'] ?? []; unset($data['materials']); $data['contract_material_value'] = $this->calcMaterialValue($materials); $packageUnit = ClassPackageUnit::create($data); $this->syncProducts($packageUnit, $materials); return $packageUnit->load('products.product'); } public function update(int $id, array $data): ?ClassPackageUnit { $packageUnit = $this->findById($id); if (!$packageUnit) return null; $materials = $data['materials'] ?? null; unset($data['materials']); if ($materials !== null) { $data['contract_material_value'] = $this->calcMaterialValue($materials); } $packageUnit->update($data); if ($materials !== null) { $this->syncProducts($packageUnit, $materials); } return $packageUnit->fresh('products.product'); } public function toggleVisibility(int $id): ?ClassPackageUnit { $packageUnit = ClassPackageUnit::find($id); if (!$packageUnit) return null; $packageUnit->update(['visible' => !$packageUnit->visible]); return $packageUnit->fresh(); } public function delete(int $id): bool { $packageUnit = ClassPackageUnit::find($id); if (!$packageUnit) return false; return $packageUnit->delete(); } /** * Sync products on an existing ClassPackageUnit from the base package. */ public function syncProductsFromBasePackage(ClassPackageUnit $packageUnit, \App\Models\ClassPackage $basePackage): void { $packageUnit->products()->delete(); $basePackage->products->each(function ($product) use ($packageUnit) { ClassPackageUnitProduct::create([ 'class_package_unit_id' => $packageUnit->id, 'product_id' => $product->id, 'quantity' => $product->pivot->quantity, 'price' => $product->pivot->price, ]); }); } public function replicateFromBasePackage(int $unitId, \App\Models\ClassPackage $basePackage): ClassPackageUnit { $packageUnit = ClassPackageUnit::create([ 'unit_id' => $unitId, 'class_package_id' => $basePackage->id, 'name' => $basePackage->name, 'quantity_classes' => $basePackage->quantity_classes, 'contract_value' => $basePackage->contract_value, 'contract_material_value' => $basePackage->contract_material_value, 'contract_register_value' => $basePackage->contract_register_value, 'contrat_discount_value' => $basePackage->contrat_discount_value, 'visible' => true, ]); $basePackage->products->each(function ($product) use ($packageUnit) { ClassPackageUnitProduct::create([ 'class_package_unit_id' => $packageUnit->id, 'product_id' => $product->id, 'quantity' => $product->pivot->quantity, 'price' => $product->pivot->price, ]); }); return $packageUnit; } private function syncProducts(ClassPackageUnit $packageUnit, array $materials): void { $packageUnit->products()->delete(); foreach ($materials as $m) { ClassPackageUnitProduct::create([ 'class_package_unit_id' => $packageUnit->id, 'product_id' => $m['product_id'], 'quantity' => $m['quantity'], 'price' => $m['price'], ]); } } private function calcMaterialValue(array $materials): float { return array_reduce($materials, fn($carry, $m) => $carry + ($m['quantity'] * $m['price']), 0.0); } }