Ведомость по взаиморасчетам (общая, текущая, просроченная задолженность по календарным и рабочим дням + документы регистраторы)




Принцип обмена данными из 1С с сайтом (на MySQL) и выдачи (публикации) этих данных по запросу.
PHP-Скрипт автоматической загрузки данных из файла данных в формате CSV в базу данных сайта работающего на WordPress.

В продолжение моей темы: 1С:Альфа-Авто Автосалон Автосервис: обмен с сайтом.
С помощью данного скрипта можно загружать в автоматическом режиме, по расписанию, данные сервисных книжек (ремонтов авто) из 1С:Альфа-Авто Автосалон Автосервис.
Также можно загружать данные в ручном режиме: для этого делается скрытая страница, где размещается специальная кнопка.
Комментарии размещенные внутри скрипта разъяснят логику и порядок действия.
Комментарии с "/////    echo" использовались для отладки.
Дополнительно создана таблица для журналирования результатов загрузки данных.
Скрипт включает в себя защиту от SQL инъекций (думаю безопасность соблюдена в полной мере).
В кратце:
1. Пишется скрипт, который запускает этот.
2. Создается регламентное задание в WordPress, по которому запускается скрипт из п.1. 
3. Этот скрипт осуществляет проверку на существование файла обмена в папке.
4. Если данные не новые, загрузка не производится.
5. Если данные новые, очищается таблица сервисных книжек.
6. Загружаются новые данные.

Собственно сам скрипт:

<?php // Полная загрузка сервисных книжек, создан 2026-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='\

