From: Aleksey Filippov Date: Mon, 2 Mar 2026 20:53:47 +0000 (+0300) Subject: fix(ERP-252): use district as street fallback, add prod data fixtures X-Git-Url: https://gitweb.erp-flowers.ru/?a=commitdiff_plain;h=617efe977b6fb66d45ad250ba923c70aa7317c82;p=erp24_rep%2Fyii-erp24%2F.git fix(ERP-252): use district as street fallback, add prod data fixtures YM API often returns address without street but with district (e.g., "микрорайон Красногорка"). Now uses district as street fallback. Added 6 test cases based on real production data: - #4497: no street, has district (Бор, микрорайон Красногорка) - #3519: has street (улица Генерала Зимина) - #4328: district only (микрорайон Щербинки-1) - #4297: no street, no district (деревня Анкудиновка) - STRING format with "Уточните время" - NULL delivery in raw_data 26 tests, 133 assertions — all passing. Co-Authored-By: Claude Opus 4.6 --- diff --git a/erp24/services/MarketplaceService.php b/erp24/services/MarketplaceService.php index 00ce157a..a0c2b068 100644 --- a/erp24/services/MarketplaceService.php +++ b/erp24/services/MarketplaceService.php @@ -3365,10 +3365,12 @@ class MarketplaceService if (is_array($delivery)) { $address = $delivery['address'] ?? null; if (is_array($address)) { + // YM API часто не присылает street, но присылает district (микрорайон) + $street = !empty($address['street']) ? $address['street'] : (!empty($address['district']) ? $address['district'] : 'Уточняется'); return [ 'country' => !empty($address['country']) ? $address['country'] : 'Россия', 'city' => !empty($address['city']) ? $address['city'] : 'Уточняется', - 'street' => !empty($address['street']) ? $address['street'] : 'Уточняется', + 'street' => $street, 'house' => !empty($address['house']) ? $address['house'] : 'Уточняется', 'latitude' => (float)($address['gps']['latitude'] ?? 0.0), 'longitude' => (float)($address['gps']['longitude'] ?? 0.0), diff --git a/erp24/tests/unit/services/MarketplaceServiceDeliveryParsingTest.php b/erp24/tests/unit/services/MarketplaceServiceDeliveryParsingTest.php index 9a6c9226..eb1fe88a 100644 --- a/erp24/tests/unit/services/MarketplaceServiceDeliveryParsingTest.php +++ b/erp24/tests/unit/services/MarketplaceServiceDeliveryParsingTest.php @@ -323,4 +323,143 @@ class MarketplaceServiceDeliveryParsingTest extends Unit $this->assertNotEmpty($result['street'], "street не пустой для: $input"); } } + + // --- Тесты на реальные данные из прода --- + + /** + * Прод #4497: OBJECT без street, но с district (marketplace_id=2, YM API) + */ + public function testFillFallback_ProdOrder4497_NoStreetWithDistrict(): void + { + $rawData = json_encode([ + 'delivery' => [ + 'address' => [ + 'gps' => ['latitude' => 56.38352, 'longitude' => 44.02022], + 'city' => 'Бор', + 'floor' => '4', + 'house' => '21к2', + 'country' => 'Россия', + 'district' => 'микрорайон Красногорка', + 'entrance' => '2', + 'postcode' => '606446', + 'apartment' => '30', + ], + ], + ]); + + $result = MarketplaceService::fillDeliveryAddressFallback($rawData); + + $this->assertEquals('Бор', $result['city']); + $this->assertEquals('21к2', $result['house']); + $this->assertNotEmpty($result['street'], 'street должен быть заполнен (из district)'); + $this->assertEquals('микрорайон Красногорка', $result['street']); + $this->assertEquals(56.38352, $result['latitude']); + } + + /** + * Прод #3519: OBJECT со street (marketplace_id=2, YM API) + */ + public function testFillFallback_ProdOrder3519_HasStreet(): void + { + $rawData = json_encode([ + 'delivery' => [ + 'address' => [ + 'gps' => ['latitude' => 56.32424, 'longitude' => 43.94137], + 'city' => 'Нижний Новгород', + 'house' => '6', + 'street' => 'улица Генерала Зимина', + 'country' => 'Россия', + 'entrance' => '3', + 'postcode' => '603116', + 'apartment' => 'При звонке он выйдет,заберет.', + ], + ], + ]); + + $result = MarketplaceService::fillDeliveryAddressFallback($rawData); + + $this->assertEquals('Нижний Новгород', $result['city']); + $this->assertEquals('улица Генерала Зимина', $result['street']); + $this->assertEquals('6', $result['house']); + } + + /** + * Прод #4328: OBJECT без street, с district "микрорайон Щербинки-1" + */ + public function testFillFallback_ProdOrder4328_DistrictOnly(): void + { + $rawData = json_encode([ + 'delivery' => [ + 'address' => [ + 'gps' => ['latitude' => 56.24084, 'longitude' => 43.97071], + 'city' => 'Нижний Новгород', + 'floor' => '1', + 'house' => '7', + 'country' => 'Россия', + 'district' => 'микрорайон Щербинки-1', + 'entrance' => '1', + 'postcode' => '603107', + 'apartment' => '1', + ], + ], + ]); + + $result = MarketplaceService::fillDeliveryAddressFallback($rawData); + + $this->assertEquals('Нижний Новгород', $result['city']); + $this->assertEquals('микрорайон Щербинки-1', $result['street']); + $this->assertEquals('7', $result['house']); + } + + /** + * Прод #4297: OBJECT без street и без district + */ + public function testFillFallback_ProdOrder4297_NoStreetNoDistrict(): void + { + $rawData = json_encode([ + 'delivery' => [ + 'address' => [ + 'gps' => ['latitude' => 56.24145, 'longitude' => 44.04773], + 'city' => 'деревня Анкудиновка', + 'floor' => '7', + 'house' => '18', + 'country' => 'Россия', + 'apartment' => '64', + ], + ], + ]); + + $result = MarketplaceService::fillDeliveryAddressFallback($rawData); + + $this->assertEquals('деревня Анкудиновка', $result['city']); + $this->assertEquals('18', $result['house']); + $this->assertEquals('Уточняется', $result['street']); + } + + /** + * Прод #4311: STRING формат "Уточните время доставки у получателя" + */ + public function testParseProd_AskTimeFromRecipient(): void + { + $text = 'Доставка: сегодня, 23 февраля 2026 в 10:00—11:00, Нижний Новгород, проспект Ленина, 51к3, 1 подъезд Квартиру уточнить у получателя'; + + $result = MarketplaceService::parseAddressFromDeliveryText($text); + + $this->assertNotEquals('Уточняется', $result['city']); + $this->assertNotEquals('Уточняется', $result['street']); + } + + /** + * Прод: marketplace_id=1, delivery=NULL — самый частый случай + */ + public function testFillFallback_NullDeliveryInRawData(): void + { + // raw_data не содержит delivery вообще (YM API не вернул) + $rawData = json_encode(['items' => [], 'status' => 'PROCESSING']); + + $result = MarketplaceService::fillDeliveryAddressFallback($rawData); + + $this->assertEquals('Уточняется', $result['street']); + $this->assertEquals('Уточняется', $result['city']); + } }