ProductionOrderPlanningService.php 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. <?php
  2. declare(strict_types=1);
  3. namespace App\Services;
  4. use App\Enums\ProductionOrderActivityType;
  5. use App\Models\ProductionOrder;
  6. use App\Models\ProductionOrderDelivery;
  7. use App\Models\ProductionOrderInstallation;
  8. use App\Models\Schedule;
  9. use App\Models\User;
  10. use Illuminate\Support\Facades\DB;
  11. class ProductionOrderPlanningService
  12. {
  13. /** @param array<string, mixed> $data */
  14. public function createDelivery(ProductionOrder $order, array $data, User $actor): ProductionOrderDelivery
  15. {
  16. return DB::transaction(function () use ($order, $data, $actor): ProductionOrderDelivery {
  17. unset($data['nav']);
  18. $delivery = $order->deliveries()->create($data + [
  19. 'created_by' => $actor->id,
  20. 'updated_by' => $actor->id,
  21. ]);
  22. $order->activities()->create([
  23. 'type' => ProductionOrderActivityType::DeliveryScheduled,
  24. 'user_id' => $actor->id,
  25. 'delivery_id' => $delivery->id,
  26. 'message' => sprintf(
  27. 'Назначена доставка на %s, водитель %s.',
  28. $delivery->delivery_date->format('d.m.Y'),
  29. $delivery->driver()->value('name') ?? '—',
  30. ),
  31. ]);
  32. return $delivery;
  33. });
  34. }
  35. /** @param array<string, mixed> $data */
  36. public function updateDelivery(ProductionOrderDelivery $delivery, array $data, User $actor): void
  37. {
  38. unset($data['nav']);
  39. $delivery->update($data + ['updated_by' => $actor->id]);
  40. }
  41. public function deleteDelivery(ProductionOrderDelivery $delivery): void
  42. {
  43. $delivery->delete();
  44. }
  45. /** @param array<string, mixed> $data */
  46. public function createInstallation(ProductionOrder $order, array $data, User $actor): ProductionOrderInstallation
  47. {
  48. return DB::transaction(function () use ($order, $data, $actor): ProductionOrderInstallation {
  49. unset($data['nav']);
  50. $installation = $order->installations()->create($data + [
  51. 'created_by' => $actor->id,
  52. 'updated_by' => $actor->id,
  53. ]);
  54. $order->activities()->create([
  55. 'type' => ProductionOrderActivityType::InstallationScheduled,
  56. 'user_id' => $actor->id,
  57. 'installation_id' => $installation->id,
  58. 'message' => sprintf(
  59. 'Назначен монтаж на %s, бригадир %s.',
  60. $installation->installation_date->format('d.m.Y'),
  61. $installation->brigadier()->value('name') ?? '—',
  62. ),
  63. ]);
  64. $this->syncInstallationSchedules($installation);
  65. return $installation;
  66. });
  67. }
  68. /** @param array<string, mixed> $data */
  69. public function updateInstallation(ProductionOrderInstallation $installation, array $data, User $actor): void
  70. {
  71. DB::transaction(function () use ($installation, $data, $actor): void {
  72. unset($data['nav']);
  73. $installation->update($data + ['updated_by' => $actor->id]);
  74. $this->syncInstallationSchedules($installation);
  75. });
  76. }
  77. public function deleteInstallation(ProductionOrderInstallation $installation): void
  78. {
  79. DB::transaction(function () use ($installation): void {
  80. $installation->schedules()->delete();
  81. $installation->delete();
  82. });
  83. }
  84. private function syncInstallationSchedules(ProductionOrderInstallation $installation): void
  85. {
  86. $installation->schedules()->delete();
  87. $order = $installation->productionOrder()->with('items.catalogItem')->firstOrFail();
  88. $equipment = $order->items
  89. ->groupBy('common_catalog_item_id')
  90. ->map(static function ($items): string {
  91. $article = $items->first()->catalogItem?->article ?? 'Без артикула';
  92. return $article.' - '.$items->count();
  93. })
  94. ->implode("\r\n");
  95. for ($offset = 0; $offset < $installation->installation_days; $offset++) {
  96. Schedule::query()->create([
  97. 'production_order_installation_id' => $installation->id,
  98. 'address_code' => $order->order_number,
  99. 'source' => Schedule::SOURCE_PRODUCTION_ORDER,
  100. 'installation_date' => $installation->installation_date->addDays($offset)->toDateString(),
  101. 'manual' => false,
  102. 'district_id' => null,
  103. 'area_id' => null,
  104. 'object_address' => $order->object_address,
  105. 'object_type' => $order->executionTypeLabel(),
  106. 'mafs' => $equipment,
  107. 'mafs_count' => $order->items->count(),
  108. 'brigadier_id' => $installation->brigadier_id,
  109. 'comment' => $installation->note,
  110. ]);
  111. }
  112. }
  113. }