Как настроить синхронизацию остатков WooCommerce с 1С через CSV-импорт

Если 1С уже выгружает остатки в CSV, а в WooCommerce они не обновляются или обновляются с ошибками, проблема обычно не в самом файле, а в сопоставлении SKU, формате чисел и способе импорта. В этой статье — рабочая схема, которая подходит для регулярной синхронизации без написания отдельной интеграции.

Когда CSV-импорт действительно подходит

Этот вариант имеет смысл, если у вас уже есть регулярная выгрузка из 1С, а задача сводится к обновлению цены, остатка и статуса наличия. Для небольших и средних каталогов CSV часто проще, чем поддерживать отдельный обмен через API: меньше точек отказа, проще проверить руками и быстрее найти ошибку в конкретной строке.

Но CSV не решает всё. Если нужны сложные правила по складам, нескольким валютам, пакетная передача характеристик и история обмена на уровне документов, лучше смотреть в сторону штатного обмена 1С или отдельного интеграционного слоя. CSV — это практичный компромисс, а не универсальная замена.

Диагностика проблемы: что ломается чаще всего

Перед настройкой импорта проверьте не WordPress, а исходные данные. В 80% случаев сбой связан с одним из типовых несоответствий:

  • в WooCommerce у товара нет совпадающего SKU, а импорт ищет товар именно по артикулу;
  • в CSV остаток записан как текст с запятой, пробелами или лишними символами;
  • кодировка файла не UTF-8 и кириллица в названиях «плывёт»;
  • в файле есть дубли SKU;
  • импорт обновляет не тот столбец: например, цену вместо остатка;
  • товары-вариации не сопоставлены отдельно, хотя у них свои артикулы.

Быстрая проверка: откройте CSV в текстовом редакторе, а не в таблицах, и убедитесь, что разделитель один и тот же по всему файлу. Если файл выглядит нормально в Excel, это ещё не значит, что он корректен для импорта.

Пошаговая схема: как сделать импорт без дублей и ручной правки

1. Приведите каталог к единому идентификатору

Для синхронизации остатков используйте SKU как основной ключ. В WooCommerce это стандартное поле товара и вариации. Если артикулы в 1С и магазине отличаются, сначала договоритесь о едином формате: это дешевле, чем потом ловить расхождения в каждом импорте.

Если у товара нет артикула, импорт по нему лучше не запускать. Иначе вы получите либо новые дубли, либо массовое обновление не тех позиций.

2. Подготовьте CSV в предсказуемом формате

Минимальный набор колонок для обновления остатков обычно такой: sku, stock_quantity, stock_status. Названия могут быть любыми, если вы сами пишете обработчик, но логика должна быть однозначной.

sku,stock_quantity,stock_status
ABC-001,12,instock
ABC-002,0,outofstock
ABC-003,5,instock

Если 1С отдаёт остаток в виде 12,000 или 12 шт., перед импортом нормализуйте значение. WooCommerce ожидает число, а не человекочитаемую подпись.

3. Настройте импорт через WP-Cron или ручной запуск

Если файл лежит на сервере, можно запускать обработку по расписанию. Для этого удобнее написать небольшой обработчик, который читает CSV и обновляет товары по SKU. Ниже пример упрощённой функции: она не зависит от стороннего плагина и показывает сам принцип.

<?php
function wpdirect_import_stock_from_csv( $file_path ) {
    if ( ! file_exists( $file_path ) || ! is_readable( $file_path ) ) {
        return new WP_Error( 'csv_not_found', 'CSV-файл недоступен' );
    }

    $handle = fopen( $file_path, 'r' );
    if ( ! $handle ) {
        return new WP_Error( 'csv_open_failed', 'Не удалось открыть CSV' );
    }

    $header = fgetcsv( $handle, 0, ',' );
    if ( ! $header ) {
        fclose( $handle );
        return new WP_Error( 'csv_empty', 'CSV пустой' );
    }

    $map = array_flip( $header );

    while ( ( $row = fgetcsv( $handle, 0, ',' ) ) !== false ) {
        $sku = isset( $row[ $map['sku'] ] ) ? trim( $row[ $map['sku'] ] ) : '';
        $qty = isset( $row[ $map['stock_quantity'] ] ) ? (int) $row[ $map['stock_quantity'] ] : 0;
        $status = isset( $row[ $map['stock_status'] ] ) ? trim( $row[ $map['stock_status'] ] ) : 'outofstock';

        if ( $sku === '' ) {
            continue;
        }

        $product_id = wc_get_product_id_by_sku( $sku );
        if ( ! $product_id ) {
            continue;
        }

        $product = wc_get_product( $product_id );
        if ( ! $product ) {
            continue;
        }

        $product->set_manage_stock( true );
        $product->set_stock_quantity( $qty );
        $product->set_stock_status( $status === 'instock' ? 'instock' : 'outofstock' );
        $product->save();
    }

    fclose( $handle );

    return true;
}

Такой код удобно запускать не на каждом хите, а по cron-задаче или вручную из админки. Если файл большой, не гоняйте импорт через обычный запрос браузера — упрётесь в таймауты и память.

4. Обрабатывайте вариации отдельно

Если у вариативного товара свои артикулы на каждую вариацию, импортируйте именно вариации, а не родительский товар. В WooCommerce родитель может быть «в наличии», даже если конкретные размеры закончились. Для этого в CSV храните SKU вариации и обновляйте их как отдельные записи.

Пример более надёжной обработки CSV

Когда файл приходит в нестабильном формате, полезно сначала проверить заголовки и логировать пропущенные строки. Это помогает быстро понять, где сломалась выгрузка из 1С.

