]> gitweb.erp-flowers.ru Git - erp24_rep/yii-erp24/.git/commitdiff
fix(ERP-252): use district as street fallback, add prod data fixtures origin/feature_filippov_ERP-252_fix_delivery_street_parsing
authorAleksey Filippov <Aleksey.Filippov@erp-flowers.ru>
Mon, 2 Mar 2026 20:53:47 +0000 (23:53 +0300)
committerAleksey Filippov <Aleksey.Filippov@erp-flowers.ru>
Mon, 2 Mar 2026 20:53:47 +0000 (23:53 +0300)
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 <noreply@anthropic.com>
erp24/services/MarketplaceService.php
erp24/tests/unit/services/MarketplaceServiceDeliveryParsingTest.php

index 00ce157a9ee3a8af111aa37571a07365669d56db..a0c2b06803cd4f3d03314f8c31a608158696c914 100644 (file)
@@ -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),
index 9a6c9226e0deeca74ed52d3926f533775f9f9221..eb1fe88a9ef283b670948cb7cd34f8073c2637f6 100644 (file)
@@ -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']);
+    }
 }