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_atms2026_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
});Скриншоты

Функции
- •Одна страница администратора со всеми аппаратами и вариантами хэшрейта инлайн
- •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 обновляется только при реальном изменении значения