<?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='\
а если нужно распределить сумму 10 на 3 одинаковых документа с одинаковым долгом 3 ?
(1) kvikster,
Как понять «Распределить на три одинаковых документа»? Если документы (или договоры) с одинаковой суммой, но разными кодами, то излишек распределится в порядке очередности кода на сколько хватит. А если это одинаковые документы, то в чем тогда смысл распределения? Исходная таблица по определению не должна содержать одинаковые значения документа. Если они одинаковые, то их нужно сгруппировать до распределения. В конечном итоге предполагается получить движения, где документ — измерение, а распределенная сумма — ресурс. Какой смысл в движениях с разными ресурсами, но одинаковыми измерениями?
Поясните или приведите пример задачи, если я неправильно понял.
Для полноты картины не хватает ссылки на основательную статью по этой теме :«Честное распределение суммы по таблице значений» . Безотносительно техники решения в указанной статье сравниваются разные принципы отнесения ошибок округления на конкретные строки базы распределения. Из статьи, кажется, следует, что упорядочивание по величине долга — не лучший метод. Мне кажется, что лучше упорядочивать по величине ошибки округления. Тогда будет работать критерий минимакса ошибки представления.
Похожая задача вроде бы возникает при масштабировании областей в растровой графике. Когда требуется увеличить площадь под линией на заданную величину, сохранив ее форму. Используемый здесь метод будет всегда поправлять верхнюю часть ограничительной линии, внося заметные на взгляд искажения.
Но по сравнению с отнесением всей невязки на одну строку (что приводит к еще более простому запросу) этот запрос получше.
(4) Dimel, Действително плохо искал. Такое простое и изящное решение, мог бы и сам додуматься. Можно ссылку, откуда это? Здесь на Инфостарте есть? Хотелось бы добавить в статью, но без ссылки на источник некрасиво будет.
(3) ildarovich, Отличная статья. По хорошему, нужно не ссылку сюда добавлять, а вообще статью с публикации снять. Как считаете, имеет смысл реализовать пакетными запросами все описанные там варианты, а не только вариант 4, и сравнить производительность на тестовой базе? Вариант с распределением по ошибке округления точнее, но приведет к лишнему этажу в пакетном запросе, что скажется на скорости. Я так понимаю, что 3 вариант реализован в комментарии (4) Dimel
(6) иной раз изящность решения задачи (ну скажем выпендрился и написал распределение в запросе) нафиг не нужно из-за своей сложности восприятия через некоторое время.
Я сторонник не пихать все и вся в запросы без необходимости. Да и на практиче возникают ситуации и у меня были, когда нужно распределить 4 числа (БУ НУ ПР ВР) параллельно по 4-м базам (БУ НУ ПР ВР) и потом еще вывести погрешности на «чистую воду» и все проровнять (решалась задача постатейного закрытия 20, 23 счетов в БП 2.0, где субконто СтатьяЗатрат не оборотное, а потом все переделывалось под БП 3.0).
К слову в БП 2.0/3.0 стандартные алгоритмы некорректно распределяют амортизацию, когда она распределяется по способам отражения, где очень много прописано разных дробных коэффициентов. Ошибка выражается в том, что правило БУ = НУ + ПР + ВР не выполняется, а должно. Пришлось написать обработку выравнивающую положение дел уже после расчета и распределения амортизации.
Увы, но переписка с 1С ни к чему не привела, они тупо отписались, что не смогли воспроизвести ошибку… хотя все предоставлял им…
(6)
Зачем снимать? ) Пусть будет бесплатный вариант для тех, кто хочет не особо разбираться в теории, а взять чистый практический пример.
(7) Brawler, Все зависит от задачи. Пихать в запросы все подряд смысла нет, когда объемы обрабатываемых данных относительно невелики. Или когда задача разовая. У меня речь идет об огромных массивах, обрабатываемых ежедневно. Речь идет о конфигурации для ЖКХ и распределении оплаты коммунальных услуг по статьям по каждому лицевому счету. «Не смогли воспроизвести ошибку» — обычное дело 🙂
(5) В 2012 году было обсуждение на Мистеhttp://www.forum.mista.ru/topic.php?id=616801 .
Спасибо! Аналогичную задачу решал на днях (распределение 20-х счетов). Запросом круче.
За вот — такие решения в рабочих конфигураций хочется бить по башке и крайне сильно.
Желаю вам приятного геммороя при раскапывании проблем, возникающих при вкрячивании таких запросов например в проведение документов (реверанс в сторону 1С).
(12) urrymca,
За подобные запросы в проведении документов действительно надо бить по голове. Все суммы должны быть рассчитаны до проведения и сохранены в табличной части документа. Динамический расчет при проведении запросом или кодом породит серьезную проблему при необходимости перепровести документы. Особенно если у них последовательность проведения изменилась. Причем здесь само решение? Задача поставлена распределить. Задача решена. А если кто-то вставит это в проведение — сам виноват. Я больше вам скажу, в той нетиповой конфигурации (за авторством КАМИН), с которой я в данный момент работаю именно так и было реализовано. Не запросом, правда, а кодом. Крайне запутанным, кстати. Но это еще полбеды. Эти ребята предусмотрели два варианта проведения. С распределением сумм до проведения и сохранения в табличной части с возможностью коррекции. И с распределением во время проведения. Мало того, что перепроведение такого документа было черевато. Так еще и код распределения был в двух разных местах продублирован. Распределение при проведении — в модуле документа. А распределение на форме — в модуле формы. И код этот чуть-чуть отличался. Видимо в какой-то момент исправили небольшую ошибку в одном из вариантов, а во втором — забыли. Что при этом происходило, думаю, объяснять не надо.
А сам запрос прекрасно будет жить в рабочей конфигурации. Замечу, что при решении типовых задач никоим образом не будет лишним воспользоваться заранее придуманными алгоритмами. И это касается не только 1С. Если задача трудоемка и существует алгоритм, позволяющий увеличить скорость решения в разы, то им можно и нужно воспользоваться. На то он и существует. Это, кстати, сравнительно простое решение. Бывают гораздо более сложные. Разбираться в его коде при этом можно только один раз — когда первый раз увидел. Или вообще не разбираться, если источнику доверяешь. Главное знать, где его границы, где входные данные и где результат.
(10)(10) Dimel, а зачем так сложно с тета-соединением и вычитать потом его ? Не догоняю… так тоже работает
Показать
(14) rozer, Попробуй своим запросом распределить 10 на 3 равные части (куда у тебя ошибки округления денутся?).
(15) Dimel, попробовал получилось 0.77+1.54+7.69=10 Но наверно да, ты прав, про округление я не подумал но как понять про использование ВТ «ДанныеСНакоплением» я так и не понял ( Чот мудреный запрос выходит… сам придумал или подсказал кто? Смысл можешь пояснить?
(16) rozer, Смысл заключается в том, что ошибка округления накапливается и учитывается по мере распределения. Попробуй расписать процесс в числах с распределением, например, 20 на 7 одинаковых строк. Обрати внимание на распределение последней строки. Туда попадает весь остаток, независимо от доли. По аналогии происходит и в предыдущих строках.
(4) Спасибо очень помогло!
А что делать, если есть еще одна группировка. И нужно распределять внутри группировки
Т.е. если добавить к примеру в задаче контрагента. И распределять долг контрагента по его договорам?
(19) Лучше вообще не использовать приведенный в публикации метод. В обсуждении приведен другой вариант, более надежныйhttps://infostart.ru/ajax/comment_pub.php?t=135893&c=4