From: Aleksey Filippov Date: Mon, 2 Mar 2026 20:30:48 +0000 (+0300) Subject: fix(ERP-252): add delivery parsing tests and fix surprise-delivery pattern X-Git-Url: https://gitweb.erp-flowers.ru/?a=commitdiff_plain;h=e83a19085aef6a593100966a4d25fff75b02f975;p=erp24_rep%2Fyii-erp24%2F.git fix(ERP-252): add delivery parsing tests and fix surprise-delivery pattern 12 unit tests for parseAddressFromDeliveryText() covering: - Full address (city/street/house) - "Уточните адрес у получателя" pattern - Surprise SMS delivery ("Отправим смс получателю...") - Empty strings, prefix-only, unknown cities - GPS coordinates for known cities - Pickup delivery, two-word cities - Result structure validation (all keys, no nulls) Fixed parser: added filters for surprise-delivery phrases that were incorrectly parsed as street names. Co-Authored-By: Claude Opus 4.6 --- diff --git a/erp24/services/MarketplaceService.php b/erp24/services/MarketplaceService.php index 89d9ef1c..c364217d 100644 --- a/erp24/services/MarketplaceService.php +++ b/erp24/services/MarketplaceService.php @@ -3367,6 +3367,10 @@ class MarketplaceService // Убираем служебные фразы, которые не являются адресом $cleaned = preg_replace('/Уточните\s+адрес\s+доставки\s+у\s+получателя/ui', '', $cleaned); + $cleaned = preg_replace('/Отправим\s+смс\s+получателю.*$/ui', '', $cleaned); + $cleaned = preg_replace('/Пожалуйста.*сохранить\s+сюрприз/ui', '', $cleaned); + $cleaned = preg_replace('/чтобы\s+узнать\s+данные\s+для\s+доставки/ui', '', $cleaned); + $cleaned = preg_replace('/не\s+звоните\s+раньше/ui', '', $cleaned); // Чистим оставшиеся запятые и пробелы $cleaned = preg_replace('/,\s*,/', ',', $cleaned); diff --git a/erp24/tests/unit/services/MarketplaceServiceDeliveryParsingTest.php b/erp24/tests/unit/services/MarketplaceServiceDeliveryParsingTest.php new file mode 100644 index 00000000..c587faac --- /dev/null +++ b/erp24/tests/unit/services/MarketplaceServiceDeliveryParsingTest.php @@ -0,0 +1,191 @@ +assertNotEquals('Уточняется', $result['city'], 'Город должен быть распознан'); + $this->assertNotEquals('Уточняется', $result['street'], 'Улица должна быть распознана'); + $this->assertNotEquals('Уточняется', $result['house'], 'Дом должен быть распознан'); + } + + /** + * Адрес без улицы: "Уточните адрес доставки у получателя" + * Пример из прода: заказ #4408 + */ + public function testParseNoAddress_AskRecipient(): void + { + $text = 'Доставка: сегодня, 27 февраля 2026 в 17:30—18:00, Уточните адрес доставки у получателя'; + + $result = MarketplaceService::parseAddressFromDeliveryText($text); + + $this->assertEquals('Уточняется', $result['city']); + $this->assertEquals('Уточняется', $result['street']); + $this->assertEquals('Уточняется', $result['house']); + } + + /** + * Сюрприз-доставка: адрес будет позже через SMS + * Пример из прода: заказы #4459, #4460, #4461, #4464 + */ + public function testParseSurpriseDelivery_SmsLater(): void + { + $text = 'Доставка: Отправим смс получателю 8 марта в 07:30, чтобы узнать данные для доставки Пожалуйста, не звоните раньше, чтобы сохранить сюрприз'; + + $result = MarketplaceService::parseAddressFromDeliveryText($text); + + // Адреса нет — всё "Уточняется" + $this->assertEquals('Уточняется', $result['street']); + $this->assertEquals('Уточняется', $result['house']); + } + + /** + * Пустая строка + */ + public function testParseEmptyString(): void + { + $result = MarketplaceService::parseAddressFromDeliveryText(''); + + $this->assertEquals('Уточняется', $result['city']); + $this->assertEquals('Уточняется', $result['street']); + $this->assertEquals('Уточняется', $result['house']); + $this->assertEquals(0.0, $result['latitude']); + $this->assertEquals(0.0, $result['longitude']); + } + + /** + * Только "Доставка:" без адреса + */ + public function testParseDeliveryPrefixOnly(): void + { + $result = MarketplaceService::parseAddressFromDeliveryText('Доставка:'); + + $this->assertEquals('Уточняется', $result['street']); + } + + /** + * GPS-координаты для Нижнего Новгорода + */ + public function testParseNizhnyNovgorod_HasGps(): void + { + $text = 'Доставка: 5 марта 2026 в 12:00—14:00, Нижний Новгород, ул. Ленина, 10'; + + $result = MarketplaceService::parseAddressFromDeliveryText($text); + + $this->assertGreaterThan(0, $result['latitude'], 'Широта должна быть заполнена для НН'); + $this->assertGreaterThan(0, $result['longitude'], 'Долгота должна быть заполнена для НН'); + } + + /** + * GPS-координаты для Москвы + */ + public function testParseMoscow_HasGps(): void + { + $text = 'Доставка: 5 марта 2026 в 12:00—14:00, Москва, Тверская, 1'; + + $result = MarketplaceService::parseAddressFromDeliveryText($text); + + $this->assertGreaterThan(0, $result['latitude'], 'Широта должна быть заполнена для Москвы'); + $this->assertGreaterThan(0, $result['longitude'], 'Долгота должна быть заполнена для Москвы'); + } + + /** + * Неизвестный город — GPS = 0 + */ + public function testParseUnknownCity_ZeroGps(): void + { + $text = 'Доставка: 5 марта 2026 в 12:00—14:00, Саратов, ул. Мира, 5'; + + $result = MarketplaceService::parseAddressFromDeliveryText($text); + + $this->assertEquals(0.0, $result['latitude']); + $this->assertEquals(0.0, $result['longitude']); + } + + /** + * Самовывоз + */ + public function testParsePickup(): void + { + $text = 'Самовывоз: 5 марта 2026 в 12:00—14:00, Нижний Новгород, ул. Речная, 22'; + + $result = MarketplaceService::parseAddressFromDeliveryText($text); + + $this->assertNotEquals('Уточняется', $result['street'], 'Улица должна быть распознана для самовывоза'); + } + + /** + * Результат всегда содержит все 5 ключей + */ + public function testParseResult_AlwaysHasAllKeys(): void + { + $result = MarketplaceService::parseAddressFromDeliveryText('любой текст'); + + $this->assertArrayHasKey('city', $result); + $this->assertArrayHasKey('street', $result); + $this->assertArrayHasKey('house', $result); + $this->assertArrayHasKey('latitude', $result); + $this->assertArrayHasKey('longitude', $result); + } + + /** + * Все значения — строки или float, никогда не null + */ + public function testParseResult_NeverReturnsNull(): void + { + $inputs = [ + '', + 'Доставка:', + 'Доставка: сегодня', + 'random text', + 'Доставка: Отправим смс получателю', + ]; + + foreach ($inputs as $input) { + $result = MarketplaceService::parseAddressFromDeliveryText($input); + + $this->assertNotNull($result['city'], "city не должен быть null для: '$input'"); + $this->assertNotNull($result['street'], "street не должен быть null для: '$input'"); + $this->assertNotNull($result['house'], "house не должен быть null для: '$input'"); + $this->assertNotNull($result['latitude'], "latitude не должен быть null для: '$input'"); + $this->assertNotNull($result['longitude'], "longitude не должен быть null для: '$input'"); + } + } + + /** + * Город с двумя словами парсится корректно + */ + public function testParseTwoWordCity(): void + { + $text = 'Доставка: 5 марта 2026 в 10:00—12:00, Нижний Новгород, Большая Покровская, 1'; + + $result = MarketplaceService::parseAddressFromDeliveryText($text); + + // Должен распознать хотя бы что-то кроме "Уточняется" + $this->assertNotEquals('Уточняется', $result['street']); + } +}