<?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='\
Ужо целая книга заданий вышла. Но лучше всего, когда люди САМИ будут разбираться. Хватит уже некудышных спецов штамповать, которые ничего сами не умеют, но сертификаты коллекционируют как марки.
Посмотрел первую часть, очень понравилось. Мастер-классы эти будут очень полезны всем. А тем, кому за свой счет курсы дороги, вообще необходимы. Все очень доходчиво с акцентом на основных моментах. Спасибо большое.
А сертификаты многим вообще не нужны..
дайте ссылочку на первую часть пожалуйста!!!
т.е на решение первого билета!!!
добавил третью часть
хорошие мастер-классы. смотрю сейчас решение опер. задач — очень наглядно. правда не совсем понятен один момент. смотрим текст запроса, используемый в обработке проведения Приходной для формирования движений по регистру остаткиНоменклатуры. все гут. затем автор говорит, что данный же запрос можно использовать для регистра ЦеныПоставщиков, что вызывает сомнения, т.к. поле «Поставщик» мы сможем вытащить из шапки док-та Приходная, а вот поле «Цена» никак нет, ведь табл. часть группируется и что в этом случае делать — суммировать цену или выбирать максимальную?
Все зависит от задачи. По хорошему, так как записи в регистре «ЦеныПоставщиков» подчинены регистратору, то физически документ «Приходная» не проведется с дублями строк. => надо запретить создавать дубли и как следствие не придутся ничего группировать при формировании запроса.
еще сдается мне, что в запросе для дока «Расходная» в обработке проведения для целей ФИФО упорядочить нужно не по Остатки.Партия.Дата, а по Остатки.Партия.МоментВремени. правда не настаиваю 😉
а не лучше ли в обработке проведения одним циклом обойти все
Выборка = Запрос.выполнить ().выбрать();
Пока Выборка.следующий () Цикл
Если Выборка.Количество > Выборка.КоличествоОстаток ТОгда
Сообщить («На складе » + Склад + » недостаточно номенклатуры » + Выборка.Номенклатура + » для списания!»);
Отказ = True;
Продолжить;
endif;
Движение = Движения.ОстаткиНоменклатуры.Добавить();
Движение.ВидДвижения = ВидДвиженияНакопления.Расход;
Движение.Номенклатура = Выборка.Номенклатура;
Движение.Регистратор = Ссылка;
Движение.Склад = Склад;
Движение.Количество = Выборка.Количество;
Движение.Сумма = Выборка.Количество / Выборка.КоличествоОстаток * Выборка.СуммаОстаток;
Движение.Период = Дата;
enddo;
если Отказ тогда
Возврат;
КонецЕсли;
«или я не прав где то?
(10) А у меня все в цикле обходится, только движения не формируются если возведен флаг Отказ.
(11) ну так и должно быть, если отказ — значит отменяется транзакция (которая неявно начинается при проведении ), следовательно, изменения не записываются.
(12) Так а зачем их формировать, если транзакция все равно отмениться? Может я не понимаю предмет нашего спора?
Я в цикле делаю полную проверку остатков, но прекращаю формировать движения если хотя бы одного товара не хватает. В (10) движения формируются ВСЕ кроме тех товаров по которым не хватает остатка, а потом они все и отменяются в транзакции, на мой взгляд это не оптимально, сначала формировать движения, а потом отменять их.
В видео лекции проведение реализовано двумя циклами (один — проверяет остатки, а второй формирует движения по регистрам ), а у меня — одним. Т.к. ситуация с недостатком товаров на складе всречаестя редко, особенно если реализовать программное заполнение, то считаю свои вариант оптимальней, по крайней мере хочу выяснить так ли это…
GROOVY, так это ваша лекция («(11)А у меня все в цикле обходится») ?
Ну тогда куча благодарностей! Обалденное изложение и преподнесение материала! Просто 10 баллов!
Павел есть 2 вопроса по лекции: 1) Почему запретили оперативное проведение «Расходной накладной»?
2) Если списать 0 шт. несуществующего товара — ошибка «Деление на ноль», надо ли добавить контроль такой ситуации?
Павел, когда идте расчет процента скидки, попробуйте сделать его когда объем продаж больше 10 000, судя по вашему запросу скидка будет НУЛЛ, мне кажеться там ошибка.
Предлягаю свой вариант запроса
ВЫБРАТЬ
ЕСТЬNULL ( МАКСИМУМ (ШкалаСкидокСрезПоследних.Процент), 0) КАК Процент
ИЗ
РегистрНакопления.Продажи.Обороты(&Дата1, &Дата2, , Контрагент = &Контрагент) КАК ПродажиОбороты
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ШкалаСкидок.СрезПоследних(&МоментВремени, ) КАК ШкалаСкидокСрезПоследних
ПО ПродажиОбороты.СуммаОборот > ШкалаСкидокСрезПоследних.ОбъемЗакупки
«
Кроме того, скидка определяется при открытии на дату (или момент) документа, Если теперь пользователь изменит дату на заднее число — то текущая скидка перестанет быть актуальной (в лекции пересчета нет), что тоже ошибочно.
(20) В регистре болжна быть верхнаяя граница указана 99999999999, тогда все тип топ работает.
(19) В лекциях нигде нет защиты от дурака, это не цель лекций.
Спасибо за коменты, учимся дальше… !
в расчетной задаче в регистре расчета ДополнительныеНачисления неправильно настроена зависимость по базе. Должна быть по периоду регистрации.
(22) C нетерпением жду объяснений. Почему?