Еще один взгляд на проблему «жизнь без последовательностей». Часть вторая (практическая)




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

34 Comments

  1. ildarovich

    🙂

    Reply
  2. Арчибальд

    Ну вот, глюк, комменты исчезли.

    Я к тому, что задача поиска пар «двумерна» (в «измерениях» МассивПриходов х МассивРасходов). А в 1х1, как я понял из описания, по этим «измерениям» мы оптимизируемся по отдельности.

    В алгоритм я лезть не стал, на задачу смотрю с эстетической точки зрения старого оптимизатора 😀

    Reply
  3. Шёпот теней

    … хм … трудно ВЫсказать что-либо по столь аргументированному труду …

    но «занимаясь» теорией можно сказать следующее:

    … если нужно знать реальные остатки по складам (партия, количество, цена, себестоимость, и др), в рамках единой системы учёта, то как не вертетЬся а «временная ось» тут или там, в том или ином виде появится … а если ОНА, временная ось, появилась то остальное только «форма» работы с ней (т.е. с последовательностями документов) …

    можно выбрать 7-ый путь … можно 8-ный … можно, как встречалась в обработке (тут на ИС), перепроведение только касающихся данной номенклатуры (документов или строк документа) …

    … но факт остаЁтся фактом … перетасовка документов в учёте (хоть бумажном, хоть электронном) без наличия временной оси — НЕвозможна … следовательно влияние «перемен» на ВСЮ цепочку зависмых документов избежать не получится … !

    … вечных двигателей не придумано … нет учёта без «временной оси» … вот …

    п.с. ну «форма» … ну а «форма» она и останется только «формой» … хоть УУ хоть БУ — а данные -то надо собирать …

    … такаяВОТбалаМУТЬвот …

    Reply
  4. ildarovich

    (2) Я видел Ваши комментарии. Вы совершенно верно подметили, что трудоемкость метода 2х2 зависит от числа документов по данной номенклатуре нелинейно и даже, возможно, квадратично. Это также подтверждается графиком. Правда, названия методов давались из других соображений.

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

    Метод 2х2, как видно из последовательности таблиц в решении, производит точечные изменения в структуре списания, но требует поиска этих точек, на который и уходит львиная доля времени.

    Reply
  5. ildarovich

    (3) Абсолютно согласен.

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

    Reply
  6. Шёпот теней

    (5) … поэтому и указал «… перепроведение только касающихся данной номенклатуры (документов или строк документа …» …

    … особенно важен поиск таких документов или строк (что то же вызывает отдельную проблему) … или идти путём 1С (общим чохом) …

    … всё таки «проще» наладить дисциплину работы с документами — чем возиться с «ЗЧ» (задним числом) … особенно если учесть глобальность 1С и её попытки позиционироваться для крупных и очень крупных предприятий (разветвлённые, разделённые базы) …

    … вот …

    … мне кажется вопрос больше касается и «упрощении» учёта и упрощения механизма перепроведения (полного, по-отдельным документам, по отдельным строкам документам) … чем (не научных) попыток отказаться от «временной оси — последовательностей» …

    … 1С — существует … переделывать никто не будет …. механизмы новых перепроведений в рамках штатных объектов более полезны чем поиск новых «последовательностей» … яркий тому пример обработки ВалерычА и anig99 и других товарищей …

    … вотНЕпопад …

    Reply
  7. Арчибальд

    (6) Лом, конечно, согнуть трудно.

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

    А вообще, Документ 1С надо бы приблизить к реальности. Т.е. иметь не только ДатуДокумента (дату, с которой в БД записываются движения), но и ДатуАктуализации (дату проведения). Тогда проведения задним числом вообще не будет, и появляются широкие возможности для оптимизации алгоритмов проведения.

    Reply
  8. Шёпот теней

    (7) … идея конечно «интересная» !!! но с точки зрения:

    «… если нужно знать реальные остатки по складам (партия, количество, цена, себестоимость, и др), в рамках единой системы учёта, то как не вертетЬся а «временная ось» тут или там, в том или ином виде появится … а если ОНА, временная ось, появилась то остальное только «форма» работы с ней (т.е. с последовательностями документов) … »

    какое это имеет отношение … всЁ равно будем вынуждены «лопатить» всю последовательность взаимосвязанных объектов чтобы «высчитать новую реальность» … остатки, партия, цена, себестоимость … …. …. ……

    … вот …

    п.с. всЁ таки проще «создать» механизм проведения и перепроведния на конкретном предприятии упростив его … и ! одновременно ужесточив дисциплину работы с документами (в этом корень основной проблемы в повседневной работе) — а здесь «мама родная … ! …» …

    Reply
  9. Арчибальд

    (8)

    механизм проведения и перепроведния на конкретном предприятии

    И я об этом. Не в типовой конфигурации, а в оттюнингованной под конкретику. Добавляем в документы общий реквизит «ДатаАктуализации» и, пользуясь ей, то как дубинкой для воспитания нерадивых юзеров, то как гибким инструментом срубания бабок на пересортице, то как оптимизатором восстановления последовательности, — делаем что хотим.

    Reply
  10. ildarovich

    (6) Я не противопоставляю доработку типовых конфигураций и создание принципиально новых. Можно заниматься и тем и другим: пропалывать грядки, распаханные и засаженные 1С и пробовать выращивать что-либо новое в чистом поле.

    Обратите внимание на механизм резервирования в Управлении торговлей 11, механизм остатков в Логистике и управлении складом 3 — они появились казалось бы на пустом месте.

    Reply
  11. hogik
    Reply
  12. Шёпот теней

    (10) … а мне нравится ВАШ математический подход к проблеме … ! … проблема только не в «изготовлении» а в «повторении» и в «распространении» … да и с «пониманием» будут проблемы …

    ведь казалось бы доступ к таблицам — построчный (в эСКуэЛ-е) … а ПЕРЕпроводим все документы … зато ОДИН механизм и УНИВЕРСАЛЬНО …

    … вот …

    (11) … хм … перетасовать документы можно … если не нужно знать актуальные остатки по складу на реальную секунду … иначе — временная ось … и т.д. + хитрая взаимосвязь и взаимовлияние документов друг на друга …

    … на мой взгляд 7-ная ТА была самым лучшим способом … если данных много можно свести её период к полу-месяцу — неделе … но видимо при «больших» обЪёмах это стало не выгодно или отказ от ТА был смелым творческим эксперментом …

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

    … вот …

    Reply
  13. ildarovich

    (7) Такая возможность рассматривалась. Правда, параметр назывался ДатаКоррекции, а не ДатаАктуализации, но по сути это тоже самое. Пока скажу только, что смысл есть, причем не только из соображений логики.

    Reply
  14. hogik

    (12)

    Александр.

    1) Про «актуальные остатки по складу на реальную секунду» мы уже беседовали в другой теме. 😉 Никакой «временной оси» для их получения не требуется, т.к. это одно число (штуки на полке). Остатки на НеРеальную секунду надо либо хранить, либо насчитывать. Если хранить, то блюсти последовательности. Если не хранить, то оптимизировать скорость алгоритма их «динамического» расчета. И делать этот расчет только когда это требуется, а не тупо считать всегда при «проведении» документов и тщательно оберегать последовательностями. 😉 При этом расчет производить и в отчетах и в «проведении» документов. Точнее при применении функции, типа, ПолучитьНаДатуЧегоНиБудь() во всех модулях системы. Простейший алгоритм это просмотр всего движения от актуального «итога» предыдущего расчета до требуемой даты. За актуальность «итога» отвечает любое изменение движения документом, стоящего «раньше» актуального — просто сбрасывается флаг актуальности «итога» на дату, указывающий на НеАктуальность всех «итогов» расположенных «ниже».

    Интересный алгоритм для реализации SQL-ем. 😉

    Вот такой алгоритм. Или я ошибаюсь?

    2) «или отказ от ТА был смелым творческим эксперментом»(с)

    — Не думаю. Причины отказа — это еще один шаг в осмыслении понятия «документ». Его места на оси времени, в схеме базы данных и в сути «автоматизации» предприятия (не только учета). Думаю, что они придут к тому, что документ это, например, только НомерДатаВремя твердой копии в схеме базы данных (образно говоря). А всё остальное содержание «документа» (агрегата данных, подсхемы) ссылается на ЭТО. И «документ» не является единым целым. Т.е. объектная или иерархическая (сетевая) модель хранения данных и представления предметной области. Но это другая тема. Можно, если хочешь, поговорить и об этом… 😉

    Reply
  15. anig99

    плюс за осуществление мечты использовать в 1с хоть какой-нибудь математический аппарат!

    Reply
  16. NCCSOFT

    (7) Элегантный механизм может быть реализован в виде отдельного нового метода

    ПровестиВсеДокументыЗаОднуСекунду(«FIFO»);

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

    Практическое доказательство что это возможно еще сделал в 2008 году Проведение по FIFO всей базы за 1 секунду ….

    Reply
  17. Поручик

    (15) плюс, конечно.

    Только смотрю на это произведение и куда его присобачить? 😀 Перепахать типовую, чтобы быть вздёрнутым на воротах проходной в назидание другим. Местное франьё дебильное заклюёт, он что-то сделал, мы разобраться не можем.

    Reply
  18. anig99

    (17) альтернативная подсистема

    Reply
  19. Шёпот теней

    … а зачем телеге — реактивный двигатель … ? … вот …

    Reply
  20. molot

    Мммм…. Вот есть же в 8-ке забавный механизм определения записей регистра, которые необходимо рассчитать заново при изменении других записей этого регистра… Только это — в регистрах рассчета… Почему, елки-палки, так сложно было придумать подобный механизм для регистров накопления? Дык нет же, присобачили к, в общем-то, неплохой платформе самое кривое, что было в 77 — последовательности, да еще и в почти не измененном виде…

    Reply
  21. Новиков

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

    По поводу выхлопа от предложенного решения (имхо): кто помнит, еще до самого бета-тестирования 1С 8.0, на партнерках проскакивало что платформа САМА будет вычислять нужную последовать документов в случае если они проводятся задними числами на временной оси и САМА же опять перепроводить эту самую последовательность. И! И в методичках самых первых от 2004 года, вообще пишут открытым текстом — что использование механизма последовательностей является плохой «устаревшей» тенденцией. Прошло с того года почти 7 лет: к чему пришли? К идеи — что в момент проведения документов нужно контролировать только жизненно-необходимые параметры (и то не всегда), а все остальное дописывать некими регламентными заданиям когда-то там ночами в конца месяцов, кварталов, лет. И кстати — новый механизм контроля остатков при проведении в 8.2 «Здравствуй» тоже! Поэтому, логично предположить, что теперь «с облаками» все будет плавно двигаться к тому, что на клиенте будет только фиксация какая-то элементарная самого факта, что оператор что-то сделал. Все остальные просчеты/портянки фифо/раузы-хренаузы будут делаться уже на серверах по специальным джобам-регламентам. В свете этого, думаю что автор может как-нибудь доработать его интересую идею до этой концепции, и вполне возможно замутить некую подсистемку. А почему бы и нет!?

    В любом случае — автору удачи!

    Reply
  22. fixin

    Честно говоря, по описанию не осилил. Подход уловил, но как реализуется на практике, не очень понял. Надо скачать и смотреть код.

    Не знаю, учел ли автор такой момент, что все движения по номенклатуре после текущего движения из регистра сведений можно получить ОДНИМ(!) запросом, соответственно, для экономии времени записывать только те записи, которые менялись. Тогда скорость будет еще больше. Вроде на использование этого нюанса автор не обратил внимания.

    Вообще описание очень сложное. Рекомендую упростить для чайников.

    Reply
  23. ildarovich

    (22) Так и делается. То есть выбирается вся структура списания номенклатуры после даты изменяемого документа до бесконечности. Вот запросы для выборки и для записи. Собственно время одной итерации складывается из времени чтения из регистра сведений, времени обработки в оперативной памяти, времени записи в регистр сведений. Я пытался оптимизировать все три операции. Основной интерес был в алгоритме обработки в оперативной памяти: казалось, что если изменение структуры списания малы, то также малыми изменениями можно привести ее к требуемому виду. Также внимание уделялось и записи, но там есть момент, который трудно обойти: запись в регистр сведений ведется «гранулами», которыми является таблица с фиксированными отборами. Мы заинтересованы выполнять запись гранулой максимального размера. Такой гранулой может быть либо все (сначала времен) списания по номенклатуре, либо по номенклатуре+приход. А промежуточного варианта нет! То есть запись все же идет не одним оператором, а порциями. В основе там то, что Update делается через Delete+Insert. 1C пока не собирается менять позицию по этому вопросу, хотя в последних версиях SQL возможность Mesh-Update (возможно, путаю термин) имеется. С другой стороны, это «технологические», а не алгоритмические ограничения. И они, судя по профилировщику, не столь существенны — запись не более четверти времени занимает от времени всей итерации.

    Reply
  24. CheBurator

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

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

    Reply
  25. CheBurator

    положил в закладки

    Reply
  26. Evil Beaver

    Математика — царица наук. Статьи ildarovich у меня всегда на отдельной почетной полочке.

    Вот и эту статью положу на видное место. Разбираться потом буду, и стопудов, оно того стоит 🙂

    Reply
  27. iov

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

    Reply
  28. ildarovich

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

    Reply
  29. CheBurator

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

    Reply
  30. iov

    (30) Таки и вопрос не для поедателей «собак» учета. Я сотни раз видел как этот маленький нюанс забывается…

    Reply
  31. CheBurator

    Все эти «минуса» и все их сопровождающее — от отсутсвия порядка в учете. И нежелания нагибать клиента (покпателя/поставщика) под работу правильно. Поэтому — все траблы чужих по отношению к нашей конторе людей — вылазять «минусами». У меня все проблемы — исключительно при псевдоисправительных действиях. Когда НАДО — а правильно или неправильно — никого не интересует. а ты потом за полторы тыщи км — мечешься как угорелый

    Reply
  32. iov

    (32) Зп 1снега фикси состоит из

    10% внедрении нового функционала

    20% Исправлении типового функционала

    30% Ошибок учета.

    40% Из «неправильно но очень нужно вчера в другой валюте на китайском языке написанном арабской вязью для очень перспективного клиента и чтобы цены динамически от яркости солнца и глубины океана подбирались на группу по постоянно меняющимся правилам. А И ЧТОБ САМО»!!!

    Reply
  33. iov

    (32) Типа шутка.

    Reply
  34. agrustny

    Все серьезно: полигон и термоядерные испытания мегатонной продукции.

    Проблема, боюсь, в том, что 1С покупается для печати отчетности в одобренном государственным бюрократическим аппаратом виде, а не наведения порядка в учете или тем более ускорения работы сервера, поддерживающего учет. Если 1С будет работать в 2 раза быстрее — никто за это им копеечки лишней не выдаст, а вот если вдруг что-то не так будет с отчетностью — сильно обидятся. По-моему, Нуралиев в каком-то интервью рассказывал, что на старте (в смутные времена) у них был момент, когда он полагал, что их закроют ко всем чертям по причине незнания бухгалтерских форм.

    А вообще фактическая неспособность программы контролировать причинно-следственные связи — это, конечно, крупное хулинство полное безобразие. Очень хочется Вас яростно плюсовать, как тут любят выражаться. (blank space to be filled by smailik)

    Reply

Leave a Comment

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