Pavel SkvortsovPavel Skvortsov
← Назад
04

WP Plugin - Quick Price Manager

Кастомный WordPress-плагин для массового управления ценами на ASIC-майнеры. Inline-редактирование, CSV импорт/экспорт, управление плашками и алерты устаревших цен - всё на одной странице.

WordPressPHPACFMySQL

"Обновить цены на 100 аппаратов без открытия ни одной карточки товара."

4
варианта хэшрейта на аппарат (H1-H4)
AJAX
сохранение без перезагрузки страницы
CSV
массовый импорт и экспорт с колонками хэшрейта
7 дней
порог устаревания цены с цветовой индикацией
Как это работает
Рендер страницы админки
Inline ввод цены
CSV импорт → заполнение полей
AJAX POST → PHP handler
update_post_meta + ACF
Timestamp _price_updated_at
Структура проекта
inc/price-manager.phpрендер страницы, AJAX-хендлеры, ACF-хук, уведомление об устаревших ценах
ms2026_save_prices_ajax()проверяет nonce, обновляет h1_price-h4_price через post_meta + ACF, ставит _price_updated_at
ms2026_update_badge_ajax()валидирует значение плашки по whitelist из ACF choices перед сохранением
ms2026_acf_track_price_update()хук ACF save_post - сравнивает старые и новые цены, обновляет timestamp только при реальном изменении
ms2026_outdated_prices_notice()WP_Query находит товары где _price_updated_at старше 7 дней - уведомление со ссылкой
Важная деталь

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

Код
// CSV импорт - полностью на клиенте, без обращения к серверу
  importBtn.addEventListener('click', function () {
    var reader = new FileReader();
    reader.onload = function (e) {
      var rows = e.target.result.split(/\r?\n/);
      // Автоопределение разделителя: ; или ,
      var sep = rows[0].indexOf(';') !== -1 ? ';' : ',';
      // Новый формат: model_name;h1_th;h2_th;h3_th;h4_th;h1_price
      // Старый формат: model_name;h1_price;h2_price
      var priceStart = rows[0].toLowerCase().includes('h1_th') ? 5 : 1;
  
      rows.slice(1).forEach(function (row) {
        var cols = row.split(sep).map(c => c.trim().replace(/^"|"$/g, ''));
        var modelName = cols[0];
        document.querySelectorAll('.ms2026-price-block').forEach(function (block) {
          if (block.dataset.model.toLowerCase() === modelName.toLowerCase()) {
            block.querySelectorAll('.ms2026-price-input').forEach(function (inp, j) {
              var newPrice = cols[priceStart + j] || '';
              if (newPrice) {
                inp.value = newPrice;
                inp.style.backgroundColor = '#fcf3cf'; // подсветка изменений
              }
            });
          }
        });
      });
    };
    reader.readAsText(fileInput.files[0], 'UTF-8');
  });
  
  // AJAX сохранение - отправляет только изменённые поля
  saveBtn.addEventListener('click', function () {
    var data = {};
    document.querySelectorAll('.ms2026-price-input').forEach(function (inp) {
      if (!inp.value.trim()) return; // пропускаем неизменённые
      var match = inp.name.match(/prices\[(\d+)\]\[(h\d+_price)\]/);
      if (match) {
        if (!data[match[1]]) data[match[1]] = {};
        data[match[1]][match[2]] = inp.value.trim();
      }
    });
    // POST на wp_ajax_ms2026_save_prices
  });
Скриншоты
admin
Функции
  • Одна страница администратора со всеми аппаратами и вариантами хэшрейта инлайн
  • Inline редактирование цен - введи цену, нажми Сохранить - AJAX без перезагрузки
  • CSV импорт: загрузи файл - поля автоматически заполняются, подсвечиваются жёлтым - проверь - сохрани
  • CSV экспорт: скачивает текущие цены с колонками хэшрейта (model_name; h1_th-h4_th; h1_price-h4_price)
  • Управление плашками товаров - выпадающий список сохраняется отдельным AJAX-запросом мгновенно
  • Фильтрация по бренду и алгоритму - URL-параметры, без JS
  • Индикатор устаревания: зелёный < 3 дней - жёлтый 3-7 дней - красный > 7 дней
  • Уведомление в админке: "N товаров с устаревшими ценами - Обновить цены"
  • Цены сохраняются через update_post_meta + update_field (ACF) одновременно для полной совместимости
  • ACF-хук отслеживает изменения - _price_updated_at обновляется только при реальном изменении значения