ОСВ по нескольким базам




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

38 Comments

  1. Хряк

    Инициализацию вставил бы в попытку

    ОЛЕ = СоздатьОбъект(«V77S.Application»);

    Не все пользуют v77s, у многих просто v77

    Reply
  2. afanasko

    (1) Черт ). И точно. Ща подправлю.

    Reply
  3. Шёпот теней

    …консилидированная отчЁтность… хм… крУто…!!!

    … вОтвЕдЬоднАко …

    Reply
  4. Доня

    Чуйствую, что хорошо!

    но требуем компоненту 1С++

    где взять?

    Reply
  5. afanasko

    (4) 1С++ можно взять на официальном сайте проекта http://www.1cpp.ru/images/3/32/Icpp-latest.rar

    Reply
  6. RayCon

    Видимо, четвёртым пунктом в том, «что не реализовано», будет элиминирование расчетов intercompany.

    >Буду благодарен за любые отзывы, плюсы, а так же за найденные глюки и баги.

    Основной глюк при формировании ОСВ — это сломанная валюта баланса, и как следствие, невозможность построения по ОСВ форм №1 и №2 при более-менее сложном учете. Я так понимаю, что исправлением ошибок стандартной поставки ты не занимался. И все они перекочевали в «консолидированную» ОСВ. Не так ли?

    P.S. А цифры почему одинаковые? Две одинаковые базы с разными названиями?

    Reply
  7. afanasko

    (6)

    >Видимо, четвёртым пунктом в том, «что не реализовано», будет >элиминирование расчетов intercompany.

    исключение расчетов, происходящих внутри компании — нетривиальная задача. Для этого нужно очень хорошо знать процессы компании. Если для своих бухов, я еще могу такое сделать, то на универсальный механизм я пока еще не готов 🙂

    Не совсем понял про «сломанную валюту» учета. Но, да, я не занимался исправлением ошибок стандартной поставки.

    Цифры одинаковые потому, что это две демонстрационные конфигурации стандартной бухгалтерии. Неужели вы думаете, что я буду показывать примеры на реальных цифрах? 🙂

    Reply
  8. RayCon

    >Не совсем понял про «сломанную валюту» учета

    Я не говорил о «валюте учета» — я говорил о «валюте баланса». Валютой баланса называется корректно полученный ажур. К сожалению, план счетов стандартной поставки 1С таков, что оба ажура — и в ОСВ, и в форме №1 — можно получить некорректно, причём оба варианта могут не иметь экономического смысла. Но не думаю, что это имеет смысл обсуждать здесь. Если интересно, в личке могу пояснить или дать ссылки на посты в конференции 1С по теме, как нужно формировать план счетов и корректно собирать по нему финотчетность.

    >Неужели вы думаете, что я буду показывать примеры на реальных цифрах? 🙂

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

    Reply
  9. Свой

    а зачем нужна 1С++ ?

    Reply
  10. afanasko

    (9) Ну на самом деле пока там используется только класс «Индексированная таблица». Можно было бы и без 1С++ сделать, но в ряде случаев удобнее работать с индексированной таблицей, чем с обычной таблицей значений.

    В дальнейшем с помощью 1С++ планируется реализовать не OLE-соединения, а работу через интерфейсы OLEDB и ODBC

    Reply
  11. andreykaq

    нехватало regsvr32 C:WINDOWSsystem32msscript.ocx

    а так вроде работает, спасибо.

    Reply
  12. v_id

    Очень пригодилось. Спасибо!

    2. Расшифровка в виде «Карточки счета». Опять же все зависит от количества желающих.

    3. Работа с базами не через OLE, а через прямые запросы с помощью 1C++. Возможно будет реализовано.

    Есть желающие

    Reply
  13. Шёпот теней

    .. КРУТО …

    … и ЭТО всЁ БЕСплатно …

    … ЭТО ФАНТАСТИКА …

    … вотТАКбывает …

    Reply
  14. afanasko

    (13) Я извиняюсь, но это шутка такая? 🙂

    Вроде ничего сложного…

    Reply
  15. Шёпот теней

    (14) … нууууНЕзнаююю…

    … ещЁ чуть-чуть + ещЁ немного и будет консилидированный отчёт, баланс …

    … какТОтакНАВЕРНОЕ …

    Reply
  16. afanasko

    (15) Понятно, спасибо ).

    Консолидированный скорее всего не получится. Как упоминал тов. RayCon, есть некоторые проблемы при сведении данных. Проблемы могут возникнуть если подразделения продают что-то друг-другу, например.

    Это что касается торговых компаний. Допустим в какой-нибудь страховой компании такая проблема маловероятна ))).

    Reply
  17. Шёпот теней

    … ага…ага…встречные движения…но это уже дело техники…

    можно подсчитать ВСЕ объёмы затем по отдельности исключив «свои» организация и где -то уже засветит консолидация … ну или морочиться внутри общейОСВ … думаю небольшой ошибкой можно и принебречь …

    … не так стрАшно нАказание как его ожидАние …

    … вот …

    Reply
  18. afanasko

    (12) Ок. Я поработаю над этим 🙂

    Reply
  19. alexmal

    Ставлю + потому как работает!

    Подправил для украинских конфигураций.

    См. http://infostart.ru/public/59979/

    Reply
  20. JohnyDeath

    Через прямые запросы трудновато будет, ибо подсистема бухучета в 7.7 — замудреная. Но есть классы от тов. berezdetsky ( http://www.1cpp.ru/forum/YaBB.pl ) .

    С нуля писать такое не советую.

    Reply
  21. afanasko

    (20) Я уже понял в какую ж… забрел )))).

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

    Во-вторых класс berezdetsky заточен под СКУЛЬ. Необходима поддержка DBF-ных баз. Тут мне кажется, предпочтительнее использовать класс «ПрямойЗапрос» от vandalsvq.

    Но у меня возникла совсем другая проблема с DBF-ными базами. Таблицы итогов содержат неверные данные, хотя стандартные средства 1С отрабатывают правильно. К примеру, приведу остатки по 41 счету:

    на 1.06.2009 в остатках есть товар на сумму 10 000 р.

    14.06.2009 весь товар списался (по табл. оборотов).

    на 1.07.2009 в остатках лежит сумма в 10 000 р. — тут должно быть 0.

    Когда формирую запрос с помощью «БухгалтерскиеИтоги», допустим на 2.07.2009, остаток получается верным: 0.

    Ну а по прямому запросу остаток выдается неверным, т.к. берутся данные из остатков + обороты.

    С чем это связано, я так и не понял. В СКУЛЬной версии таких проблем нет.

    Reply
  22. JohnyDeath

    (21) Класс vandalsvq использует компоненту 1sqlite, поэтому выдрать данные из внешней дбф-базы этим классом не получится. У berezdetsky — да, только под скуль. Вот такая вот загагулина…

    Или ты решился переписать всё под ОЛЕ ДБ? ))

    А конкретные вопросы по поводу данных, хранящихся в этих табличках, думаю, стоит задать тем, кто конкретно с этим сталкивался. Я знаю только двух людей — berezdetsky и vandalsvq 😉

    Reply
  23. afanasko

    (22)

    Или ты решился переписать всё под ОЛЕ ДБ? ))

    Ну сначала так и хотел 😀

    Делал класс «БыстрыеБухИтоги». Хотел подменять стандартные вызовы (ВыполнитьЗапрос, ПолучитьСубконто и т.д.) собственной реализацией. Было задумано так, что если запрос к SQL базе, то через ODBCRecordset, если к ДБФ то в зависимости от монопольности либо стандартные методы, либо через OLE DB.

    Reply
  24. JohnyDeath

    (23) ну тогда удачи! С великим удовольствием посмотрел бы. (я так и не осилил 😳 )

    Reply
  25. v_id

    Добавлю свои 5 копеек. У меня список баз фиксирован, да и если использовать ИТЗ, то наверное проще так:

    //******************************************************************************
    // Предопределенная процедура
    //
    Процедура ПриОткрытии(ФлагВостановленияНастройки)
    
    Если ЗагрузитьВнешнююКомпоненту(«1CPP.DLL») = 0 Тогда
    Предупреждение(«Для работы обработки необходима компонента 1С++!»);
    Возврат;
    КонецЕсли;
    
    Если ФлагВостановленияНастройки = 0 Тогда
    НачДата = НачКвартала(ТекущаяДата());
    КонДата = КонКвартала(ТекущаяДата());
    КонецЕсли;
    
    ТаблицаБаз.НоваяКолонка(«ИмяБазы», «Строка»,,, «Название БД», 20);
    ТаблицаБаз.НоваяКолонка(«Путь»   , «Строка»,,, «Путь», «20»);
    ТаблицаБаз.НоваяКолонка(«Пользователь», «Строка»,,,, 10);
    ТаблицаБаз.НоваяКолонка(«Пароль», «Строка»,,,, 10);
    ТаблицаБаз.НоваяКолонка(«ТипБазы», «Строка»,,, «Тип базы», 5);
    
    ЗаполнитьСписокБаз();
    
    ВидимостьРеквизитов();
    
    ИмяФайла = КаталогИБ() + «SpisokBazOSV»;
    Если ФС.СуществуетФайл(ИмяФайла) = 1 Тогда
    ИТЗ = СоздатьОбъект(«ИндексированнаяТаблица»);
    ИТЗ.ИзФайла(ИмяФайла);
    ИТЗ.Выгрузить(ТаблицаБаз);
    КонецЕсли;
    
    КонецПроцедуры
    
    //******************************************************************************
    // Предопределенная процедура
    //
    Процедура ПриЗакрытии()
    
    ИмяФайла = КаталогИБ() + «SpisokBazOSV»;
    ИТЗ = СоздатьОбъект(«ИндексированнаяТаблица»);
    ИТЗ.Загрузить(ТаблицаБаз);
    ИТЗ.ВФайл(ИмяФайла);
    
    КонецПроцедуры // ПриЗакрытии()
    

    Показать

    Reply
  26. afanasko

    (25). Я уже это сделал 🙂 Только немного по другому. Как доделаю валюты, выложу обновленную версию.

    Reply
  27. v_id

    (26)

    😀

    Будем ждать!

    Reply
  28. maxchaos

    Однозначно «плюс»!

    Не помешает перед обращением к константам использовать проверку на их периодичность, иначе отчет вылетает с ошибкой «Типы не совпадают».

    Reply
  29. afanasko

    (28). Название организации?

    ОК.

    Reply
  30. maxchaos

    (29) Да, там пока другой константы нет 🙂

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

    Reply
  31. v_id

    Ради любопытства спрошу. Чем вызван отказ от 1с++? Идея из (23) свое отжила?

    Reply
  32. afanasko

    (31).

    Решил отказаться от 1С++ ради максимальной простоты использования. Чтобы человек скачал и запустил без дополнительных усилий.

    С прямыми запросами к DBF-ным базам возникли проблемы, описанные в (21). Подумал, что не стоит рисковать правильностью данных ради быстродействия.

    Reply
  33. wumka

    «Не знаю, может кому-нибудь пригодится. Делал для наших бухгалтеров. Очень удобно, когда в компании неколько юридических лиц или развитая филиальная сеть.»

    использовала данную разработку для сравнения нескольких баз одного и того же юр.лица, удобно: выдаётся одна ОСВ и видно по каким счетам разница. Удобно при восстановлении учёта.

    Спасибо.

    Reply
  34. afanasko

    wumka, Спасибо за оригинальную идею использования!

    Reply
  35. Arin

    У меня почему-то не работает. Выходит ошибка «Подключение = ОЛЕ.Initialize(ОЛЕ.RMTrade,»/d»»»+ТаблицаБаз.Путь+»»» /N»+ПользовательБазы+» /P»+ПарольБазы,»NO_SPLASH_SHOW»);

    {C:DOCUMENTS AND SETTINGSUSERРАБОЧИЙ СТОЛSVODNAJAOBOROTKA.ERT(130)}: Неизвестная ошибка»

    Reply
  36. kostya23

    Интересная обработка, попробовали с ней поработать — понравилось. Спасибо автору.

    Reply
  37. 987ww765

    А для 8.2 такой ни у кого нет???? очень нужно

    Reply
  38. v_id

    (32) спасибо вам за этот отчет.

    Сейчас дорабатываю его под себя, добавляю разворот по первому субконто у счета с возможностью выбора реквизита для группировки. Появилась желание попробовать реализовать это через прямыезапросы, в связи с этим очень бы хотелось посмотреть на вашу «кухню» в первых попытках реализовать текущий отчет, ну чтобы испугаться и больше не думать об этом 🙂

    Reply

Leave a Comment

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