ClassPackageUnitVariationService.php 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. <?php
  2. namespace App\Services;
  3. use App\Models\ClassPackageUnit;
  4. use App\Models\ClassPackageUnitVariation;
  5. use Illuminate\Database\Eloquent\Collection;
  6. class ClassPackageUnitVariationService
  7. {
  8. public function getAll(int $packageUnitId, int $unitId): Collection
  9. {
  10. return ClassPackageUnitVariation::with('products.product')
  11. ->whereHas('classPackageUnit', fn ($query) => $query->where('unit_id', $unitId))
  12. ->where('class_package_unit_id', $packageUnitId)
  13. ->get();
  14. }
  15. public function findById(int $id, int $packageUnitId, int $unitId): ClassPackageUnitVariation
  16. {
  17. return ClassPackageUnitVariation::with('products.product')
  18. ->whereHas('classPackageUnit', fn ($query) => $query->where('unit_id', $unitId))
  19. ->where('class_package_unit_id', $packageUnitId)
  20. ->findOrFail($id);
  21. }
  22. public function create(int $packageUnitId, int $unitId, array $data): ClassPackageUnitVariation
  23. {
  24. $packageUnit = ClassPackageUnit::with('products')
  25. ->where('unit_id', $unitId)
  26. ->findOrFail($packageUnitId);
  27. // sem lista propria a proposta herda os materiais do pacote da unidade
  28. $materials = $data['materials'] ?? $this->unitMaterials($packageUnit);
  29. unset($data['materials']);
  30. // o valor do material nao e editavel, ele acompanha a lista
  31. $data['material_value'] = $this->calcMaterialValue($materials);
  32. $data['class_package_unit_id'] = $packageUnit->id;
  33. $variation = ClassPackageUnitVariation::create($data);
  34. $this->syncProducts($variation, $materials);
  35. return $variation->load('products.product');
  36. }
  37. public function update(int $id, int $packageUnitId, int $unitId, array $data): ClassPackageUnitVariation
  38. {
  39. $variation = $this->findById($id, $packageUnitId, $unitId);
  40. $materials = $data['materials'] ?? null;
  41. unset($data['materials']);
  42. if ($materials !== null) {
  43. $data['material_value'] = $this->calcMaterialValue($materials);
  44. }
  45. $variation->update($data);
  46. if ($materials !== null) {
  47. $this->syncProducts($variation, $materials);
  48. }
  49. return $variation->fresh('products.product');
  50. }
  51. public function delete(int $id, int $packageUnitId, int $unitId): bool
  52. {
  53. $variation = $this->findById($id, $packageUnitId, $unitId);
  54. return $variation->delete();
  55. }
  56. // Add custom business logic methods here
  57. private function calcMaterialValue(array $materials): float
  58. {
  59. return array_reduce($materials, fn ($carry, $material) => $carry + ($material['quantity'] * $material['price']), 0.0);
  60. }
  61. private function syncProducts(ClassPackageUnitVariation $variation, array $materials): void
  62. {
  63. $variation->products()->delete();
  64. foreach ($materials as $material) {
  65. $variation->products()->create([
  66. 'product_id' => $material['product_id'],
  67. 'quantity' => $material['quantity'],
  68. 'price' => $material['price'],
  69. ]);
  70. }
  71. }
  72. private function unitMaterials(ClassPackageUnit $packageUnit): array
  73. {
  74. return $packageUnit->products
  75. ->map(fn ($product) => [
  76. 'product_id' => $product->product_id,
  77. 'quantity' => $product->quantity,
  78. 'price' => (float) $product->price,
  79. ])
  80. ->all();
  81. }
  82. }