<?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='\
По-моему, в данном случае математическая модель не проясняет, а маскирует ситуацию. Поскольку никому не нужно складывать булки с отвертками, мы всегда находимся ровно в одном «слое», так что задача линейного программирования (ЗЛП) не более чем двумерна. А с учетом того, что Приход = -Расход, размерность и вовсе единична. Далее, ограничение «приход раньше расхода» на практике несущественно, ибо физически невозможна отгрузка несуществующего товара. Вот документально, даже юридически, она вполне возможна — хоть «задним числом» это назови, хоть «фьючерсным контрактом». И наконец, никакой целевой функции нет, так что это вообще не ЗЛП.
Интересная модель но к сожалению неприменима к жизни. Как например быть с себестоимостью в рамках конкретного периода?
(3) «Таблица — это регистр остатков с измерениями: номенклатура, документ прихода, документ расхода и ресурсом: количество.»
Таблица — это регистр сведений … без количества, поскольку вводим запись на каждую минимальную единицу учета, т.е. кол == 1
**
В измерения кроме Номенклатуры впихнем еще ЗначенияНабораХарактеристикНоменклатуры
**
В набор характеристик можно добавить число ЦенаПоступления
(2) Имея актуальную «структуру списания», то есть зная: что, когда и по какому документу приходило, в каком количестве, когда и по какому документу списывалось Вы дальше можете рассчитать что угодно.
Не хотелось усложнять, но, наверное понятно, что ЛИФО будет отличаться видом целевой функции (разность времен в числителе), при среднем в таблице будет одна строка, при среднемесячном — столько, сколько месяцев и так далее.
(3) Повеселил 😀
Ничего подобного я не думаю. Я это знаю и делаю. Нет у меня никаких последовательностей, и я прекрасно себя чувствую.
Не факт, что списание самых ранних партий всегда лучше. Но даже если и так, то после возврата части древней партии «трехмерная» оптимизация рассыплется — все последующие списания придется корректировать.
Тогда как бухгалтер/менеджер решение легко найдут…
Меня удивить вряд ли получится 😀
http://infostart.ru/profile/46936/blog/843/
прочитал бегло… так что не взыщите…
> То есть нам будет выгоднее списывать более ранние партии для конкретного расхода. И вот этот Ваш заветный наилучший способ …
— бяка (частная). при списывании с ранних партий — при необходимости впихнуть задним числом новый расход натыкаемся на нехватку товара — так как товар с ранних партий уже списан. А вот если списывать с ближайших партий — такого не будет…
.. но это все пока написал «на бегу».. в порядке дежурного бреда…
(7) Слово «выгоднее» я употребил для объяснения значения параметров целевой функции. Имелось ввиду, что это требование заставит считать лучшим решение распределения партий «как при списании по ФИФО». Не имелась ввиду динамика наших действий — целевая функция определяет требование к результату, который может быть получен хоть алгоритмом случайного поиска. Про алгоритм «метод потенциала» и его реализацию я вообще не упоминал, считая, что он и так известен. Этот алгоритм довольно мудреный и, если тут еще и его описывать, вообще запутаемся. Просто считаем, что он применяется и таким образом мы переходим от одного разрешенного состояния к другому в направлении оптимума (правильно распределенных партий). Не применяя абстракции от используемого алгоритма поиска оптимального решения, нам потребуется рассматривать отдельно уменьшение прихода, увеличение прихода, уменьшение расхода, увеличение расхода, перестановку приходов, перестановку расходов. А затем просматривать «волну изменений» в «таблице списания». Этого не нужно, если на данном этапе представить алгоритм «метод потенциала» как черный ящик, дающий оптимальное решение. Возьмите хотя бы Эксель и решение транспортной задачи через подбор параметра. Там Вы не видите процесса решения — видите результат.
Математика тут применяется для того, чтобы описать, что мы хотим получить в итоге. И каким требованиям должно удовлетворять решение. Существует ли оно вообще. Это и выводит нас на общий метод решения таких задач. Дальше остаются подробности реализации. И хотя «дьявол кроется в деталях», математическая обоснованность сходимости и скорости сходимости методов ЛП, дает уверенность в получении результата.
… не согласен с :
«Обозначим номенклатуру i, приход j, расход k. Функция X(i,j,k) »
почему:
1. эта функция истинна в случае номенклатура = приходу …
2. если номенклатура = НЕприход тогда это множество без сортировки …
3. если мы к п.2. добавляем партии, то номенклатура превращается в двойное множество …
4. если мы берём лифо-фифо то функции усложняется ещё и сортировкой внутри п.3 …
5. в связи с усложнённостью функции учитывающей пп. 2,3,4 мы имеем систему охреНительной сложность … а если ещё добавить сложность перекрёстных ссылок (влияние документов друг на друга) — то будет полная амба — типа 1С ….
… ВОТтакоеМНЕНИЕесть …
…
Что-то мне непонятно в этой прикладной математике! 😀
В реальном учете (не виртуальном, не теоретическом!) у «изменения документа задним числом» одна единственная задача — привести все последующие показатели к требуемым величинам. Т.е. переделать движения всех последующих документов!
Если не требуется изменять все уже рассчитанное, то ошибочный документ прошлого периода исправляется текущей датой: сторнируются все (или отдельные) его прежние движения и записываются новые.
Механизмы для решения обеих задач существуют. Что нового предлагает обсуждаемая медота?
(10)
Когда Вы говорите «переделать движения всех последующих документов», Вы как-будто подразумеваете, что последующий документ делает движения по регистру партий и что, не перепроводя его, ничего не сделать, поскольку нельзя (или сложно) изменить движения без перепроведения. То есть связываете себя конкретной реализацией партионного учета.
Я же смотрю на проблему в целом. Что есть регистр партий? — Всего лишь структура для определения того, из какого документа прихода взят конкретный расход (X(i,j,k)). Функция X(i,j,k) может быть реализована как угодно. И рассчитываться не обязательно последовательным проведением документов. В моем предложении — небольшими или большими (если изменение в массиве документов существенное) точечными корректировками dX(i,j,k).
Другими словами, НЕ переделать ДВИЖЕНИЯ ВСЕХ ПОСЛЕДУЮЩИХ документов, а пересчитать только измененные связи документов, возникшие из-за исходного изменения.
Я говорю только о первой задаче. Новое в том, что она сведена к известным оптимизационным задачам. В результате можем использовать готовые хорошо исследованные алгоритмы решения, которые, я, кстати, здесь не описывал, если не все это заметили!
Кроме того, предлагаемое решение не использует понятие «последовательность».
Также мне показалось ценным то, что в классе возможных алгоритмов решения определено место стандартного алгоритма 1С, а следовательно — его достоинства и недостатки относительно других методов. В итоге, я и предлагаю осознанно искать лучшие методы, зная, что мы можем выиграть и нужно ли это вообще!
кажется, для 7.7 это не применимо, т.к. движения можно делать только в модуле документа. а здесь получается придется изменять движения по регистрам обработкой…
поправьте меня, если я не прав, автор предлагает восстанавливать последовательность только по тем товарам, которые изменились при проведении задним числом каким-то хитрым способом с привлечением (потусторонних сил) транспортной логистики..
хотя с теорией я увы на ВЫ, поэтому так и хочется крикнуть «Пример в студию!» 😉
(12) Понимаю Ваши сомнения. Намеренно хотел уйти от технических подробностей реализации, чтобы взглянуть на корень проблемы.
Вижу, без примера не все понятно. Пример подготовлю. Нужно какое-то время.
(13) будем ждать
(12)
Вы не совсем правы. Хитрым способом я предлагаю не восстанавливать последовательность, а корректировать структуру списания X(i,j,k), которая ее заменяет. Привлекается не транспортная логистика, а математически схожая с распределением по партиям задача линейного программирования.
Уважаемый автор! Я поставил плюс за новый, свежий взгляд на известные вещи. Но должен Вас предупредить : те самые «готовые хорошо исследованные алгоритмы решения» неприятно удивят Вас своей сходимостью для случая большого количества переменных. Сам пробовал, удивлялся. Теоретически вроде все ОК, а практически до числа довести — фиг!
(16) Большое спасибо. Вы уловили суть дела. Но все же хочу попробовать. В данном случае критерием истины будут результаты практического исследования на задачах реальной размерности. Обнадеживает легко просматриваемое сходство с приемами ускоренного проведения по партиям.
(0)
В данной статье меня заинтересовал текст после слов: «…зачем?». Я согласен с каждым утверждением этой части статьи. И попробую дополнить этот текст некоторыми деталями своего понимания задачи.
1) «…1С …нацеливает решения не на отражение настоящего, а на рисование прошлого.»
— А изменение прошлого не должно влиять на текущий процесс торговли. Как в изменении основных итоговых показателей — реальные остатки на полках и взаиморасчеты с клиентами. Так и не должны нарушать вычислительный процесс регламентными работами в сетевой (многопользовательской) среде.
2) «Бухгалтер раскладывает на столе первичку и решает: в какой момент произвести списание? Когда товар был подороже или подешевле? Показывать или нет авансы?»
— Для этого можно не раскладывать документы на столе. А дать бухгалтеру программные средства раскладки документов в компьютерной базе данных в соответствии с его пожеланиями (правилами).
3) «Ну и пусть попробует один вариант, восстановит последовательность (пересчитает себестоимость), подождет.»
— Т.к. данные этого расчета (например, себестоимости) никак не влияют на «отражение настоящего», то не имеет смысла хранить эти расчеты в базе данных в момент «восстановления последовательности» прошлого периода. И, тем более не имеет смысла, нагружать систему лишней работой в момент отражения настоящего (проведение документов текущего периода). Т.е. «себестоимость» надо не пересчитывать, а считать всегда заново после перестановки документов (см. пункт #5).
4) «Вам хочется, чтобы это делалось максимально быстро? … Раз в месяц, раз в квартал — компьютер не перетрудится!»
— Для «настоящего» требуется доступность вычислительных средств всегда. И перерыв в работе торговли, даже один раз в месяц (квартал), не допустим. Это означает, что «восстановление последовательностей» прошлого периода (для бухгалтерских нужд) должен выполняться в многопользовательской среде и не мешать реальной торговле.
5) «… эта задача «рисования прошлого» … не требует высокой скорости расчетов.»
— Сам расчет существует всегда. А быстро он выполняется, если в процессе расчета не делается перепроведение документов. Т.е. документы расставлены в соответствии с пунктом #2, а окончательные цифирьки рассчитываются и выводятся отчетом. И не хранятся в базе данных!
(0) Как говорят англоязычные коллеги: if you are so clever, show me your money.
Переводя с «ихнего», и адаптируя к сути Вашей статьи: если Вы такой умный, нам код работающий покажите.
Сразу PS: Не сочтите реплику за неуважение. Будет практический результат Ваших идей — обсудим, а так — мутно всё это.
(19) Будет сделано.
Интересная идея по поводу того что можно проверять приход за весь период с сравнивать его с предполагаемым расходом. А если без дельта и т.д. напрямую?
Приход = ПолучитьПриходЗаВесьПериод();
РасчетныйРасход = ПолучитьРасходЗаВесьПериод + КолвоСписать;
Если Приход — РасчетныйРасход < 0 Тогда
Сообщить(«Списание в минус»);
Подумать только как бы общий расход приход хранить для быстрого расчета.
(12)(16)(19) В статьеhttp://infostart.ru/public/74343/ описывается практическая реализация данного метода, приводятся: тестовая конфигурация, программный код, оценки быстродействия.