duplicateGroups(); if ($groups === []) { $this->info('Nincs duplikált gyártónév ebben az adatbázisban.'); return self::SUCCESS; } $path = $this->option('path') ?: storage_path( 'app/private/gyarto_duplikaciok_' . now()->format('Y-m-d') . '.xlsx' ); $spreadsheet = new Spreadsheet(); $sheet = $spreadsheet->getActiveSheet(); $sheet->setTitle('Gyártó duplikációk'); $this->writeIntro($sheet); $headerRow = 8; $this->writeHeader($sheet, $headerRow); $lastRow = $this->writeGroups($sheet, $headerRow, $groups); $this->finishLayout($sheet, $headerRow, $lastRow, count($groups), $groups); $directory = dirname($path); if (! is_dir($directory)) { mkdir($directory, 0775, true); } (new Xlsx($spreadsheet))->save($path); $records = array_sum(array_map('count', $groups)); $this->info('Döntési lap elkészült: ' . $path); $this->line(' Csoportok: ' . count($groups) . ' | érintett gyártó rekord: ' . $records); return self::SUCCESS; } private function writeIntro($sheet): void { $sheet->setCellValue('A1', 'Gyártó nevek összevonása – döntési lap'); $sheet->getStyle('A1')->getFont()->setBold(true)->setSize(16); $sheet->setCellValue('A2', 'EV3-357 · Árlista feltöltés és feldolgozás újragondolása'); $sheet->setCellValue('A3', 'Adatforrás: ' . \DB::connection()->getDatabaseName() . ' adatbázis · Készült: ' . now()->format('Y-m-d H:i')); $sheet->setCellValue('A5', 'A rendszerben ugyanaz a gyártó több néven is szerepel – például ' . '"Danone" és "Danone " egy záró szóközzel, vagy "Pick" és "PICK". Ez két gondot okoz: az ' . 'árlista feldolgozó valódi változás nélkül is módosulást jelez, a statisztikában pedig egy ' . 'gyártóra szűrve a másik név alá könyvelt tételek kimaradnak a riportból.'); $sheet->mergeCells('A5:I5'); $sheet->getStyle('A5')->getAlignment()->setWrapText(true)->setVertical(Alignment::VERTICAL_TOP); $sheet->getRowDimension(5)->setRowHeight(46); $sheet->setCellValue('A6', 'TEENDŐ: minden csoportnál töltsd ki a sárga "VÉGLEGES NÉV" mezőt – ez lesz ' . 'a megmaradó, egységes név. Előre beírtuk a javaslatunkat: a legtöbb terméket tartalmazó ' . 'változat, szóközöktől megtisztítva. Ha egyetértesz vele, hagyd úgy. A kis- és nagybetűs ' . 'írásmód a te döntésed. A többi név nem vész el: összevonjuk őket a véglegesbe, a termékek ' . 'és a rendelési előzmények megmaradnak. Az "Azonosító" oszlopot kérjük ne módosítsd.'); $sheet->mergeCells('A6:I6'); $sheet->getStyle('A6')->getAlignment()->setWrapText(true)->setVertical(Alignment::VERTICAL_TOP); $sheet->getStyle('A6')->getFont()->setBold(true); $sheet->getRowDimension(6)->setRowHeight(64); } private function writeHeader($sheet, int $headerRow): void { $headers = [self::COLUMN_GROUP, self::COLUMN_ID, 'Gyártó neve a rendszerben', 'Eltérés', 'Termékek', 'Rendelési tételek', 'Létrehozva', self::COLUMN_FINAL_NAME, 'Megjegyzés']; foreach ($headers as $i => $text) { $sheet->setCellValueByColumnAndRow($i + 1, $headerRow, $text); } $range = 'A' . $headerRow . ':I' . $headerRow; $sheet->getStyle($range)->getFont()->setBold(true)->getColor()->setARGB('FFFFFFFF'); $sheet->getStyle($range)->getFill()->setFillType(Fill::FILL_SOLID) ->getStartColor()->setARGB('FF44546A'); $sheet->getStyle($range)->getAlignment()->setWrapText(true) ->setVertical(Alignment::VERTICAL_CENTER); $sheet->getRowDimension($headerRow)->setRowHeight(32); } private function writeGroups($sheet, int $headerRow, array $groups): int { $row = $headerRow + 1; $groupIndex = 0; foreach ($groups as $members) { $groupIndex++; $proposed = trim((string) $members[0]['producer']->name); $shade = $groupIndex % 2 === 0 ? 'FFF2F2F2' : 'FFFFFFFF'; $groupFirstRow = $row; foreach ($members as $index => $member) { $producer = $member['producer']; $name = (string) $producer->name; // A csoport sorszáma MINDEN soron szerepel: így a lap szűrhető és // rendezhető anélkül, hogy a csoportok összekeverednének. $sheet->setCellValue('A' . $row, $groupIndex); $sheet->setCellValue('B' . $row, $producer->id); $sheet->setCellValueExplicit('C' . $row, '"' . $name . '"', DataType::TYPE_STRING); $sheet->setCellValue('D' . $row, $index === 0 ? 'javasolt megtartani' : implode(', ', $this->describeDifference($name, $proposed))); $sheet->setCellValue('E' . $row, $member['counts']['products']); $sheet->setCellValue('F' . $row, $member['counts']['order_archives_items']); $sheet->setCellValue('G' . $row, substr((string) $producer->created_at, 0, 10)); $sheet->getStyle('A' . $row . ':I' . $row)->getFill() ->setFillType(Fill::FILL_SOLID)->getStartColor()->setARGB($shade); if ($index === 0) { $sheet->setCellValueExplicit('H' . $row, $proposed, DataType::TYPE_STRING); $sheet->getStyle('H' . $row)->getFill()->setFillType(Fill::FILL_SOLID) ->getStartColor()->setARGB('FFFFF2CC'); $sheet->getStyle('H' . $row)->getFont()->setBold(true); $sheet->getStyle('C' . $row)->getFont()->setBold(true); } $row++; } $sheet->getStyle('A' . $groupFirstRow . ':I' . ($row - 1))->getBorders()->getTop() ->setBorderStyle(Border::BORDER_THIN)->getColor()->setARGB('FFBFBFBF'); } return $row - 1; } /** * @return array */ private function describeDifference(string $name, string $proposed): array { $differences = []; if ($name !== trim($name)) { $differences[] = 'szóköz a név szélén'; } if (trim($name) !== $proposed && mb_strtoupper(trim($name)) === mb_strtoupper($proposed)) { $differences[] = 'eltérő kis/nagybetű'; } if (str_contains($name, '/') || str_contains($name, '_')) { $differences[] = 'eltérő elválasztó'; } if (preg_match('/\s{2,}/', $name)) { $differences[] = 'dupla szóköz'; } return $differences === [] ? ['eltérő írásmód'] : $differences; } private function finishLayout($sheet, int $headerRow, int $lastRow, int $groupCount, array $groups): void { $first = $headerRow + 1; $sheet->getStyle('E' . $first . ':F' . $lastRow)->getNumberFormat()->setFormatCode('# ##0'); $sheet->getStyle('A' . $first . ':B' . $lastRow)->getAlignment() ->setHorizontal(Alignment::HORIZONTAL_CENTER); $sheet->getStyle('H' . $first . ':H' . $lastRow)->getBorders()->getAllBorders() ->setBorderStyle(Border::BORDER_THIN)->getColor()->setARGB('FFBF8F00'); $widths = ['A' => 9, 'B' => 11, 'C' => 34, 'D' => 22, 'E' => 11, 'F' => 17, 'G' => 13, 'H' => 34, 'I' => 26]; foreach ($widths as $column => $width) { $sheet->getColumnDimension($column)->setWidth($width); } $sheet->freezePane('A' . $first); $sheet->setAutoFilter('A' . $headerRow . ':I' . $lastRow); $summaryRow = $lastRow + 2; $sheet->setCellValue('A' . $summaryRow, 'Összesen ' . $groupCount . ' gyártó-csoport, ' . array_sum(array_map('count', $groups)) . ' rekord. A csoportok többségénél mindkét névhez ' . 'tartoznak termékek, ezért az összevonás után is minden termék megmarad.'); $sheet->mergeCells('A' . $summaryRow . ':I' . $summaryRow); $sheet->getStyle('A' . $summaryRow)->getFont()->setItalic(true); } }