[ОБУЧАЛОВКА] Как с минимальными затратами сделать "красивый" прайс




Принцип обмена данными из 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='\

15 Comments

  1. 50 чел посмотрело.. никто ниче не сказал…

    вывод — написал лажу?

    Reply
  2. Почему? Неплохое техническое задание на создание выделения прайса 🙂 Но это далеко не минимальные затраты, это обычная работа программиста

    Reply
  3. Ну так и буум стремится, чтобы программист обходился минимальными затратами 😉

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

    пятому хоть глаза выколи чтоб колонка «цена» шла пятой, а не 4-ой (наша программа по другому не умеет — уроды моральные 😉 седьмому нафиг не надо по мылу слать — дайте ему ссылку ftp-шную откуда он стянуть сможет… стоит насущная задача конструктора прайсов и способов их доставки… если кто подскажет м.б. готовый полуфабрикат/решение — буду благодарен (втроенный язык и конфигуратор не предлагать — это я и сам могу 😉

    Reply
  4. Egor

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

    Reply
  5. > Идеи и реализации на коленке многие могут изобразить, а вот написать грамотную завершёную статью — нет.

    «Грамотные завершенные статьи» — только за гонорар.

    Статья не преследовала цели сделать за вас все,а как раз наоборот — натолкнуть на идею/возможность реализации… 😉

    Reply
  6. O-Planet

    Охеренеть… Ну ни в жизни бы не стал использовать столь полезный механизм свойств номенклатуры для раскраски документиков печатных… Нет, это — не метод. Надо учитывать, что чаще всего товары объединяются в группы, и свойства товара в прайсе может определяться свойствами, установленными на его группу. Потом, у одного моего клиента в прайсе ок. 8000 позиций. Так что он мне, интересно, скажет, если я ему предложу на каждую позицию свойства прайса выставлять…

    Я бы, решая эту задачу, пошел по пути исключений. Сделал бы что-то типа документика «Прайс лист: приоритеты» и в нем бы уже указал те товары, которые надо делать жирными или красным (синим, зеленым) цветом. А все остальное — по умолчанию, стало быть, если оно в этом документе не фигурирует.

    Вывод:

    1. Такое решение — более простое для понимания менеджера. Он теперь просто сам набирает в документ те товары, которые хочет как-либо выделить

    2. Оно менее ресурсоемкое и более быстрое

    3. Логика использования свойств номенклатуры для аналитических целей не нарушена!

    Салон продаж «БЕЛКА»: Бизнес Электроника (http://www.belkamag.ru)

    Reply
  7. CheBurator

    > Сделал бы что-то типа документика «Прайс лист: приоритеты»

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

    > указал те товары, которые надо делать жирными или красным (синим, зеленым) цветом.

    аналог — выставляем нужное значение свойства.

    Имеено такая парадигма ближе работе менеджера — менеджер мыслит не регистрацией событий документами, а выполняет некие процессы, (которые у тебя привязываются к 1С-ой методологии доков).

    Можно и твой и мой вариант использовать, а можно — и третий придумать…

    А насчет ресурсоемкости — не надо ля-ля! В моем варианте пишется код обработки и все. В твоем — создаются новые объекты базы данных (документЮ, его реквизиты и пр)…

    > менее ресупсоемкое и более быстрое — возможно… (см.выше 😉 зато мое — универсальнее..

    > Логика использования свойств номенклатуры для аналитических целей не нарушена!

    Ваще бред: с какого бодуна ты решил что свойства номенклатуры используются для аналитических целей…? Аналитические цели — всего лишь один вариант применения свойств, у меня например есть свойства по которым никогда аналитика не строится/не используется — мне что, нельзя так свойства применить? у меня на механизме свойств, например, контрагентов — целая система управления рассылкой прайсов построена… и ничего.. успешно работает…

    Успехов!

    Reply
  8. CheBurator

    > Нет, это — не метод. Надо учитывать, что чаще всего товары объединяются в группы, и свойства товара в прайсе может определяться свойствами, установленными на его группу.

    ..

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

    ..

    > Так что он мне, интересно, скажет, если я ему предложу на каждую позицию свойства прайса выставлять…

    ..

    Это ваши проблемы, если вы не можете путем использования стандартного универсального механизма подбора объектов определить совокупность объектов и прописать на них свойство… а не лопатить 8000 позиций вручную…

    Reply
  9. O-Planet

    Эх, вот не учат программировать видно в Москве…

    Что лучше, документ или обработка. Да еще и приписал парадигму логики менеджера! Ты сядь и запраграммируй эту свою байду. Чем лучше документ? ТАМ ВСЕ НАГЛЯДНО. Его можно открыть и изменить. Можно ваще удалить. И никаких записей в справочнике свойств. Но ты главного не уловил: ты предлагаешь решение в лоб, а я — от обратного.

    А по поводу анализа на основании свойств… Что сказать? У меня в одном ювелирном салоне в свойствах прописан материал, камень, размер, обработка, форма, тип изделия. Ты даже во сне не представишь, какую развернутую картину продаж на основании этого видит директор!

    Reply
  10. CheBurator

    Ну, насчет как кого и где учат программировать — я уже высказался про отчет по остаткам, так что — не будем…. 😉

    А по существу: я предложил/показал метод, вполне работающий, с минимумом кодирования — сто не нравится-то?

    Я ж ниже писал — кому-то удобнее документом, кому-то в свойствах прописать — не вопрос.

    А использовать свойства для построения развернутой картиный продаж — ну и что? и у меня так есть… только я не замыкаюсь на использовании свойств для построения аналитических отчетов… вот и все…

    Reply
  11. alexqc

    Я не юзаю типовую российскую ТИС, поэтому как там сделаны свойства не знаю.

    Но судя из вашего кода, это подчиненный номенклатуре справочник с реквизитами ВидСвойства и ЗначениеСвойства, которые тоже справочники.

    Тогда вопрос:

    НАФИГА искать в символьных строках

    |Условие (Найти(ВРЕГ(ВидСвойства),»»ВЫДЕЛИТЬВПРАЙСЕ»») <> 0);

    |Условие (Найти(ВРЕГ(ЗначениеСвойства),»»ДА»») <> 0);»;

    Ведь для этого 1Ске для каждого элемента придется вызывать свои ф-ции Найти,ВРЕГ

    Гораздо логичнее и быстрее было бы сначала найти в справочнике видов свойств — то которое «ВЫДЕЛИТЬВПРАЙСЕ» (поместим его, наприер, в переменную ВидСвойства_Прайс), в справочнике значений — то которое «Да». И потом запрос бы преобразовался в 2 условия на равенства

    |ВидСвойства = Справочник.СвойстваНоменклатуры.ВидСвойства;

    |ЗначениеСвойства = Справочник.СвойстваНоменклатуры.ЗначениеСвойства;

    |Условие (ВидСвойства=ВидСвойства_Прайс);

    |Условие (ЗначениеСвойства=Значение_Да);

    При этом — никаких вызовов ф-ций языка, все делается на уровне движка БД.

    Справочник наверняка индексирован по полю ВидСвойства, и такой поиск был бы еще и оптимизирован…

    Ну а если в справочнике несколько значений ВЫДЕЛИТЬВПРАЙСЕ — тогда можно создать СписокЗначений? b использовать условие «В». Врядли таких значений много настолько, чтобы поиск подстроки стал эффективнее поиска по «В». Но лучше — привязать все такие свойства к одному ВидуСвойства, а лишние виды — грохнуть.

    Reply
  12. CheBurator

    Конечно же, осноное назначение статьи — возможность обойтись механизмом свойств.

    Поэтому особенно с конкретной реапусть сделает быстрее..

    особо реализацией в статье не заморачивался — надо бы было код для позиционирования на свойствах и пр… А если чела подход устроил — уж соптимизирует как надо…

    Спасибо за внимание к статье.

    Reply
  13. a_E

    а если потребуется прайс поэкономней печатать две колонки на страницу в альбомном формате к примеру тогда что? (1колонка-номеклатурный номер, наименование, цена) + разбиение по группам..

    Reply
  14. CheBurator

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

    Reply
  15. PochekutovOleg

    Спасибо

    Reply

Leave a Comment

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