ExportProductionOrdersService.php 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. <?php
  2. declare(strict_types=1);
  3. namespace App\Services\Export;
  4. use App\Models\File;
  5. use App\Models\ProductionOrder;
  6. use Illuminate\Support\Facades\Storage;
  7. use Illuminate\Support\Str;
  8. use PhpOffice\PhpSpreadsheet\Cell\DataType;
  9. use PhpOffice\PhpSpreadsheet\Spreadsheet;
  10. use PhpOffice\PhpSpreadsheet\Style\Alignment;
  11. use PhpOffice\PhpSpreadsheet\Style\Border;
  12. use PhpOffice\PhpSpreadsheet\Style\Fill;
  13. use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
  14. class ExportProductionOrdersService
  15. {
  16. public const HEADERS = [
  17. 'ID',
  18. 'Номер заказа',
  19. 'Год',
  20. 'Заказчик',
  21. 'Адрес объекта',
  22. 'Номер счёта',
  23. 'Дата счёта',
  24. 'Номер договора',
  25. 'Дата договора',
  26. 'Дата оплаты',
  27. 'Срок поставки, раб. дней',
  28. 'Дата отгрузки по договору',
  29. 'Дата отгрузки по заявке',
  30. 'Статус',
  31. 'Тип исполнения',
  32. 'Менеджер',
  33. 'Оборудование',
  34. 'Примечание',
  35. ];
  36. /** @param list<int> $orderIds */
  37. public function handle(array $orderIds, int $userId): File
  38. {
  39. $spreadsheet = new Spreadsheet;
  40. $sheet = $spreadsheet->getActiveSheet();
  41. $sheet->setTitle('График заказов');
  42. $sheet->fromArray(self::HEADERS, null, 'A1');
  43. $sheet->getStyle('A1:R1')->getFont()->setBold(true);
  44. $sheet->getStyle('A1:R1')->getFill()
  45. ->setFillType(Fill::FILL_SOLID)
  46. ->getStartColor()->setARGB('FFD9EAF7');
  47. $row = 2;
  48. ProductionOrder::query()
  49. ->with(['manager', 'items.catalogItem'])
  50. ->whereKey($orderIds)
  51. ->orderByDesc('created_at')
  52. ->orderByDesc('id')
  53. ->chunk(200, function ($orders) use ($sheet, &$row): void {
  54. foreach ($orders as $order) {
  55. $sheet->setCellValue("A{$row}", $order->id);
  56. $sheet->setCellValueExplicit("B{$row}", $order->order_number, DataType::TYPE_STRING);
  57. $sheet->setCellValue("C{$row}", $order->order_year);
  58. $sheet->setCellValue("D{$row}", $order->customer_name);
  59. $sheet->setCellValue("E{$row}", $order->object_address);
  60. $sheet->setCellValueExplicit("F{$row}", $order->invoice_number, DataType::TYPE_STRING);
  61. $sheet->setCellValue("G{$row}", $order->invoice_date?->format('d.m.Y'));
  62. $sheet->setCellValueExplicit("H{$row}", (string) $order->contract_number, DataType::TYPE_STRING);
  63. $sheet->setCellValue("I{$row}", $order->contract_date?->format('d.m.Y'));
  64. $sheet->setCellValue("J{$row}", $order->payment_date?->format('d.m.Y'));
  65. $sheet->setCellValue("K{$row}", $order->supply_working_days);
  66. $sheet->setCellValue("L{$row}", $order->contract_shipment_date?->format('d.m.Y'));
  67. $sheet->setCellValue("M{$row}", $order->application_shipment_date?->format('d.m.Y'));
  68. $sheet->setCellValue("N{$row}", $order->statusLabel());
  69. $sheet->setCellValue("O{$row}", $order->executionTypeLabel());
  70. $sheet->setCellValue("P{$row}", $order->manager?->name);
  71. $sheet->setCellValue("Q{$row}", $this->equipmentSummary($order));
  72. $sheet->setCellValue("R{$row}", $order->note);
  73. $row++;
  74. }
  75. });
  76. $lastRow = max(1, $row - 1);
  77. $sheet->getStyle("A1:R{$lastRow}")->getBorders()->getAllBorders()->setBorderStyle(Border::BORDER_THIN);
  78. $sheet->getStyle("A1:R{$lastRow}")->getAlignment()->setWrapText(true)->setVertical(Alignment::VERTICAL_TOP);
  79. $sheet->freezePane('A2');
  80. $sheet->setAutoFilter("A1:R{$lastRow}");
  81. foreach (range('A', 'R') as $column) {
  82. $sheet->getColumnDimension($column)->setWidth(in_array($column, ['D', 'E', 'Q', 'R'], true) ? 36 : 18);
  83. }
  84. $filename = 'График_заказов_'.now()->format('Y-m-d_H-i-s').'.xlsx';
  85. $path = 'generated/production-orders/'.$userId.'/'.Str::uuid().'/'.$filename;
  86. Storage::disk('local')->makeDirectory(dirname($path));
  87. (new Xlsx($spreadsheet))->save(Storage::disk('local')->path($path));
  88. $spreadsheet->disconnectWorksheets();
  89. $file = File::query()->create([
  90. 'user_id' => $userId,
  91. 'original_name' => $filename,
  92. 'mime_type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
  93. 'path' => $path,
  94. 'link' => '',
  95. 'is_generated' => true,
  96. ]);
  97. $file->update(['link' => route('schedule.orders.files.download', $file)]);
  98. return $file;
  99. }
  100. private function equipmentSummary(ProductionOrder $order): string
  101. {
  102. return $order->items
  103. ->groupBy(static fn ($item): string => implode('|', [
  104. $item->catalogItem?->article,
  105. $item->catalogItem?->calculator_name ?: $item->catalogItem?->print_name,
  106. ]))
  107. ->map(static function ($items): string {
  108. $item = $items->first();
  109. $name = $item->catalogItem?->calculator_name ?: $item->catalogItem?->print_name;
  110. $label = collect([$item->catalogItem?->article, $name])
  111. ->filter(static fn ($value): bool => filled($value))
  112. ->implode(' — ');
  113. return ($label !== '' ? $label.' — ' : '').$items->count().' шт.';
  114. })
  115. ->implode("\n");
  116. }
  117. }