Дебиторка fifo по долгам контрагентов (УТ 10.3).




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

38 Comments

  1. Поручик

    Давненько на эту тему ничего не писали. Боюсь, в понедельник набежит бомонд, и закидают автора веществами. Я даже знаю кто.

    Reply ↓
  2. mxm2

    Отчетец не без «тонких» ))) мест, но зато универсальный и работает. проверено. а так конечно правильнее применять подход с договорами по расчетным документам. Но не могу я народ заставить ))) в свое время «расслабила» их семерка. и еще в принципе отчет легко модифицировать, убрав детализацию по договорам (используя функцию Максимум или Минимум по Допустимым дням задолженности и Допустимой сумме задолженности)… Ну и вобщем готов к здоровой критике, ибо «чем больше я познаЮ, тем больше я не знАю» (с) Сократ

    Reply ↓
  3. anig99

    Собственно кидаться какулями не буду.

    Просто есть несколько моментов:

    — ссылка на описание методики нерабочая (возможно ещё неотмодерировали)

    — оптимизация запроса за счет ограничения выборки по времени по дате последнего перехода в минус — это лучше, чем тупое ограничение выборки по общей дате, но всё же далека от цели… В реальности постоянные контрагенты НИКОГДА не оплачивают долг полностью, а только просроченный. Таким образом, оптимизация работать не будет.

    — жаль, что привязка только к договорам.

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

    Reply ↓
  4. mxm2

    (3) anig99,

    — ссылка на описание методики нерабочая (возможно ещё неотмодерировали)

    в публикации методика не описана — мне её «на пальцах» объяснил наш экономист…

    В реальности постоянные контрагенты НИКОГДА не оплачивают долг полностью, а только просроченный. Таким образом, оптимизация работать не будет.

    конечно правилнее отделный регистр, но слишком затратно)..

    По поводу статей — на этом сайте?

    Reply ↓
  5. sevipa

    Отчет актуальный. Делали подобный но не с таким глубоким анализом. Изменения в конфу не вводили, а разрешили корректировку реквизитов Договора из формы отчета.

    Данный отчет особенно актуален потому что заставить сбытовиков работать по документам расчетов практически нереально по двум причинам, разносят деньги не они и даже не бухгалтерия а финслужба и там то все и виснет… ну а сбыт любит работать прошлым периодом (только не говорите про закрытие периода, всегда есть что-то или кто-то архиважный и архипипецвнеправилзапретов)

    Reply ↓
  6. IDija

    При попытке открыть, ругается на компоновку данных:

    {(20, 20)}: Таблица не найдена «РегистрСведений.АгентыПоДоговорам.СрезПоследних»

    ЛЕВОЕ СОЕДИНЕНИЕ <<?>>РегистрСведений.АгентыПоДоговорам.СрезПоследних(&ГраницаКонца, ) КАК АгентыПоДоговорамСрезПоследних

    Точно для ред. 10.3? Может с какого то определенного релиза?

    Reply ↓
  7. Поручик

    (6) Нет в УТ 10.3 никакого релиза такого регистра.

    Reply ↓
  8. mxm2

    (6) IDija,

    мой промах… у меня в конфе это применяется, а сюда я выложил с вырезом этого регистра… но видимо «недовырезал» сейчас исправлю. Кстати в статье текст запроса — верный, можно просто перенести, ну и внастройках отчета убрать упоминание «агента»

    Reply ↓
  9. mxm2
    IDija пишет:

    При попытке открыть, ругается на компоновку данных:

    {(20, 20)}: Таблица не найдена «РегистрСведений.АгентыПоДоговорам.СрезПоследних»

    ЛЕВОЕ СОЕДИНЕНИЕ <<?>>РегистрСведений.АгентыПоДоговорам.СрезПоследних(&ГраницаКонца, ) КАК АгентыПоДоговорамСрезПоследних

    Точно для ред. 10.3? Может с какого то определенного релиза?

    Перезалил файл.

    Reply ↓
  10. mxm2
    anig99 пишет:

    Собственно кидаться какулями не буду.

    Просто есть несколько моментов:

    — ссылка на описание методики нерабочая (возможно ещё неотмодерировали)

    — оптимизация запроса за счет ограничения выборки по времени по дате последнего перехода в минус — это лучше, чем тупое ограничение выборки по общей дате, но всё же далека от цели… В реальности постоянные контрагенты НИКОГДА не оплачивают долг полностью, а только просроченный. Таким образом, оптимизация работать не будет.

    — жаль, что привязка только к договорам.

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

    Посмотрел Ваши публикации по поводу оптимизации, «буду курить»,

    У меня клиенты достаточно часто оплачивают долг до нуля, иногда даже авансируют… + договора действуют максимум 1 год.

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

    Reply ↓
  11. IDija

    >> Кстати в статье текст запроса — верный, можно просто перенести, ну и внастройках отчета убрать упоминание «агента».

    Вставлял текст запроса, после двух ошибок исправлять далее не захотелось… разочаровывает статья…

    Reply ↓
  12. IDija

    (7) тогда не понятен ваш плюс…

    Reply ↓
  13. mxm2

    (11) IDija, файл уже правильный, его достаточно скачать.

    «после двух ошибок исправлять далее не захотелось» — кроме отборов там нет упоминаний об агенте.)

    кстати предыдущий файл, тоже правильный только при наличии доп регистра… возможно поздне опишу для чего он нужен…

    Reply ↓
  14. urbanist

    Пару лет назад ваял на эту тему:

    http://infostart.ru/public/22091/

    Сейчас вспомнил и добавил с с просрочкой по интервалам:

    http://infostart.ru/public/100137/

    Reply ↓
  15. mxm2

    (14) urbanist, всетаки инфо о доп днях и сумме правильнее брать из договора. а вот решение показывать — по интервалам — красиво. я в свое время исходил из того что отчет должен нормально печататься на а4 и раздаваться менеджерам-селянам (т.е. быть прозрачным и понятным)

    Reply ↓
  16. urbanist

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

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

    Reply ↓
  17. mxm2

    (16) urbanist, про правку — это да…, но по опыту торговлю чаще всего приходится «затачивать»… вот бухию — обычно оставляю в первозданном виде.

    Reply ↓
  18. orehova123

    ммм, спасибо! интересно и достаточно подробно, добавлю в закладки

    Reply ↓
  19. mxm2

    Для УТ11 аналогичный отчет: http://infostart.ru/public/128507/ (основная группировка по АналитикеУчетаПоПартнерам)

    Reply ↓
  20. Stas-ch

    Спасибо за отчет.

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

    Правда не понял, что есть поля

    НО и КО — если не сложно, опишите.

    Reply ↓
  21. mxm2

    (20) Stas-ch, НО = Начальный остаток, КО = Конечный остаток, по логике отчета вроде это видно. Если модифицировали — смело выкладывайте, возможно кому-то нужен именно Ваш отчет.

    Reply ↓
  22. kotuke

    Данный отчет актуален потому что заставить сбытовиков работать по документам расчетов практически нереально по двум причинам, разносят деньги не они и даже не бухгалтерия а финслужба и там то все и виснет…

    Reply ↓
  23. mxm2

    (16) urbanist, в принципе и без правки можно обойтись… нужно только сделать некую внешнюю обработку в которой будут доступны для записи нужные реквизиты договора… но с правкой — проще.

    Reply ↓
  24. LexSeIch

    Мир этому дому!

    Статья интересная, возможно скоро воспользуюсь обработкой, но пока взял на заметку. Хочу разобраться с запросами.

    Reply ↓
  25. serge_focus

    Обсуждение похоже затихло…

    Однозначно плюс за расписанную процедуру.

    Но хочу заметить строить отчет погашая по фифо — очень нерационально. Берем ТЕКУЩИЙ ДОЛГ (+ или — ) и разворотом от сейчас назад по документам-регистратором задолженности. Набераем требуемую сумму — будет в 10 раз быстрее… Тем более если есть задача сохранить «девственность» кода 1С и не использовать для накопления регистры, то зачастую на средней фирме уже через год внешний пересчет всех долгов по ФИФО занимает прилично времени, и блокирует работу…

    А пересчет разворотом от сейчас успешно используется со времен 7.7 (здесь примеров полно).

    И второе. Количество дней просрочки часто используют для СТОПа отгрузок.

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

    Да и при сохранении «девственности» кода 1С лучше использовать свойства объекта(справочник «Контрагенты»).

    Reply ↓
  26. mxm2

    (25) serge_focus,

    Согласен с Вами. А есть соображения как можно сделать эффективнее с использованием регистров?

    Общая идея: записи в регистрах (самопальных) фомируются фоновым заданием (скажем ночью), со сдвигом соответствующей последовательности. А в процессе работы производится «склейка» результатов по регистру и остатка по fifo, непосредственно из документов.

    Reply ↓
  27. ildarovich

    Предлагаю другое, гораздо более быстрое решение той же задачи: http://infostart.ru/public/262300/. Не требующее, к тому же, изменений в конфигурации.

    Reply ↓
  28. Pawlick

    Все это здорово, но вот незадача:

    этот отчет и http://infostart.ru/public/262300/ от ildarovichа разные результаты показывают…

    или это только у меня одного?

    И кстати результаты отчета от ildarovichа более похожи на правду…

    Reply ↓
  29. mxm2

    (28) Pawlick, у Вас нет документов введенных одной датой и одним времением по одному контрагенту? Всмотритесь в алгоритм: оптимизированный отчет имеет некоторые особенности.

    Reply ↓
  30. 20tanush

    Ошибок в запрос как минимум 2:

    1. И (ВЫБОР

    КОГДА ДоговорРеализации.ДатаОплаты = ДАТАВРЕМЯ(1, 1, 1, 0, 0, 0)

    ТОГДА ВЫБОР

    КОГДА ДоговорРеализации.ДатаДокумента = ДоговорРеализацияКО.ДатаДокумента

    ТОГДА ДоговорРеализации.Регистратор ИНАЧЕ ДоговорРеализации.ДатаДокумента КОНЕЦ

    ИНАЧЕ ВЫБОР

    КОГДА ДоговорРеализации.ДатаОплаты = ДоговорРеализацияКО.ДатаОплаты

    ТОГДА ДоговорРеализации.Регистратор ИНАЧЕ ДоговорРеализации.ДатаОплаты КОНЕЦ

    КОНЕЦ)

    2. ГДЕ

    ВзаиморасчетыСКонтрагентамиОстаткиИОбороты.СуммаУпрНачальныйОстаток И ВзаиморасчетыСКонтрагентамиОстаткиИОбороты.СуммаУпрКонечныйОстаток > 0

    Reply ↓
  31. mxm2

    (31) 20tanush, Как-то не очевидно, что в приведенных фрагментах есть ошибки. Логику запроса — вижу, а вот ошибок — нет. Ткните, как говорится, носом.

    Reply ↓
  32. 20tanush

    Да, на вид все вроде очевидно. Но конструктор запроса спотыкается на этих местах.

    В 1. конструкция И (Выбор…) Неверные параметры «И»

    И (<<?>> Выбор…) 

    Во втором: получаю вот такую ошибку: «Операция не разрешена в предложении ГДЕ

    <<?>>ВзаиморасчетыСКонтрагентамиОстаткиИОбороты.СуммаУпрНачальныйОстаток И ВзаиморасчетыСКонтрагентамиОстаткиИОбороты.СуммаУпрКонечныйОстаток > 0″
    Reply ↓
  33. 20tanush

    Уважаемый автор! Я прошу прощения, что все время вроде как нахожу ошибки. Но вот в третьем запросе, кроме реализаций попадают еще и платежки исходящие. Думаю, тут надо еще условие поставить, потому что платежки вроде не нужны. Поправьте меня, если я ошибаюсь.

    Reply ↓
  34. mxm2

    (33) 20tanush, во втором случае следует читать ВзаиморасчетыСКонтрагентамиОстаткиИОбороты.СуммаУпрНачальныйОстаток <=0 И ВзаиморасчетыСКонтрагентамиОстаткиИОбороты.СуммаУпрКонечныйОстаток > 0,

    Видимо «<=» — «съел» редактор, в самом тексте обработки все в порядке. В основном тексте — это уже исправлено. Спасибо.

    Reply ↓
  35. nucha

    Актуальный и доходчивый алгоритм. Хотя http://infostart.ru/public/262300/ быстрее в 3 раза.

    Reply ↓
  36. Vit_Kherson

    Вопрос к автору или тем кто скачал. (Конфигурация УТ 10.3)

    1.Тут как-то возвраты учитываются?

    2.Если да, то если в документе ВозвратОтПокупателя в табличной части указан документ РеализацияТоваровиУслуг по которому был Возврат, то будет ли это учитываться как уменьшение долга по указанной Реализации? Или все возвраты учитываются как погашение самого старого долга?

    Reply ↓
  37. mxm2

    (37) Возвраты учитываются как уменьшение суммы долга контрагента по конкретному договору (не по реализации, которая указана в ТЧ возврата)

    Reply ↓
  38. 028

    здесь учитывается ввод начальных остатков: Расчеты с покупателями и заказчиками (счета 1210, 3510)?

    Reply ↓

Leave a Comment

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