$deliveryModel->longitude = 0.0;
}
}
- // Fallback: еÑ\81ли street вÑ\81Ñ\91 Ñ\80авно пÑ\83Ñ\81Ñ\82ой â\80\94 паÑ\80Ñ\81им из raw_data или ставим дефолт
+ // Fallback: еÑ\81ли street пÑ\83Ñ\81Ñ\82ой â\80\94 извлекаем из raw_data или ставим дефолт
if (empty($deliveryModel->street)) {
- $rawData = json_decode($marketplaceOrder->raw_data, true);
- $deliveryText = $rawData['delivery'] ?? null;
- Yii::warning('[ERP-252-v3] new: street empty для заказа #' . $marketplaceOrder->id . ', address=' . ($address ? 'object' : 'null') . ', deliveryText=' . (is_string($deliveryText) ? $deliveryText : json_encode($deliveryText, JSON_UNESCAPED_UNICODE)), 'marketplace');
- if ($deliveryText && is_string($deliveryText)) {
- $parsed = self::parseAddressFromDeliveryText($deliveryText);
- $deliveryModel->country = $deliveryModel->country ?: 'Россия';
- $deliveryModel->city = $deliveryModel->city ?: $parsed['city'];
- $deliveryModel->street = $parsed['street'];
- $deliveryModel->house = $deliveryModel->house ?: $parsed['house'];
- $deliveryModel->latitude = $deliveryModel->latitude ?: $parsed['latitude'];
- $deliveryModel->longitude = $deliveryModel->longitude ?: $parsed['longitude'];
- } else {
- $deliveryModel->country = $deliveryModel->country ?: 'Уточняется';
- $deliveryModel->city = $deliveryModel->city ?: 'Уточняется';
- $deliveryModel->street = 'Уточняется';
- $deliveryModel->house = $deliveryModel->house ?: 'Уточняется';
- $deliveryModel->latitude = $deliveryModel->latitude ?: 0.0;
- $deliveryModel->longitude = $deliveryModel->longitude ?: 0.0;
- }
+ Yii::warning('[ERP-252-v4] street empty для заказа #' . $marketplaceOrder->id, 'marketplace');
+ $fallback = self::fillDeliveryAddressFallback($marketplaceOrder->raw_data);
+ $deliveryModel->country = $deliveryModel->country ?: $fallback['country'];
+ $deliveryModel->city = $deliveryModel->city ?: $fallback['city'];
+ $deliveryModel->street = $fallback['street'];
+ $deliveryModel->house = $deliveryModel->house ?: $fallback['house'];
+ $deliveryModel->latitude = $deliveryModel->latitude ?: $fallback['latitude'];
+ $deliveryModel->longitude = $deliveryModel->longitude ?: $fallback['longitude'];
}
$shipments = $delivery->getShipments();
if ($shipments) {
$deliveryModel->longitude = 0.0;
}
}
- // Fallback: еÑ\81ли street вÑ\81Ñ\91 Ñ\80авно пÑ\83Ñ\81Ñ\82ой â\80\94 паÑ\80Ñ\81им из raw_data или ставим дефолт
+ // Fallback: еÑ\81ли street пÑ\83Ñ\81Ñ\82ой â\80\94 извлекаем из raw_data или ставим дефолт
if (empty($deliveryModel->street)) {
- $rawData = json_decode($marketplaceOrder->raw_data, true);
- $deliveryText = $rawData['delivery'] ?? null;
- Yii::warning('[ERP-252-v3] update: street empty для заказа #' . $marketplaceOrder->id . ', address=' . ($address ? 'object' : 'null') . ', deliveryText=' . (is_string($deliveryText) ? $deliveryText : json_encode($deliveryText, JSON_UNESCAPED_UNICODE)), 'marketplace');
- if ($deliveryText && is_string($deliveryText)) {
- $parsed = self::parseAddressFromDeliveryText($deliveryText);
- $deliveryModel->country = $deliveryModel->country ?: 'Россия';
- $deliveryModel->city = $deliveryModel->city ?: $parsed['city'];
- $deliveryModel->street = $parsed['street'];
- $deliveryModel->house = $deliveryModel->house ?: $parsed['house'];
- $deliveryModel->latitude = $deliveryModel->latitude ?: $parsed['latitude'];
- $deliveryModel->longitude = $deliveryModel->longitude ?: $parsed['longitude'];
- } else {
- $deliveryModel->country = $deliveryModel->country ?: 'Уточняется';
- $deliveryModel->city = $deliveryModel->city ?: 'Уточняется';
- $deliveryModel->street = 'Уточняется';
- $deliveryModel->house = $deliveryModel->house ?: 'Уточняется';
- $deliveryModel->latitude = $deliveryModel->latitude ?: 0.0;
- $deliveryModel->longitude = $deliveryModel->longitude ?: 0.0;
- }
+ Yii::warning('[ERP-252-v4] update: street empty для заказа #' . $marketplaceOrder->id, 'marketplace');
+ $fallback = self::fillDeliveryAddressFallback($marketplaceOrder->raw_data);
+ $deliveryModel->country = $deliveryModel->country ?: $fallback['country'];
+ $deliveryModel->city = $deliveryModel->city ?: $fallback['city'];
+ $deliveryModel->street = $fallback['street'];
+ $deliveryModel->house = $deliveryModel->house ?: $fallback['house'];
+ $deliveryModel->latitude = $deliveryModel->latitude ?: $fallback['latitude'];
+ $deliveryModel->longitude = $deliveryModel->longitude ?: $fallback['longitude'];
}
$dates = $delivery->getDates();
if ($dates) {
}
// Fallback: если street всё равно пустой — парсим из raw_data или ставим дефолт
if (empty($deliveryModel->street)) {
- $rawData = json_decode($marketplaceOrder->raw_data, true);
- $deliveryText = $rawData['delivery'] ?? null;
- Yii::warning('[ERP-252-v3] existing: street empty для заказа #' . $marketplaceOrder->id . ', address=' . ($address ? 'object' : 'null') . ', deliveryText=' . (is_string($deliveryText) ? $deliveryText : json_encode($deliveryText, JSON_UNESCAPED_UNICODE)), 'marketplace');
- if ($deliveryText && is_string($deliveryText)) {
- $parsed = self::parseAddressFromDeliveryText($deliveryText);
- $deliveryModel->country = $deliveryModel->country ?: 'Россия';
- $deliveryModel->city = $deliveryModel->city ?: $parsed['city'];
- $deliveryModel->street = $parsed['street'];
- $deliveryModel->house = $deliveryModel->house ?: $parsed['house'];
- $deliveryModel->latitude = $deliveryModel->latitude ?: $parsed['latitude'];
- $deliveryModel->longitude = $deliveryModel->longitude ?: $parsed['longitude'];
- } else {
- $deliveryModel->country = $deliveryModel->country ?: 'Уточняется';
- $deliveryModel->city = $deliveryModel->city ?: 'Уточняется';
- $deliveryModel->street = 'Уточняется';
- $deliveryModel->house = $deliveryModel->house ?: 'Уточняется';
- $deliveryModel->latitude = $deliveryModel->latitude ?: 0.0;
- $deliveryModel->longitude = $deliveryModel->longitude ?: 0.0;
- }
+ Yii::warning('[ERP-252-v4] existing: street empty для заказа #' . $marketplaceOrder->id, 'marketplace');
+ $fallback = self::fillDeliveryAddressFallback($marketplaceOrder->raw_data);
+ $deliveryModel->country = $deliveryModel->country ?: $fallback['country'];
+ $deliveryModel->city = $deliveryModel->city ?: $fallback['city'];
+ $deliveryModel->street = $fallback['street'];
+ $deliveryModel->house = $deliveryModel->house ?: $fallback['house'];
+ $deliveryModel->latitude = $deliveryModel->latitude ?: $fallback['latitude'];
+ $deliveryModel->longitude = $deliveryModel->longitude ?: $fallback['longitude'];
}
$shipments = $delivery->getShipments();
if ($shipments) {
return true;
}
+ /**
+ * Извлекает адрес из raw_data заказа, когда API не вернул структурированный адрес.
+ * Обрабатывает 3 варианта raw_data['delivery']:
+ * 1) string — текст FlowWow ("Доставка: ..., город, улица, дом")
+ * 2) array с address — JSON-объект YM API
+ * 3) null / отсутствует — дефолт "Уточняется"
+ *
+ * @param string|null $rawDataJson JSON-строка raw_data заказа
+ * @return array{country: string, city: string, street: string, house: string, latitude: float, longitude: float}
+ */
+ public static function fillDeliveryAddressFallback(?string $rawDataJson): array
+ {
+ $defaults = [
+ 'country' => 'Уточняется',
+ 'city' => 'Уточняется',
+ 'street' => 'Уточняется',
+ 'house' => 'Уточняется',
+ 'latitude' => 0.0,
+ 'longitude' => 0.0,
+ ];
+
+ if (empty($rawDataJson)) {
+ return $defaults;
+ }
+
+ $rawData = json_decode($rawDataJson, true);
+ if (!is_array($rawData)) {
+ return $defaults;
+ }
+
+ $delivery = $rawData['delivery'] ?? null;
+
+ // Вариант 1: текстовая строка FlowWow
+ if (is_string($delivery) && $delivery !== '') {
+ $parsed = self::parseAddressFromDeliveryText($delivery);
+ return [
+ 'country' => 'Россия',
+ 'city' => $parsed['city'],
+ 'street' => $parsed['street'],
+ 'house' => $parsed['house'],
+ 'latitude' => $parsed['latitude'],
+ 'longitude' => $parsed['longitude'],
+ ];
+ }
+
+ // Вариант 2: массив (JSON-объект YM API) с address
+ if (is_array($delivery)) {
+ $address = $delivery['address'] ?? null;
+ if (is_array($address)) {
+ return [
+ 'country' => !empty($address['country']) ? $address['country'] : 'Россия',
+ 'city' => !empty($address['city']) ? $address['city'] : 'Уточняется',
+ 'street' => !empty($address['street']) ? $address['street'] : 'Уточняется',
+ 'house' => !empty($address['house']) ? $address['house'] : 'Уточняется',
+ 'latitude' => (float)($address['gps']['latitude'] ?? 0.0),
+ 'longitude' => (float)($address['gps']['longitude'] ?? 0.0),
+ ];
+ }
+ }
+
+ // Вариант 3: null или нет данных
+ return $defaults;
+ }
+
public static function parseAddressFromDeliveryText(string $text): array
{
$city = 'Уточняется';
// Должен распознать хотя бы что-то кроме "Уточняется"
$this->assertNotEquals('Уточняется', $result['street']);
}
+
+ // --- Тесты fillDeliveryAddressFallback ---
+
+ /**
+ * Текстовая строка delivery в raw_data — парсится в адрес
+ */
+ public function testFillFallback_TextDelivery_ParsesAddress(): void
+ {
+ $rawData = json_encode([
+ 'delivery' => 'Доставка: 8 марта 2026 в 10:30—12:30, Нижний Новгород, улица Ленина, 10',
+ ]);
+
+ $result = MarketplaceService::fillDeliveryAddressFallback($rawData);
+
+ $this->assertNotEquals('Уточняется', $result['street']);
+ $this->assertNotEquals('Уточняется', $result['city']);
+ }
+
+ /**
+ * delivery = null в raw_data — возвращает "Уточняется"
+ */
+ public function testFillFallback_NullDelivery_ReturnsDefaults(): void
+ {
+ $rawData = json_encode(['delivery' => null]);
+
+ $result = MarketplaceService::fillDeliveryAddressFallback($rawData);
+
+ $this->assertEquals('Уточняется', $result['street']);
+ $this->assertEquals('Уточняется', $result['city']);
+ $this->assertEquals('Уточняется', $result['house']);
+ }
+
+ /**
+ * delivery = массив (JSON-объект от YM API) с address.street
+ */
+ public function testFillFallback_ArrayDelivery_WithAddress(): void
+ {
+ $rawData = json_encode([
+ 'delivery' => [
+ 'type' => 'DELIVERY',
+ 'address' => [
+ 'country' => 'Россия',
+ 'city' => 'Москва',
+ 'street' => 'Тверская',
+ 'house' => '1',
+ ],
+ ],
+ ]);
+
+ $result = MarketplaceService::fillDeliveryAddressFallback($rawData);
+
+ $this->assertEquals('Москва', $result['city']);
+ $this->assertEquals('Тверская', $result['street']);
+ $this->assertEquals('1', $result['house']);
+ }
+
+ /**
+ * delivery = массив без address — возвращает "Уточняется"
+ */
+ public function testFillFallback_ArrayDelivery_NoAddress(): void
+ {
+ $rawData = json_encode([
+ 'delivery' => [
+ 'type' => 'DELIVERY',
+ ],
+ ]);
+
+ $result = MarketplaceService::fillDeliveryAddressFallback($rawData);
+
+ $this->assertEquals('Уточняется', $result['street']);
+ }
+
+ /**
+ * delivery = массив с address, но street пустой
+ */
+ public function testFillFallback_ArrayDelivery_EmptyStreet(): void
+ {
+ $rawData = json_encode([
+ 'delivery' => [
+ 'address' => [
+ 'city' => 'Москва',
+ 'street' => '',
+ 'house' => '5',
+ ],
+ ],
+ ]);
+
+ $result = MarketplaceService::fillDeliveryAddressFallback($rawData);
+
+ $this->assertEquals('Уточняется', $result['street']);
+ $this->assertEquals('Москва', $result['city']);
+ }
+
+ /**
+ * raw_data невалидный JSON — возвращает "Уточняется"
+ */
+ public function testFillFallback_InvalidJson(): void
+ {
+ $result = MarketplaceService::fillDeliveryAddressFallback('not json');
+
+ $this->assertEquals('Уточняется', $result['street']);
+ }
+
+ /**
+ * raw_data = null — возвращает "Уточняется"
+ */
+ public function testFillFallback_NullRawData(): void
+ {
+ $result = MarketplaceService::fillDeliveryAddressFallback(null);
+
+ $this->assertEquals('Уточняется', $result['street']);
+ $this->assertEquals('Уточняется', $result['city']);
+ $this->assertEquals('Уточняется', $result['house']);
+ }
+
+ /**
+ * Результат fallback всегда содержит все ключи и не null
+ */
+ public function testFillFallback_AlwaysCompleteResult(): void
+ {
+ $inputs = [null, '', 'not json', '{}', '{"delivery":null}', '{"delivery":"text"}'];
+
+ foreach ($inputs as $input) {
+ $result = MarketplaceService::fillDeliveryAddressFallback($input);
+
+ $this->assertArrayHasKey('country', $result, "country для: $input");
+ $this->assertArrayHasKey('city', $result, "city для: $input");
+ $this->assertArrayHasKey('street', $result, "street для: $input");
+ $this->assertArrayHasKey('house', $result, "house для: $input");
+ $this->assertArrayHasKey('latitude', $result, "latitude для: $input");
+ $this->assertArrayHasKey('longitude', $result, "longitude для: $input");
+ $this->assertNotNull($result['street'], "street не null для: $input");
+ $this->assertNotEmpty($result['street'], "street не пустой для: $input");
+ }
+ }
}