<?php
function wpdirect_normalize_stock_value( $value ) {
    $value = trim( (string) $value );
    $value = str_replace( array( ' ', ' ' ), '', $value );
    $value = str_replace( ',', '.', $value );

    return (int) floor( (float) $value );
}

function wpdirect_import_stock_row( array $row, array $map ) {
    $sku = isset( $row[ $map['sku'] ] ) ? sanitize_text_field( $row[ $map['sku'] ] ) : '';
    $qty = isset( $row[ $map['stock_quantity'] ] ) ? wpdirect_normalize_stock_value( $row[ $map['stock_quantity'] ] ) : 0;

    if ( $sku === '' ) {
        return new WP_Error( 'empty_sku', 'Пустой SKU' );
    }

    $product_id = wc_get_product_id_by_sku( $sku );
    if ( ! $product_id ) {
        return new WP_Error( 'product_not_found', 'Товар не найден: ' . $sku );
    }

    $product = wc_get_product( $product_id );
    $product->set_manage_stock( true );
    $product->set_stock_quantity( $qty );
    $product->set_stock_status( $qty > 0 ? 'instock' : 'outofstock' );
    $product->save();

    return true;
}

Здесь важен не сам стиль кода, а принцип: сначала нормализация входных данных, потом поиск товара, затем обновление. Если поменять порядок, отладка станет заметно сложнее.

Сравнение подходов: плагин, код или ручной импорт

ПодходКогда подходитПлюсыМинусы
Плагин импортаНужен быстрый запуск без разработкиЕсть интерфейс, логирование, маппинг полейДополнительная нагрузка, зависимость от плагина
Собственный кодФормат CSV стабилен и нужен контроль логикиГибкость, меньше лишнего кода в админкеНужно поддерживать и тестировать
Ручной импортРедкие обновления и небольшой каталогПросто начать, не требует автоматизацииОшибки из-за человеческого фактора

Если у вас уже есть регулярные выгрузки и нужен минимум ручной работы, кодовый импорт обычно выигрывает. Если же формат CSV меняется вместе с настройками 1С, удобнее использовать интерфейсный импорт с маппингом колонок.

Как проверить, что синхронизация сработала

После первого запуска не ограничивайтесь просмотром пары товаров в админке. Проверьте цепочку целиком:

  • товар найден по SKU и не создан дубль;
  • изменилось именно поле остатка, а не только статус;
  • на витрине товар исчезает из наличия при 0;
  • вариации обновляются отдельно, если у них свои артикулы;
  • в логах нет строк с пустым SKU и нераспознанными значениями.

Практический тест: возьмите один товар, поменяйте остаток в CSV на 0, запустите импорт и откройте карточку товара в админке. Если WooCommerce показывает outofstock, а на витрине товар скрывается или помечается как отсутствующий — базовая логика работает.

Частые ошибки и как их исправить

Товар не находится по SKU

Причина обычно в том, что артикул в WooCommerce пустой, отличается по регистру или содержит лишние пробелы. Сначала проверьте карточку товара, потом CSV. Если артикулы генерируются автоматически, убедитесь, что они одинаково формируются и в 1С, и в магазине.

Остаток обновился, но статус не поменялся

Так бывает, если импорт меняет только количество, а статус наличия WooCommerce рассчитывает отдельно. В коде нужно явно задавать и set_stock_quantity(), и set_stock_status(). Иначе товар может остаться «в наличии» при нулевом остатке.

После импорта появились дубли

Это почти всегда признак импорта не по SKU, а по названию или ID из внешней системы. Для WooCommerce внешний ID из 1С не имеет смысла, если вы его отдельно не храните. Используйте один устойчивый ключ и не смешивайте несколько идентификаторов в одном процессе.

Импорт падает на больших файлах

Причина — обработка всего CSV за один запрос. Разбейте импорт на пачки, запускайте через cron и логируйте прогресс. Если файл приходит очень большой, лучше сначала выгружать его на сервер, а потом обрабатывать построчно.

Безопасность и производительность

Если CSV лежит в публичной директории, не оставляйте его доступным без ограничений. Файл с остатками и ценами — это уже чувствительные данные. Храните выгрузку вне web-root или закрывайте доступ на уровне сервера.

Для производительности важно не обновлять товар без необходимости. Перед save() сравнивайте старый и новый остаток: если значение не изменилось, лишняя запись в базу не нужна. На каталоге с большим количеством товаров это заметно снижает нагрузку.

Если вам нужен не только импорт, но и чистка лишних дублей, служебных мета-данных и мусора после тестов, имеет смысл посмотреть в сторону Clearfy Pro. Он не решает обмен с 1С, но помогает держать сайт в более чистом состоянии, когда интеграции уже обросли служебными данными.

Что делать, если нужен следующий шаг

Если CSV-обмен уже работает, следующий полезный этап — добавить журналирование: кто запустил импорт, какой файл был обработан, сколько строк обновилось и сколько было пропущено. Это сильно упрощает разбор инцидентов, когда 1С выгрузила не тот формат или менеджер случайно загрузил старый файл.

Для стабильной схемы обычно достаточно трёх вещей: единый SKU, предсказуемый CSV и проверка результата после каждого запуска. Всё остальное — уже вопрос удобства и масштаба каталога.

Как использовать мета-записи для контекстного контента в WordPress
07.12.2025
WooCommerce: автоматическое отключение отзывов по условиям
25.06.2026
Как удалить пустые категории и теги в WordPress
24.11.2025
WooCommerce: автоматическое удаление отменённых заказов по расписанию
11.05.2026
Как автоматизировать создание и удаление черновиков в WordPress
08.01.2026