37 Comments

  1. ZLENKO

    «При реализации возникла проблема»

    А в чем проблема то ? В конфигурацию добавить 1 строчку кода и сделать доступным количество дней отсрочки.

    Reply ↓
  2. macsol

    (1) А проблема в том, что у меня в базе 7 организаций, из них 3 — в разных городах России, а я один со всем этим хозяйством. 1-сники штампуют обновления каждый месяц. Если я буду по любому случаю в конфу «строчки добавлять», то просто не справлюсь один с очередным обновлением. Я придерживаюсь такого мнения, что менять конфу нужно только в случае крайней необходимости. Если можно обойти, нужно обходить.

    Reply ↓
  3. ZLENKO

    А можно увидеть в отчете по каким документам просрочено и на сколько дней просрочено ?

    Reply ↓
  4. wirg

    Я уже таких кучу на сайте видел и зачем такой отчет, если он расшифровку по документам не показывает? Советую поучится или посмотреть подобное на сайте, чем выкладывать такое.

    Reply ↓
  5. molot

    «При реализации возникла проблема»

    Кстати, а чем «Максимальное число дней отсрочки» в договоре не устраивает? В 23-м релизе — доступно и для договоров с поставщиком. А до этого можно было и внешней обработкой заполнять…

    Reply ↓
  6. macsol

    (5) Не успеваю угнаться за новыми релизами, 6 дней назад обновлялся только.

    «Максимальное число дней отсрочки» в типовой конфигурации доступно только при ведении взаиморасчетов по документам расчетов. У нас не все договора ведутся по документам расчетов. Внешней обработкой заполнить можно, только в типовой форме значений не будет видно, придется выводить в этой обработке. А самый главный минус — человеческий фактор. Придется обучать менеджеров пользоваться обработкой и отчетом.

    Reply ↓
  7. macsol

    (3)В этом отчете нельзя. Я писал что у нас договора смешаны. Запрос строился по регистру «Взаиморасчеты с контрагентами». Если у вас все договора ведутся по документам расчетов то можно переделать запрос по регистру «Взаиморасчеты с контрагентами по документам расчетов» и дернуть нужные данные. У меня такой задачи не стояло.

    Reply ↓
  8. ZLENKO

    (7) У нас документы расчетов вообще не используются, поэтому я написал отчет, который выдает данные в независимости от использования документов расчетов. По личному опыту если выдается сумма без расшифровки — возникает много вопросов типа «Почему тут такая сумма ?!».

    Reply ↓
  9. macsol

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

    Reply ↓
  10. anig99

    Вот-вот. Точно как (8) Возьми мою обработку, глянь. А число дней отсрочки там вычисляется отдельно, можно исправить на твой вариант со свойствами. И расшифровки там есть. Скоро обновлю отчет — пару функций добавлю. Оценки не ставлю ибо особо плохого в этой обработке не вижу, но и новизны никакой.

    Reply ↓
  11. ZLENKO

    (9) «ищут на них ответы в типовых отчетах»

    Ну вот, например, на вопрос «А за какие такие отгрузки у клиента просрочена оплата на вот эту сумму что показывает отчет ?» в каких типовых отчетах и как они ищут ответ ? Вручную отбирают последние отгрузки что ли ?

    Reply ↓
  12. ZLENKO

    (10) «Оценки не ставлю ибо особо плохого в этой обработке не вижу, но и новизны никакой.»

    Аналогично.

    Reply ↓
  13. macsol

    Да пофиг оценки, интересно послушать мнения. Если кто знает, пролейте свет.

    Какое выражение в запросе выполниться быстрее :

    a >= b

    Не a<b

    Reply ↓
  14. macsol

    (11) данный отчет был написан в рамках поставленной задачи, попросили бы показать документы, были бы документы. Я выложил отчет на этом сайте, для того чтоб народ его посмотрел, написал отзывы по поводу запроса, возможно что — то взял для себя. Мне он показался интересным, именно способом получения дней отсрочки, все остальное в нем ерунда. И вообще для меня этот сайт не место откуда можно скатать готовые решения, а возможность познакомиться с новыми идеями.

    Reply ↓
  15. ZLENKO

    (14) С другой стороны, если каждый начнет выкладывать сюда все свои запросы или процедуры — раздел «Программы» превратится в помойку. Для обсуждения приемов программирования есть раздел «Форум» и тематические форумы на других сайтах.

    Reply ↓
  16. molot

    (13) второе.

    Только вряд ли ты этим че-то оптимизируешь 🙂

    Reply ↓
  17. anig99

    Код закрыт — это минус. Производительность по сравнению с моей обработкой вроде бы хуже. Пока тестировал на 1 клиенте — где-то раз в 10 эта обработка медленнее. Сейчас буду пробывать на группе клиентов. Но для манагеров часто важен 1 клиент.

    Reply ↓
  18. anig99

    Так, кажется, просто при заполнении данных не делается предварительный отбор по контрагентам. Сделай примерно как я. Сначала через СКД формируется список контрагентов, потом его в таблицу и запихивается как условие в твою обработку. Существенно должно сократить срок выполнения на одиночных клиентах.

    Reply ↓
  19. anig99

    Да… на множестве клиентов получилось быстрее. Но вот достоверность данных надо тоже проверить.

    Reply ↓
  20. anig99

    А что за 2 скриншот? На интервалы не похоже.

    Reply ↓
  21. macsol

    (20) вывод таблицей по строки — контрагенты

    колонки — отсрочка платежа.

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

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

    Reply ↓
  22. macsol

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

    Reply ↓
  23. ZLENKO

    (19) Проверил отчет на демо базе конфигурации «Управление торговлей».

    Отчет работает неправильно:

    — общая сумма задолженности всех контрагентов не соответствует отчету «Ведомость по взаиморасчетам с контрагентами», а должна быть одинаковая;

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

    Reply ↓
  24. Nefertary

    «Создается свойство договора «Отсрочка платежа», в нем по порядку добавляются знаечения свойств 1,2,3, 4, 5, 6… Числа должны идти по порядку, и заканчиваться числом равным количеству дней максимальной отсрочки.»

    Можно создать свойство договора «Отсрочка платежа» и задать ему тип «Число».

    Reply ↓
  25. macsol

    (23) спасибо за тестирование, замечание справедливо. Я перемудрил с запросом (некоторые данные задваивались). Во второй версии исправил.

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

    Reply ↓
  26. macsol

    (24) Решая некоторые задачи, иногда кажется что простых решений нет, по-этому и спрятаны эти решения прямо перед носом тех кто их не замечает.

    В общем — огромное спасибо и респект. Во второй версии отчета использовал числовой тип.

    Reply ↓
  27. Nefertary

    Дефолтовое название характеристики лучше другое поставить

    Reply ↓
  28. macsol

    (27) аФтор начальник отдела продаж.

    Reply ↓
  29. anig99

    чего-то последняя версия какая-то не такая стала. Во первых — странное поведение с датами отчета.

    » Если документы сформировавшие остаток на дату отчета не входят в этот интервал, отчет присваивает им дату ДАТА = (Дата начала интервала — 1 день) отнесение задолженности

    на текущую и просроченную будет расчитываться исходя из этой даты.» — честно абракадабра какая-то. Т.е. получается, что если долг не вошел в этот период, то я его не увижу? Фигня какая-то… должен сидеть и подбирать период… Имхо изначально отчет лучше был.

    Reply ↓
  30. macsol

    (29) Извиняюсь за костоязычность. Попробую объяснить заново. Отчет выводит задолженность на конец последней даты интервала. Общую задолженность отчет покажет в любом случае. В интервал могут не попасть даты документов — образовавших эту задолженность. Отчет может не показать документ регистратор, и если он его не находит, то присваивает ему дату КонецПериода — 1.

    Это сделано для ускорения, кому нужна вся инфа, уменьшат начальную дату интервала.

    Reply ↓
  31. anig99

    Просто получается, что если я не угадаю с периодом, то просроченный долг увижу неверно. Это очень плохо.

    Reply ↓
  32. anig99

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

    Reply ↓
  33. macsol

    (32)Уже посмотрел, впечатление хорошее. Есть недочеты, я тебе о них написал.

    Reply ↓
  34. orsprog

    Да ладно!!! вполне сносный отчет…

    Reply ↓
  35. AndrewAks

    Скачал v4, сконвертировал под 8.2, при запуске получил сообщение «Демонстрационный срок использования отчета вышел.». Отчёт платный? И если да, то почему об этом нигде не сказано?

    Reply ↓
  36. trum86

    (33) при запуске пишет «Демонстрационный срок использования отчета вышел.», какой еще демонстрационный срок? Только скачал..

    Reply ↓
  37. Dracarys

    То же самое: «Скачал v4, сконвертировал под 8.2, при запуске получил сообщение «Демонстрационный срок использования отчета вышел.»»

    {ВнешнийОтчет.ВедомостьПоВзаиморасчетамТекущимПросроченным.МодульОбъекта(737)}: Ошибка при вызове метода контекста (Вывести)

    по причине:

    Ошибка вывода результата

    по причине:

    Ошибка при выводе результата

    по причине:

    Ошибка получения данных

    по причине:

    Ошибка создания набора данных «НаборДанных1»

    по причине:

    Ошибка при исполнении запроса набора данных

    по причине:

    {(94, 21)}: Ошибка обработки представления «РегистрНакопления.ВзаиморасчетыСКонтрагентамиПоДокументамРасчетов.ОстаткиИОбороты:Неправильно задан период: начало периода должно быть меньше или равно окончанию»

    ЛЕВОЕ СОЕДИНЕНИЕ <<?>>РегистрНакопления.ВзаиморасчетыСКонтрагентамиПоДокументамРасчетов.ОстаткиИОбороты(&ДатаНачала, &ДатаОкончания, Регистратор, , ДоговорКонтрагента.ВестиПоДокументамРасчетовСКонтрагентом) КАК Обороты

    Reply ↓

Leave a Comment

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