| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- <?php
- namespace App\Services;
- use App\Models\ClassPackage;
- use App\Models\Unit;
- use Illuminate\Database\Eloquent\Collection;
- class ClassPackageService
- {
- public function getAll(): Collection
- {
- return ClassPackage::orderBy('created_at', 'desc')->get();
- }
- public function getByUnit(int $unitId): Collection
- {
- return ClassPackage::whereHas('units', fn($q) => $q->where('units.id', $unitId)->where('visible', true))
- ->orderBy('name')
- ->get();
- }
- public function findById(int $id): ?ClassPackage
- {
- return ClassPackage::with(['units', 'products'])->find($id);
- }
- public function create(array $data): ClassPackage
- {
- $unitVisibilities = $data['unit_visibilities'] ?? [];
- $materials = $data['materials'] ?? [];
- unset($data['unit_visibilities'], $data['materials']);
- $data['contract_material_value'] = $this->calcMaterialValue($materials);
- $package = ClassPackage::create($data);
- $this->syncUnitVisibilities($package, $unitVisibilities);
- $this->syncMaterials($package, $materials);
- return $package->load(['units', 'products']);
- }
- public function update(int $id, array $data): ?ClassPackage
- {
- $package = $this->findById($id);
- if (!$package) return null;
- $unitVisibilities = $data['unit_visibilities'] ?? null;
- $materials = $data['materials'] ?? null;
- unset($data['unit_visibilities'], $data['materials']);
- if ($materials !== null) {
- $data['contract_material_value'] = $this->calcMaterialValue($materials);
- }
- $package->update($data);
- if ($unitVisibilities !== null) {
- $this->syncUnitVisibilities($package, $unitVisibilities);
- }
- if ($materials !== null) {
- $this->syncMaterials($package, $materials);
- }
- return $package->fresh(['units', 'products']);
- }
- public function delete(int $id): bool
- {
- $package = ClassPackage::find($id);
- if (!$package) return false;
- return $package->delete();
- }
- public function getAllUnitsWithVisibility(int $packageId): \Illuminate\Support\Collection
- {
- $allUnits = Unit::orderBy('fantasy_name')->get(['id', 'fantasy_name']);
- $package = ClassPackage::with('units')->find($packageId);
- $visibilityMap = $package
- ? $package->units->keyBy('id')
- : collect();
- return $allUnits->map(fn($unit) => [
- 'id' => $unit->id,
- 'fantasy_name' => $unit->fantasy_name,
- 'visible' => $visibilityMap->has($unit->id)
- ? (bool) $visibilityMap[$unit->id]->pivot->visible
- : true,
- ]);
- }
- private function syncUnitVisibilities(ClassPackage $package, array $unitVisibilities): void
- {
- $syncData = [];
- foreach ($unitVisibilities as $uv) {
- $syncData[$uv['unit_id']] = ['visible' => $uv['visible']];
- }
- $package->units()->sync($syncData);
- }
- private function syncMaterials(ClassPackage $package, array $materials): void
- {
- $syncData = [];
- foreach ($materials as $m) {
- $syncData[$m['product_id']] = [
- 'quantity' => $m['quantity'],
- 'price' => $m['price'],
- ];
- }
- $package->products()->sync($syncData);
- }
- private function calcMaterialValue(array $materials): float
- {
- return array_reduce($materials, fn($carry, $m) => $carry + ($m['quantity'] * $m['price']), 0.0);
- }
- }
|