ExportScheduleService.php 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. <?php
  2. namespace App\Services;
  3. use App\Helpers\DateHelper;
  4. use App\Models\Product;
  5. use Illuminate\Support\Collection;
  6. use Illuminate\Support\Facades\Log;
  7. use Illuminate\Support\Facades\Storage;
  8. use Illuminate\Support\Str;
  9. use PhpOffice\PhpSpreadsheet\IOFactory;
  10. use PhpOffice\PhpSpreadsheet\Style\Alignment;
  11. use PhpOffice\PhpSpreadsheet\Style\Border;
  12. use PhpOffice\PhpSpreadsheet\Style\Color;
  13. use PhpOffice\PhpSpreadsheet\Style\Fill;
  14. use PhpOffice\PhpSpreadsheet\Worksheet\PageSetup;
  15. use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
  16. use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
  17. class ExportScheduleService
  18. {
  19. private const DATA_START_ROW = 3;
  20. private const DATA_END_COLUMN = 'K';
  21. private const PDF_ROWS_PER_PAGE = 24;
  22. /**
  23. * @throws \Exception
  24. */
  25. public function handle(Collection $schedules, int $userId): string
  26. {
  27. $spreadsheet = $this->buildSpreadsheet($schedules);
  28. $sheet = $spreadsheet->getActiveSheet();
  29. $header = (string) $sheet->getCell('A1')->getValue();
  30. $fileName = $header . '.xlsx';
  31. $writer = new Xlsx($spreadsheet);
  32. $fd = 'export/schedule/tmp';
  33. Storage::disk('public')->makeDirectory($fd);
  34. $fp = storage_path('app/public/export/schedule/') . '/tmp/' . $fileName;
  35. Storage::disk('public')->delete($fd . '/' . $fileName);
  36. $writer->save($fp);
  37. PdfConverterClient::convert($fp);
  38. // create zip archive
  39. $fileModel = (new FileService())->createZipArchive($fd, Str::replace('.xlsx', '.zip', $fileName), $userId);
  40. // remove temp files
  41. Storage::disk('public')->deleteDirectory($fd);
  42. // return link
  43. return $fileModel?->link ?? '';
  44. }
  45. public function buildSpreadsheet(Collection $schedules): \PhpOffice\PhpSpreadsheet\Spreadsheet
  46. {
  47. $reader = IOFactory::createReader('Xlsx');
  48. $spreadsheet = $reader->load('./templates/Schedule.xlsx');
  49. $sheet = $spreadsheet->getActiveSheet();
  50. $sheet->getPageSetup()->setOrientation(PageSetup::ORIENTATION_LANDSCAPE);
  51. $row = self::DATA_START_ROW;
  52. $from = '-';
  53. $prevInstDate = null;
  54. $sameDateRows = 0;
  55. $rowsOnCurrentPage = 0;
  56. $lastScheduleDate = null;
  57. foreach ($schedules as $schedule) {
  58. if ($prevInstDate === null) {
  59. $from = $schedule->installation_date;
  60. $prevInstDate = $schedule->installation_date;
  61. $sameDateRows = 1;
  62. } elseif ($prevInstDate === $schedule->installation_date) {
  63. $sameDateRows++;
  64. } else {
  65. if ($sameDateRows > 1) {
  66. $this->mergeDateColumns($sheet, $row - $sameDateRows, $row - 1);
  67. }
  68. if ($rowsOnCurrentPage >= self::PDF_ROWS_PER_PAGE) {
  69. $sheet->setBreak('A' . $row, Worksheet::BREAK_ROW);
  70. $rowsOnCurrentPage = 0;
  71. }
  72. $sameDateRows = 1;
  73. $prevInstDate = $schedule->installation_date;
  74. }
  75. $sheet->setCellValue('A' . $row, DateHelper::getHumanDayOfWeek($schedule->installation_date));
  76. $sheet->setCellValue('B' . $row, DateHelper::getHumanDate($schedule->installation_date, true));
  77. $sheet->setCellValue('C' . $row, $schedule->address_code);
  78. $sheet->setCellValue('D' . $row, $schedule->district->shortname);
  79. $sheet->setCellValue('E' . $row, $schedule->area->name);
  80. $sheet->setCellValue('F' . $row, $schedule->object_address);
  81. $sheet->setCellValue('G' . $row, $schedule->object_type);
  82. $sheet->setCellValue('H' . $row, Str::trim($schedule->mafs));
  83. $sheet->setCellValue('I' . $row, $schedule->mafs_count);
  84. $sheet->setCellValue('J' . $row, $schedule->brigadier->name);
  85. $sheet->setCellValue('K' . $row, $schedule->comment);
  86. $sheet->getStyle('C' . $row . ':K' . $row)
  87. ->getFill()
  88. ->setFillType(Fill::FILL_SOLID)
  89. ->getStartColor()
  90. ->setRGB(Str::replace('#', '', $schedule->brigadier->color));
  91. $lastScheduleDate = $schedule->installation_date;
  92. $row++;
  93. $rowsOnCurrentPage++;
  94. }
  95. if ($sameDateRows > 1) {
  96. $this->mergeDateColumns($sheet, $row - $sameDateRows, $row - 1);
  97. }
  98. $lastDataRow = max($row - 1, 2);
  99. $sheet->getStyle('A2:B' . $lastDataRow)->getAlignment()->setTextRotation(90);
  100. $sheet->getStyle('A2:' . self::DATA_END_COLUMN . $lastDataRow)
  101. ->getBorders()
  102. ->getAllBorders()
  103. ->setBorderStyle(Border::BORDER_THIN)
  104. ->setColor(new Color('777777'));
  105. $sheet->getStyle('A2:' . self::DATA_END_COLUMN . $lastDataRow)
  106. ->getAlignment()
  107. ->setHorizontal(Alignment::HORIZONTAL_CENTER);
  108. $sheet->getStyle('C2:' . self::DATA_END_COLUMN . $lastDataRow)->getAlignment()->setWrapText(true);
  109. $this->configurePdfLayout($sheet, $lastDataRow);
  110. $fromText = DateHelper::isDate($from) ? DateHelper::getHumanDate($from) : '-';
  111. $toText = DateHelper::isDate((string) $lastScheduleDate) ? DateHelper::getHumanDate($lastScheduleDate) : '-';
  112. $header = 'График монтажей с ' . $fromText . ' по ' . $toText;
  113. $sheet->setCellValue('A1', $header);
  114. $sheet->getStyle('A1')->getFont()->setBold(true);
  115. return $spreadsheet;
  116. }
  117. private function mergeDateColumns(Worksheet $sheet, int $startRow, int $endRow): void
  118. {
  119. $sheet->mergeCells('A' . $startRow . ':A' . $endRow);
  120. $sheet->mergeCells('B' . $startRow . ':B' . $endRow);
  121. }
  122. private function configurePdfLayout(Worksheet $sheet, int $lastDataRow): void
  123. {
  124. $pageSetup = $sheet->getPageSetup();
  125. $pageSetup->setPaperSize(PageSetup::PAPERSIZE_A4);
  126. $pageSetup->setOrientation(PageSetup::ORIENTATION_LANDSCAPE);
  127. $pageSetup->setFitToWidth(1);
  128. $pageSetup->setFitToHeight(0);
  129. $sheet->getPageMargins()
  130. ->setTop(0.4)
  131. ->setBottom(0.4)
  132. ->setLeft(0.25)
  133. ->setRight(0.25);
  134. $pageSetup->setRowsToRepeatAtTopByStartAndEnd(1, 2);
  135. $pageSetup->setPrintArea('A1:' . self::DATA_END_COLUMN . $lastDataRow);
  136. }
  137. }