Просроченная дебиторская задолженность по датам без ведения учета по документам расчетов для УТ 10.3




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

23 Comments

  1. makas

    симпатичный отчет!

    Reply
  2. ranger

    Держи 5

    Reply
  3. den_valley

    Основная проблема таких отчетов — низкая скорость работы на больших объемах данных (причем скорость падает экспоненциально с возрастом базы).

    Насколько я понимаю, причина в том, что все они основаны на выборке таблицы регистраторов из виртуальной таблицы оборотов регистра «Взаиморасчеты с контрагентами».А поскольку нижнюю границу начала выборки определить нельзя (выбирать приходится от Р.Х.), то на каждую сумму остатка приходится выбирать по 2-3 тысячи строк (если обороты с контрагентами интенсивные).

    В результате, например, подобные отчеты на базе УПП/УТ 3- летнего возраста формируются у меня уже минут по 15-20 (по 18-20 сек на контрагента).

    И что-то все попытки оптимизации пока никуда не ведут особо.

    Reply
  4. V1V

    (3) den_valley,

    не понял вас. 15 минут по 20 секунд на контрагента получаем 45 контрагентов. по 45 контрагентам медленно формируются запросы по документам… как-то не верится. У меня на данный момент в базе 387 контрагентов по которым есть хоть какая-то задолженность в том числе с 2010 года. Отчет формируется: до вывода в отчет 25 секунд, вывод в отчет еще 7 секунд. Менеджеры формируют отчет только по «своим» контрагентам (RLS) соответственно у них еще быстрее формируется.

    Reply
  5. den_valley

    (4) V1V,

    Ну не на всех контрагентах запрос так долго работает.

    18-20 секунд выдает на 6375 записях (тестовый контрагент есть у меня один)

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

    Сейчас 15-20.

    Количество активных договоров около 1500.

    И у меня отчет по ПКЗ (хотя принцип выборки, увы, тот же), потому формирует один человек по всей базе.

    И выхода то особо нет, или использовать регистр «Взаиморасчеты по документам»(или ему подобные) со своими проблемами, или считать ПДЗ/ПКЗ по ФИФО расчетным методом (с потерей производительности).

    Мониторю различные ресурсы в надежде найти «третий вариант», но возможно его просто не существует в природе.

    Reply
  6. V1V

    (5) den_valley,

    Третий вариант — это например регламентное задание, которое будет заполнять регистр, а отчет соответственно строится уже по готовому регистру. Задание запускается всякий раз при изменении в регистре взаиморасчетов. Такой вариант я рассматривал когда платформа стояла 8.1. При переходе на 8.2 проблема отпала.

    Reply
  7. den_valley

    Такой вариант реализован в УТ 11.

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

    Следовательно днем, в рабочее время, запуск его проблематичен….

    А ночью результат его работы никому не нужен 🙂

    P.S. И скорость работы регл. задания сопоставима со скоростью работы отчета, только отчет работу не блокирует.

    Reply
  8. V1V

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

    Reply
  9. sobeyko2008

    Не работает Фильтр контрагентов «Не в группе из списка»

    Reply
  10. ZLENKO

    (3) Вот тут оптимизации есть по скорости http://infostart.ru/public/117647/

    Выборка начинается не от Р.Х., а от последней «нулевой» задолженности.

    Reply
  11. ZLENKO

    (5) Еще вариант сделать регистр сведений (не накопления — будет медленно писаться в него) и распределение отгрузок и оплат хранить там. Я использую у одного клиента такой вариант, т.к. нужны сложные отчеты по задолженности (например, просроченная задолженность по дням в течение месяца). Недостаток: информация в регистре сведений обновляется периодически регламентным заданием.

    Reply
  12. smir

    Надо попробывать

    Reply
  13. V1V

    (9) sobeyko2008, не только этот. отбор строится программно. туда вставлены те отборы, которыми люди пользуются, остальные никому не нужны были. переменная ТекстВидСравнения в строке 91 модуля формы. там все формирование отбора, можете добавить при необходимости те что вам нужны

    Reply
  14. sobeyko2008

    Почему вы считаете что люди не пользуются этим отбором? Ну вот ни хочу я видеть задолженность по контрагентам: Сотрудники, рекламщики, откатчики и т.д. и как с этим быть?

    переменная ТекстВидСравнения в строке 91 модуля формы

    мне к сожалению ни о чем не говорит… я не программист…

    Reply
  15. V1V

    (14) sobeyko2008, те у кого работает этот отчет — не пользуются. про всех на свете людей я не говорил. отчет используют менеджеры по продажам, а они видят только «своих» контрагентов. Да и откуда у других будет дебиторка? типа мы сотруднику что-то продали, а он нам не заплатил?

    Reply
  16. sobeyko2008

    А если например так получилось что Покупатель и он же поставщик и рассчитался он со мной товаром. То отчет всеравно показывает что он нам должен.

    Reply
  17. V1V

    тогда вы сделаете корректировку долга и перенесете задолженность с одного договора на другой (смотрите методологию) и отчет все покажет правильно.

    Reply
  18. 31337

    спасибо!пригодился

    Reply
  19. ildarovich

    (5) den_valley, можете попробовать вариант, предложенный в публикации «Неоплаченные долги при распределении оплаты по правилу ФИФО одним запросом и намного быстрее, чем Вы думали». Там используется принципиально другой подход, позволяющий получить нужный результат гораздо быстрее. Речь идет не о минутах, а секундах. Конфигурацию менять не нужно.

    Reply
  20. Sedow

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

    контролировать число дней задолженности.

    автор заявляет что отчет будет указывать просрочку и без этого.

    я не прав?

    Reply
  21. V1V

    (21) Нет под рукой релиза торговли 10.3. На память уже тоже не помню последовательность галочек. Ничего не могу по этому поводу сказать. Сорри. Давно это было

    Reply
  22. 028

    Здесь будет работать?

    Управление торговым предприятием для Казахстана, редакция 2.0

    Reply
  23. galalik

    спасибо! очень интересная статья/разработка!

    Reply

Leave a Comment

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