XXIV Олимпиада по программированию учетно-аналитических задач (в среде 1С)




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

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

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

<?php // Полная загрузка сервисных книжек, создан 2025-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='\

30 Comments

  1. marsohod

    Максимальную прибыль дает эмиссия национальной валюты, ее вывод на спекулятивный рынок Forex и приобретение доллара, евро, золота. Конечно, если Вы контролируете Центральный Банк.

    Ой, что это я сказал…

    © Сами Знаете Кто

    Reply
  2. Serj1C

    ))

    Reply
  3. Arabo_xv

    А где можно посмотреть требования к работе (время работы, объем доступной памяти). В каком виде должен выдаваться ответ?

    Reply
  4. Serj1C

    (3) Требования всегда описываются в задании. Время работы — чем меньше тем лучше. Объем памяти строго не ограничен, сдесь большее значение имеет красота решения. Именно в этой задаче ответ выводится в документ, где состав и тип полей жестко указан в конфигурарторе.

    Вообще олимпиада по 1С имеет принципиальные оличия от олимпиад по спортивному программированию (количество задач, объемы тестов, экономическая направленность)

    Reply
  5. Arabo_xv

    Просто эта задача легко решается жадным алгоритмом. Если не ограничена память то я тогда не могу понять в чём сложность зачи :(. Без ограничений она решение её тривиально.

    Reply
  6. Serj1C

    (5) Хорошо. Сколько ты думаешь времени у тебя уйдет с отладкой? 2 часа?

    Попробуй засечь время. На олимпиаде есть 4 часа.

    И пришли мне плиз решение.

    Мне тоже кажется легко. Но однозначного решения если курс покупки <> курсу продажи я не нашел. Это уже интереснее.

    Reply
  7. Arabo_xv

    К сожалению я не могу скачать условие задачи (сегодня уже скачивал с инфостарта файл) 🙁

    Reply
  8. Arabo_xv

    Значит так алгоритм решения следующий:

    1 — Определяем дату начала и дату конца торговли.

    2 — Делаем цикл по дням с даты начала по дата конец — 1.

    3 — Если есть закупленная валюта то продаём её.

    4 — Получаем срез последних за текушую дату и на следующий день.

    5 — Для валют у которых курсы отличаются берём ту валюту по которой вырожение (КурсКонца — КурсНачала) / КурсНачала максимален и на все активы покупаем эту валюту.

    После цикла проверяем если всё ещё есть закупленные валюты то продаём их.

    Этот алгоритм даёт максимальную прибыль но не оптимален к ресурсам вычислительной техники.

    PS реализация займёт не более часа 🙂

    Reply
  9. Serj1C

    (8) логика, конечно, верная, но… Получать срез последних в цикле — не комильфо по стандартам методики разработки 1С. Мне тоже казалось час надо, а получилось полтора как минимум. И потом еще мелкие штришки. Так что зря ты так ) Напиши, сделаем замер производительности.

    Reply
  10. Arabo_xv

    В условиях сказанно что победит тот кто получит максимальную прибыл и только в случае если прибыль будет одинаковая будут оценивать другие критерии.

    Reply
  11. tango

    (8)

    3. сначала по 5. определяем валюту к покупке, и если имеющаяся валюта не равна по 5., то продаем ее

    не забываем, что за каждую транзакцию отчисляем бонус оператору

    Reply
  12. Serj1C

    (10) думаю, что итоговый навар у нас получится одинаковый

    (11) в условиях задачи про коммисию ничего не сказано

    Reply
  13. tango

    (11) тогда лишнее движение будем учитывать при прочих равных

    Reply
  14. Arabo_xv

    (12) Ваш алгоритм будет хромать если курсы не каждым днём вносить. В моём случае я всегда получаю максимальную прибыль.

    Reply
  15. Arabo_xv

    (11) Картину это не меняет. Это меняет лишь количество операций, а не прибыль.

    Reply
  16. Serj1C

    (13) мое решение (уже в каркасной конфигурации) минимум операций делает.

    (14) хромать он не будет, он на это заточен, проверь

    (15) согласен

    Reply
  17. Arabo_xv

    (16) Хех у вас вообще «Не зачёт!» если слегка подкрутить курсы.

    Строка №5 Превышен денежный лимит -0,01<>1 015 364,406

    Строка №9 Превышен денежный лимит -242,65<>1 034 502,5985

    Строка №11 Превышен денежный лимит -242,53<>1 046 427,584

    Строка №13 Превышен денежный лимит -242,66<>1 155 906,344

    Строка №15 Превышен денежный лимит -242,64<>1 158 187,7232

    Строка №17 Превышен денежный лимит -242,61<>1 183 783,0014

    Строка №19 Превышен денежный лимит -242,58<>1 282 827,7332

    Свой решение я написал за 38 минут + до этого минут 20 потратил на ознакомление с задачей. Работает она в 2-3 раза медленнее, но даёт максимальный результат и не имеет ошибок округления.

    Reply
  18. Serj1C

    (17) Любопытно! Поделишься подкрученными курсами и своим решением?

    Reply
  19. Arabo_xv

    (18) http://depositfiles.com/files/l0ghbrjoy пароль 123456.

    Reply
  20. Serj1C

    (19) Хорошая попытка. В 7й и 8й строчке на лицо переполнение Количества.

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

    Ваше решение в студию 🙂

    Reply
  21. Arabo_xv

    (20) А разве не на вас лежит ответственность за контролем переполнения? В условии сказанно что вы не можете исползовать больше чем у вас есть средств. Дело в том что вы даже не пытаетесь избежать ошибки округления а значит всегда есть исходные данные когда у вас будет ошибка. Моё решение http://depositfiles.com/files/oa8oxkf7f пароль 123456.

    PS Исходные данные я поменял именно из-за того что заметил в вашем решени перерасход средств.

    Reply
  22. Serj1C

    (21) Мне понравилось. Хоть и медленней, но это хорошее решение! Плюс.

    Если Вы еще студент, очень рекомендую зарегистрироваться на сайте Финансовой Академии (http://fa-kit.ru/) и участвовать хотя бы в заочном туре, у вас все шансы на победу! А если не студент, то можно будет нам вне конкурса посоревноваться.

    Было оч. приятно дискутировать!

    Reply
  23. Arabo_xv

    Уже давно не студент 🙂 Посмотрим если будет на работе возможность буду участвовать.

    Reply
  24. vlad3190

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

    Reply
  25. Serj1C

    (24) Мало себе это представляю.

    Reply
  26. RegrZ

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

    детский сад какой-то а не олимпиада.

    Reply
  27. RegrZ

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

    Reply
  28. Serj1C

    (26) При всей простоте задачи ни один студент 4го курса не смог ее решить и выйти во второй тур. Было печально.

    Вот кстати, задание олимпиады этого года http://fa-kit.ru/main_dsp.php?top_id=22317

    Reply
  29. Irwin

    У кого-нибудь есть финальное задание 2008 года?

    Reply
  30. Serj1C

    (29) Irwin, на официальном сайте организатора — http://fa-kit.ru/main_dsp.php?top_id=3730

    Reply

Leave a Comment

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