Ценообразование — задача и решение (несколько прайсов для товаров)




Принцип обмена данными из 1С с сайтом (на MySQL) и выдачи (публикации) этих данных по запросу.
PHP-Скрипт автоматической загрузки данных из файла данных в формате CSV в базу данных сайта работающего на WordPress.

В продолжение моей темы: 1С:Альфа-Авто Автосалон Автосервис: обмен с сайтом.
С помощью данного скрипта можно загружать в автоматическом режиме, по расписанию, данные сервисных книжек (ремонтов авто) из 1С:Альфа-Авто Автосалон Автосервис.
Также можно загружать данные в ручном режиме: для этого делается скрытая страница, где размещается специальная кнопка.
Комментарии размещенные внутри скрипта разъяснят логику и порядок действия.
Комментарии с "/////    echo" использовались для отладки.
Дополнительно создана таблица для журналирования результатов загрузки данных.
Скрипт включает в себя защиту от SQL инъекций (думаю безопасность соблюдена в полной мере).
В кратце:
1. Пишется скрипт, который запускает этот.
2. Создается регламентное задание в WordPress, по которому запускается скрипт из п.1. 
3. Этот скрипт осуществляет проверку на существование файла обмена в папке.
4. Если данные не новые, загрузка не производится.
5. Если данные новые, очищается таблица сервисных книжек.
6. Загружаются новые данные.

Собственно сам скрипт:

<?php // Полная загрузка сервисных книжек, создан 2024-01-05 12:44:55

global $wpdb2;
global $failure;
global $file_hist;

/////  echo '<H2><b>Старт загрузки</b></H2><br>';

$failure=FALSE;
//подключаемся к базе
$wpdb2 = include_once 'connection.php'; ; // подключаемся к MySQL
// если не удалось подключиться, и нужно оборвать PHP с сообщением об этой ошибке
if (!empty($wpdb2->error))
{
/////   echo '<H2><b>Ошибка подключения к БД, завершение.</b></H2><br>';
$failure=TRUE;
wp_die( $wpdb2->error );
}

$m_size_file=0;
$m_mtime_file=0;
$m_comment='';
/////проверка существования файлов выгрузки из 1С
////файл выгрузки сервисных книжек
$file_hist = ABSPATH.'/_1c_alfa_exchange/AA_hist.csv';
if (!file_exists($file_hist))
{
/////   echo '<H2><b>Файл обмена с сервисными книжками не существует.</b></H2><br>';
$m_comment='Файл обмена с сервисными книжками не существует';
$failure=TRUE;
}

/////инициируем таблицу лога
/////если не существует файла то возврат и ничего не делаем
if ($failure){
///включает защиту от SQL инъекций и данные можно передавать как есть, например: $_GET['foo']
/////   echo '<H2><b>Попытка вставить запись в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>$m_comment));
wp_die();
/////    echo '<H2><b>Возврат в начало.</b></H2><br>';
return $failure;
}
/////проверка лога загрузки, что бы не загружать тоже самое
$masiv_data_file=stat($file_hist);   ////передаем в массив свойство файла
$m_size_file=$masiv_data_file[7];    ////получаем размер файла
$m_mtime_file=$masiv_data_file[9];   ////получаем дату модификации файла
////создаем запрос на получение последней удачной загрузки
////выбираем по штампу времени создания (редактирования) файла загрузки AA_hist.csv, $m_mtime_file

/////   echo '<H2><b>Размер файла: '.$m_size_file.'</b></H2><br>';
/////   echo '<H2><b>Штамп времени файла: '.$m_mtime_file.'</b></H2><br>';
/////   echo '<H2><b>Формирование запроса на выборку из лога</b></H2><br>';
////препарируем запрос
$text_zaprosa=$wpdb2->prepare("SELECT * FROM `vin_logs` WHERE `last_mtime_upload` = %s", $m_mtime_file);
$results=$wpdb2->get_results($text_zaprosa);

if ($results)
{   foreach ( $results as $r)
{
////если штамп времени и размер файла совпадают, возврат
if (($r->last_mtime_upload==$m_mtime_file) && ($r->last_size_upload==$m_size_file))
{////echo '<H2><b>Возврат в начало, т.к. найдена запись в логе.</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>'Загрузка отменена, новых данных нет, т.к. найдена запись в логе.'));
wp_die();
return $failure;
}
}
}
////если данные новые, пишем в лог запись о начале загрузки
/////echo '<H2><b>Попытка вставить запись о начале загрузки в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>0, 'last_size_upload'=>$m_size_file, 'comment'=>'Начало загрузки'));

