ADD EV3-357 a laza javaslatok eltérés-jelleg szerint kategorizálva
101 javaslat egy kupacban túl sok egy kézi átnézéshez, ráadásul nagyon eltérő mérlegelést igényelnek: a "Békás Kft." és a "Békás Kft" között nincs mit eldönteni, a "Dénes Natura" és a "Dénes Natura Kft" között viszont van. - ProducerDeduplicator::differenceCategory(): a LEGKEVÉSBÉ agresszív átalakítás, ami már egy kulcsra hozza a csoport tagjait - csak írásjel / egybeírás / ékezet / cégforma / vegyes. - a riport ebben a sorrendben írja ki a csoportokat (elöl a gyakorlatilag eldöntött esetek), és a "csak írásjel" kategóriánál előre beírja a javaslatot; a többinél a végleges név üresen marad, a javaslat a Megjegyzés oszlopban. A d2d másolaton: 14 csak írásjel (előre kitöltve, azonnal végrehajtható), 7 egybeírás, 8 ékezet, 72 cégforma - utóbbi 87 vár a megrendelő döntésére. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
4198c03f5a
commit
87cab4cad5
@ -33,8 +33,6 @@ class ProducersDedupeReport extends Command
|
|||||||
|
|
||||||
private const TYPE_CERTAIN = 'biztos';
|
private const TYPE_CERTAIN = 'biztos';
|
||||||
|
|
||||||
private const TYPE_REVIEW = 'ellenőrizendő';
|
|
||||||
|
|
||||||
public function handle(ProducerDeduplicator $deduplicator): int
|
public function handle(ProducerDeduplicator $deduplicator): int
|
||||||
{
|
{
|
||||||
$certain = $deduplicator->duplicateGroups();
|
$certain = $deduplicator->duplicateGroups();
|
||||||
@ -107,12 +105,14 @@ private function writeIntro($sheet, bool $hasLoose): void
|
|||||||
$sheet->getRowDimension(6)->setRowHeight(46);
|
$sheet->getRowDimension(6)->setRowHeight(46);
|
||||||
|
|
||||||
if ($hasLoose) {
|
if ($hasLoose) {
|
||||||
$sheet->setCellValue('A7', 'A "Típus" oszlop kétféle sort különböztet meg. A "' . self::TYPE_CERTAIN
|
$sheet->setCellValue('A7', 'A "Típus" oszlop megmutatja, miben térnek el a nevek – így kötegelve '
|
||||||
. '" csoportoknál a nevek csak írásmódban térnek el, ott már beírtuk a javaslatunkat. '
|
. 'tudsz haladni. A "' . ProducerDeduplicator::DIFF_PUNCTUATION . '" csoportoknál csak pont, '
|
||||||
. 'Az "' . self::TYPE_REVIEW . '" csoportoknál a nevek jobban különböznek (elírás, kötőjel, '
|
. 'kötőjel vagy vessző a különbség ("Békás Kft." és "Békás Kft"), ott már beírtuk a '
|
||||||
. 'egybeírás, hiányzó ékezet), ezért NEM töltöttük ki a végleges nevet: '
|
. 'javaslatot. A többinél ("' . ProducerDeduplicator::DIFF_SPACING . '", "'
|
||||||
|
. ProducerDeduplicator::DIFF_ACCENT . '", "' . ProducerDeduplicator::DIFF_COMPANY_FORM
|
||||||
|
. '") NEM töltöttük ki a végleges nevet, mert ott valódi döntés kell: '
|
||||||
. 'ha ugyanaz a cég, írd be a nevet (a javaslat a "Megjegyzés" oszlopban van); '
|
. 'ha ugyanaz a cég, írd be a nevet (a javaslat a "Megjegyzés" oszlopban van); '
|
||||||
. 'HA NEM UGYANAZ, HAGYD ÜRESEN – akkor nem nyúlunk hozzájuk.');
|
. 'HA NEM UGYANAZ A CÉG, HAGYD ÜRESEN – akkor nem nyúlunk hozzájuk.');
|
||||||
$sheet->mergeCells('A7:J7');
|
$sheet->mergeCells('A7:J7');
|
||||||
$sheet->getStyle('A7')->getAlignment()->setWrapText(true)->setVertical(Alignment::VERTICAL_TOP);
|
$sheet->getStyle('A7')->getAlignment()->setWrapText(true)->setVertical(Alignment::VERTICAL_TOP);
|
||||||
$sheet->getStyle('A7')->getFont()->setBold(true)->getColor()->setARGB('FF9C5700');
|
$sheet->getStyle('A7')->getFont()->setBold(true)->getColor()->setARGB('FF9C5700');
|
||||||
@ -138,24 +138,50 @@ private function writeHeader($sheet, int $headerRow): void
|
|||||||
$sheet->getRowDimension($headerRow)->setRowHeight(32);
|
$sheet->getRowDimension($headerRow)->setRowHeight(32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A laza javaslatok sorrendje: elöl a gyakorlatilag eldöntött esetek, hátul azok,
|
||||||
|
* amik valódi cégismeretet igényelnek. Így a megrendelő kötegelve tud haladni.
|
||||||
|
*/
|
||||||
|
private const CATEGORY_ORDER = [
|
||||||
|
ProducerDeduplicator::DIFF_PUNCTUATION,
|
||||||
|
ProducerDeduplicator::DIFF_SPACING,
|
||||||
|
ProducerDeduplicator::DIFF_ACCENT,
|
||||||
|
ProducerDeduplicator::DIFF_COMPANY_FORM,
|
||||||
|
ProducerDeduplicator::DIFF_MIXED,
|
||||||
|
];
|
||||||
|
|
||||||
private function writeGroups($sheet, int $headerRow, array $certain, array $loose): int
|
private function writeGroups($sheet, int $headerRow, array $certain, array $loose): int
|
||||||
{
|
{
|
||||||
$row = $headerRow + 1;
|
$row = $headerRow + 1;
|
||||||
$groupIndex = 0;
|
$groupIndex = 0;
|
||||||
|
|
||||||
foreach ([self::TYPE_CERTAIN => $certain, self::TYPE_REVIEW => $loose] as $type => $groups) {
|
foreach ($certain as $members) {
|
||||||
foreach ($groups as $members) {
|
|
||||||
$groupIndex++;
|
$groupIndex++;
|
||||||
$row = $this->writeGroup($sheet, $row, $groupIndex, $type, $members);
|
$row = $this->writeGroup($sheet, $row, $groupIndex, self::TYPE_CERTAIN, $members, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
$deduplicator = app(ProducerDeduplicator::class);
|
||||||
|
$byCategory = [];
|
||||||
|
foreach ($loose as $key => $members) {
|
||||||
|
$byCategory[$deduplicator->differenceCategory($members)][$key] = $members;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (self::CATEGORY_ORDER as $category) {
|
||||||
|
foreach ($byCategory[$category] ?? [] as $members) {
|
||||||
|
$groupIndex++;
|
||||||
|
// Az írásjel-eltérésnél nincs mérlegelnivaló (a "Kft." és a "Kft" ugyanaz),
|
||||||
|
// ezért ott előre beírjuk a javaslatot - a megrendelő így csak a valóban
|
||||||
|
// kérdéses eseteket nézi át tételesen.
|
||||||
|
$prefill = $category === ProducerDeduplicator::DIFF_PUNCTUATION;
|
||||||
|
$row = $this->writeGroup($sheet, $row, $groupIndex, $category, $members, ! $prefill);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $row - 1;
|
return $row - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function writeGroup($sheet, int $row, int $groupIndex, string $type, array $members): int
|
private function writeGroup($sheet, int $row, int $groupIndex, string $type, array $members, bool $isReview): int
|
||||||
{
|
{
|
||||||
$isReview = $type === self::TYPE_REVIEW;
|
|
||||||
$proposed = trim((string) $members[0]['producer']->name);
|
$proposed = trim((string) $members[0]['producer']->name);
|
||||||
$shade = $isReview ? 'FFFDF2E9' : ($groupIndex % 2 === 0 ? 'FFF2F2F2' : 'FFFFFFFF');
|
$shade = $isReview ? 'FFFDF2E9' : ($groupIndex % 2 === 0 ? 'FFF2F2F2' : 'FFFFFFFF');
|
||||||
$groupFirstRow = $row;
|
$groupFirstRow = $row;
|
||||||
|
|||||||
@ -32,6 +32,17 @@ class ProducerDeduplicator
|
|||||||
|
|
||||||
private const UPDATE_CHUNK = 5000;
|
private const UPDATE_CHUNK = 5000;
|
||||||
|
|
||||||
|
/** Az eltérés jellege egy laza jelölt-csoportban (lásd differenceCategory) */
|
||||||
|
public const DIFF_PUNCTUATION = 'csak írásjel';
|
||||||
|
|
||||||
|
public const DIFF_SPACING = 'egybeírás';
|
||||||
|
|
||||||
|
public const DIFF_ACCENT = 'ékezet';
|
||||||
|
|
||||||
|
public const DIFF_COMPANY_FORM = 'cégforma';
|
||||||
|
|
||||||
|
public const DIFF_MIXED = 'vegyes';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Duplikált névcsoportok, csoportonként a tagokkal és a hivatkozás-darabszámokkal.
|
* Duplikált névcsoportok, csoportonként a tagokkal és a hivatkozás-darabszámokkal.
|
||||||
* A tagok rendezettek: az első a javasolt megtartandó (legtöbb termék).
|
* A tagok rendezettek: az első a javasolt megtartandó (legtöbb termék).
|
||||||
@ -129,6 +140,51 @@ public function looseCandidateGroups(): array
|
|||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Egy laza jelölt-csoport eltérésének jellege - a LEGKEVÉSBÉ agresszív átalakítás,
|
||||||
|
* ami már egy kulcsra hozza a tagokat.
|
||||||
|
*
|
||||||
|
* Ez adja meg a megrendelőnek, mennyi mérlegelést igényel a sor: a "csak írásjel"
|
||||||
|
* eseteknél gyakorlatilag nincs döntés, a "cégforma" és a "vegyes" viszont valódi
|
||||||
|
* ismeretet kíván a cégekről.
|
||||||
|
*
|
||||||
|
* @param array<int, array{producer: object, counts: array<string, int>}> $members
|
||||||
|
*/
|
||||||
|
public function differenceCategory(array $members): string
|
||||||
|
{
|
||||||
|
$names = array_map(fn ($m) => (string) $m['producer']->name, $members);
|
||||||
|
|
||||||
|
$levels = [
|
||||||
|
self::DIFF_PUNCTUATION => fn ($n) => $this->stripPunctuation(NameNormalizer::normalize($n)),
|
||||||
|
self::DIFF_SPACING => fn ($n) => preg_replace('/\s+/u', '',
|
||||||
|
$this->stripPunctuation(NameNormalizer::normalize($n))),
|
||||||
|
self::DIFF_ACCENT => fn ($n) => preg_replace('/\s+/u', '',
|
||||||
|
$this->stripAccents($this->stripPunctuation(NameNormalizer::normalize($n)))),
|
||||||
|
self::DIFF_COMPANY_FORM => fn ($n) => $this->splitCompanyForm($n)[0],
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($levels as $category => $key) {
|
||||||
|
if (count(array_unique(array_map($key, $names))) === 1) {
|
||||||
|
return $category;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::DIFF_MIXED;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function stripPunctuation(string $text): string
|
||||||
|
{
|
||||||
|
return trim(preg_replace('/\s+/u', ' ', preg_replace('/[.,\-\'"()]/u', ' ', $text) ?? $text) ?? $text);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function stripAccents(string $text): string
|
||||||
|
{
|
||||||
|
return strtr($text, [
|
||||||
|
'Á' => 'A', 'É' => 'E', 'Í' => 'I', 'Ó' => 'O', 'Ö' => 'O',
|
||||||
|
'Ő' => 'O', 'Ú' => 'U', 'Ü' => 'U', 'Ű' => 'U',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Név szétbontása alapnévre és cégforma-toldatra, a "csak elírás" eltérések
|
* Név szétbontása alapnévre és cégforma-toldatra, a "csak elírás" eltérések
|
||||||
* kiszűrésével: írásjelek, ékezetek és szóközök elhagyásával.
|
* kiszűrésével: írásjelek, ékezetek és szóközök elhagyásával.
|
||||||
@ -137,12 +193,7 @@ public function looseCandidateGroups(): array
|
|||||||
*/
|
*/
|
||||||
private function splitCompanyForm(string $name): array
|
private function splitCompanyForm(string $name): array
|
||||||
{
|
{
|
||||||
$normalized = NameNormalizer::normalize($name);
|
$normalized = $this->stripAccents($this->stripPunctuation(NameNormalizer::normalize($name)));
|
||||||
$normalized = preg_replace('/[.,\-\'"()]/u', ' ', $normalized) ?? $normalized;
|
|
||||||
$normalized = strtr($normalized, [
|
|
||||||
'Á' => 'A', 'É' => 'E', 'Í' => 'I', 'Ó' => 'O', 'Ö' => 'O',
|
|
||||||
'Ő' => 'O', 'Ú' => 'U', 'Ü' => 'U', 'Ű' => 'U',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$form = '';
|
$form = '';
|
||||||
$pattern = '/\b(KFT|ZRT|BT|NYRT|KKT|RT|GMBH|LTD|INC|SRL|NV|BV|AG|SA|SPA)\b/u';
|
$pattern = '/\b(KFT|ZRT|BT|NYRT|KKT|RT|GMBH|LTD|INC|SRL|NV|BV|AG|SA|SPA)\b/u';
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user