////очищаем таблицу
$clear_tbl_zap=$wpdb2->prepare("TRUNCATE TABLE %s", 'vin_history');
$clear_tbl_zap_repl=str_replace("'","`",$clear_tbl_zap);
$results=$wpdb2->query($clear_tbl_zap_repl);
/////   echo '<H2><b>Очистка таблицы сервисных книжек</b></H2><br>';
if (empty($results))
{
/////   echo '<H2><b>Ошибка очистки таблицы книжек, завершение.</b></H2><br>';
//// если очистка не удалась, возврат
$failure=TRUE;
wp_die();
return $failure;
}

////загружаем данные
$table='vin_history';         // Имя таблицы для импорта
//$file_hist Имя CSV файла, откуда берется информация     // (путь от корня web-сервера)
$delim=';';          // Разделитель полей в CSV файле
$enclosed='"';      // Кавычки для содержимого полей
$escaped='\

37 Comments

  1. iov

    (0)

    как вам матрица с таким раскладом — процент или фиксированная цена устанавливается на

    группу контрагентов/контрагента/договор/тип цен документа/группу номенклатуры/номенклатуру/характеристику/время действия (относительное и абсолютное).

    все это в иерархии и с разными приоритетами. А закупочные цены меняются только если они попадают в определенную вилку разрешенных изменений. Всё это рассчитывается автоматически согласно сезонности/объемов продаж/количеству возвратов(компенсация потерь). Дорого — очень производительность резко падает на операциях расчета цен — но результат попадание в рынок по 90% номенклатуре.

    Reply
  2. noook

    (1) iov, в Вашем случае я бы использовал нечто другое, чем матрица цен

    думаю, что

    _если взять «на группу контрагентов/контрагента/договор», то использовал бы доработку справочника + обработка в документе

    _если взять «на тип цен документа/группу номенклатуры/номенклатуру/характеристику», то использовал бы использовал бы как то регистр, но мысль про матрицу моя бы не подошла

    если взять «время действия (относительное и абсолютное)», то тут бы только использовал бы только доработку в документе

    А у Вас уже действует то, про что Вы говорите?

    Reply
  3. iov

    (2) действует.

    Reply
  4. ander_

    (3) iov, какое примерно количество позиций номенклатуры, типов цен?

    Reply
  5. ander_

    noook, управленческий учет в какой валюте ведется?

    Reply
  6. noook

    (4) ander_, номенклатура более 1000 товаров, могу сказать точно если интересно

    типов цен как в статье, то есть 9 штук + плановая себестоимость (типовой тип цен)

    учет ведётся в рублях ибо мы в РФ живём, но много отчетов нужно и в долларах

    Reply
  7. ander_

    Вопрос.. наверное ко всем. Может есть идеи как быть в случае если нужна подобная гибкая схема, т.е. хранить и крутить процент от входа (ну или другой, возможно хитро рассчитанной базы), с возможностью указания накруток по каждому типу цен с точностью до товара. Но при этом номенклатуры от 100000 позиций…

    Reply
  8. tango

    + за подход.

    но тема, в общем-то, не раскрыта

    Reply
  9. tango

    (7) ander_, бесплатно?

    Reply
  10. tango

    автор, поправь орфографию, пожалуйста

    тема актуальная, орфография нужна.

    **

    «Минимальная — это цена ниже которой будет не выгодно продавать вообще» — улыбнуло — «Умру, но не продам дешевле»

    🙂

    Reply
  11. tango
    …и добавил в кнопку ЗАПОЛНИТЬ.

    эта ваще пять

    Reply
  12. tango
    Ставлю в валюте USD внутренний курс на день переоценки

    собственно, вся байда именно в этом — определить «правильный курс», вся остальная фигня — два часа с клавой

    Reply
  13. iov

    (3) 2500 позиций 20 типов цен

    Reply
  14. iov

    (7) встречал примерно 6 разных решений. Если цены надо проставлять автоматически сразу на большую группу товаров- ничего не подходит. прайс формируется по несколько часов на 2000 наименований. Есть решения с использованием хранения во внешней базе с расчетом раз в сутки. В общем гибкость цен = тормоза в базе.

    Reply
  15. noook

    (12) tango, тема не раскрыта — понял, что нужно добавить? какие процессы описать подробнее?

    Про текст — пытался писать с юмором. Орфографию где поправить?

    У нас внутренний курс «задаёт» директор, поэтому тебе будет 2 часа + 1 минута общения с директором )))

    Reply
  16. noook

    (14) iov, В общем гибкость цен = тормоза в базе

    это да, при большом количестве критериев и категорий

    Reply
  17. iov

    (16) К сожалению у меня расчет цены на 1 позицию может до 2 секунд выполнятся (с учетом расчета средней маржы по документу)

    Reply
  18. tango

    (15) два часа — я имел ввиду на реализацию сабжа.

    «по несколько часов на 2000 наименований» (14) — это я даже не знаю как комментить. гг студенты писали?

    (17) —

    на 1 позицию может до 2 секунд

    — можно кусок кода в студию?

    Reply
  19. noook

    (18) tango, я понял что на реализацию сабжа

    Reply
  20. iov

    (17) со всем уважением — нет. условия контракта не позволяют. да и не я писал.

    Основная суть тормозов — не удавалось получить в запросе нужные данные…

    Про оптимизацию я соответственно знаю — но это не моя задача.

    а расчет на 2000 позиций — это уникальные прайсы для клиента со всеми правилами. (на мой взгляд можно сократить вполовину — но тут надо будет исправить ошибку в архитектуре БД а это уже отдельная песня…)

    Да и я не претендую на супер код — просто говорю что уже есть и как работает. Моя хата — производство — пока руководителей устраивает формирование цены — трогать не собираюсь (альтруизм в этом деле — враг).

    Я лелею надежду написать статью — для решения проблемы «всем миром» и получения оптимального механизма/алгоритма

    который пользователи инфостарта смогут использовать уже дальше. Но время — искусный враг.

    Reply
  21. ander_

    (9) tango, ага 🙂

    интересны идеи, ибо вскоре планируется перенос управленческой базы на 8Х. Сейчас реализовано на 7.7 с 1с++, справочник 120т позиций, чуть более 10 типов цен. Все что нужно хранится в 1с (фактически — это правила), а на основе этих данных триггерами обновляется максимально развернутая (для быстродействия) матрица накруток. Так вот вопрос: то-же самое придется делать и 8-ке? или все-таки может есть идеи получше?

    Reply
  22. tango

    (21) ander_, держать матрицу в отдельной таблице, можно в той же базе, но созданной не конфигуратором. и средствами же скл ее пересчитывать

    Reply
  23. tango

    +(22) это как бы бесплатная идея

    Reply
  24. iov

    (22) Работали с такой схемой — нормальная схема только с одним важным условием обновление цен — раз в сутки иначе как только меняю цены -тут же пытаются их использовать — но сама технология даже где то на этом сайте была.

    Reply
  25. tango

    (24) iov, а если сделать ее где-то в темпе, то, наверное, можно даже будет обращаться к ней как 1сной временной

    Reply
  26. iov

    (25) вопрос в том что 2500 -4000 номенклатуры * 2*количество контрагентов * типов цен * кроче таблица огромная… я пробовал.. 4 раза кончал сервер по памяти вешал…

    Reply
  27. iov

    (25) Я себе пометил — как только напишу статью — приглашу на обсуждение решения…

    кстати в Питер ждать 15-16 ноября? Я бы не отказался лично пообщаться.

    Reply
  28. tango

    (27) iov, весьма польщен. но я там был по весне уже 🙂

    пс: кепочку вот купил

    Reply
  29. iov

    (28) Я настаиваю — приезжайте тут будет много 1снегов в лицо всех будет возможность запомнить на всякий случай.

    На конференцию я думаю вопрос с проходм я решу.

    Reply
  30. tango

    (29) iov, меня управляющий не пустил даже на московскую инталевскую тусовку (они там про КиПиАй что-то парят)

    типа за свой счет — пожалуйста… гы

    реально жаба душит за каждый дневной получк

    Reply
  31. iov

    (30) меня тоже не пускали — напомнил что они минимум 7 дней отгулов задолжали. Ну тогда летом велкам в Питер…

    Летом мы регулярно вечерне ночные фото прогулки устраиваем я думаю Доржи тоже присоединится- он теперь тоже фотограф… В общем коньяк обещаю — фото не обещаю. 🙂

    Reply
  32. tango

    коньяк… да, пятница

    Reply
  33. tango

    и две минуты до старта

    Reply
  34. ander_

    (22)(23) tango, спасибо. В (21) об этом и писал, только не уточнил что «матрица» создана не средствами 1с (по-другому бы на таких объемах и не взлетело). Т.е. такой вариант уже был реализован, и работает. Просто думал, может еще какие очевидные варианты имеются.

    Reply
  35. ander_

    (24) iov, для этой цели удобно вешать триггеры на таблички влияющие на цену. Как только изменился один из параметров — пересчитываем соответствующие цены (естественно не все, а только те, которых это касается). Тогда всё работает практически в реалтайме.

    Reply
  36. iov

    (35) Из-за объемов данных + из-за необходимости хранить историю изменения + время просчета слишком длительное +

    изменения вносятся несколькими людьми и они могут вносить изменения в одной группе даже в подчиненных элементах , треггеры не использовались. Я тоже об этом подумал про них как увидел все это…

    Reply
  37. noook

    приятно у себя читать умных людей

    спс Вам

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *