Методика распределения затрат в разрезе дополнительных аналитик




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

16 Comments

  1. Арчибальд

    Данное направление еще ждет своих разработчиков. Есть кое-что готовое, например, http://www.ec-network.ru/index.php?option=com_frontpage&Itemid=1

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

    Reply
  2. Арчибальд

    Реализация похожей модели в Бух 7.7 потребовала только добавления трех документов: «НезавершенкаВспомогательного», «ОтчетЦеха» и «Себестоимость». Последний как раз и служит для хранения результатов решения системы линейных уравнений (решает систему в процессе проведения). Сопровождаемость/обновляемость, как правильно указывается в статье, при этом сохраняется (см. http://infostart.ru/blogs/1040/ )

    Reply
  3. Ish_2

    (2)» решает систему в процессе проведения»

    Извиняюсь , каким методом ? Проверяется вырожденность матрицы (detA=0) ?

    Возможны ли плохо обусловленные матрицы ?

    Reply
  4. Арчибальд

    (3) Метод Гаусса (приведение к верхнетреугольному виду). Это как раз для плохо обусловленных матриц. И пузырьковая сортировка строк.

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

    Reply
  5. Demarsh

    (1) Что ж, я ждал, что раньше или позже эта ссылка всплывет. В таком случае придется сказать, что я стоял у истоков, приведенной по ссылке компании и программного продукта. Правильнее сказать, что как программист, именно я создал систему распределения затрат на платформе 7.7, которая использовала внешнюю библиотеку (по решению систем линейных уравнений), которая в свою очередь используется в вышеупомянутом продукте. К созданию данного продукта на платформе 8.1, я имею лишь косвенное отношение, однако понимание того как он работает мне очень хорошо знакомо.

    К созданию собственного алгоритма распределения затрат, меня подтолкнула мизерная проблема, которая может возникать при использовании численных методов решения системы линейных уравнений. А именно возможность зависания копеек разного знака после распределения. Происходит это потому, что решение системы линейный уравнений идет относительно тарифов, т.е. вычисляется стоимость одной единицы «Коэффициента распределения». Например, если в качестве коэффициентов используется количество переданной электроэнергии, то решая систему мы ищем стоимость одного квт/час. Соответственно сумма проводки вычисляется как значение Тарифа*Коэффициент распределения, а так как сумма проводки должна иметь только 2 знака после запятой, то при округлении и возникают злополучные копейки. Теория о том, что если где-то зависла копейка, то пройдя по графу найдем минус копейку — закроем одно на другое и все будет ок, к сожалению не проходит, проверено на распределениях затрат реальных предприятий.

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

    Reply
  6. Demarsh

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

    Reply
  7. Ish_2

    (4) Дело в том , что я как-то столкнулся с решением СЛАУ в 1с и пробовал устойчивую и очень простую разновидность метода сопряженных градиентов для произовльной матрицы А(m,n) с нахождением обобщенного решения (нормального псевдорешения).

    Если будет желание , как-нибудь обсудим.

    Reply
  8. Арчибальд

    (5) Поиск копейки по графу, действительно, крайне неблагодарное занятие. Не следует бескомпромиссно оставаться в математических рамках — см. 4 коммент.

    Однако же остается вопрос расчета пресловутых коэффициентов. Или это за рамками статьи? Я понимаю, конечно, что главным в статье является «сквозное» прослеживание затрат от первичных до подажи — и это ценоо и полезно.

    Reply
  9. Арчибальд

    (7) Шо, невыпуклая задача была?

    Reply
  10. Demarsh

    (8) На самом деле я готов дать ответ или даже написать еще одну статью по поводу коэффициентов, но походу зашорен в своих формулировках и никак не могу понять вопрос.

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

    Вкратце, могу выделить следующие схемы для определения коэффициентов:

    1. Коэффициенты могут браться из производственных отчетов соответствующих объектов учета, т.е. коэффициенты являются некими натуральными показателями. Например, АТЦ (маш/час), РМЦ (час), Электроснабжение (квт/ч), Котельная (гкал) и т.п. Собственно здесь расчет коэффициентов не происходит, происходит их сбор, на основе первичных документов.

    2. Если объект производит некую продукцию (полуфабрикаты). То в качестве коэффициентов может использоваться Количество выпущенной продукции (полуфабрикатов)*Плановую стоимость для каждого наименования продукции. Что в данном случае считать под «Плановой стоимостью» — это вопрос скорее к ПЭО. В зависимости от вида производства данное понятие может принимать разные значения от нормативов до рыночной стоимости.

    3. Коэффициенты для движения готовой продукции (полуфабрикатов) берутся такие же как и в п.2, если ведется партионный учет. При учете по средней необходимо также учесть начальные остатки.

    4. Коэффициенты определяются пропорционально каким-либо первичным затратам или их совокупности. В основном применяются для общепроизводственных и общецеховых затрат. Здесь, по-моему, тоже никаких проблем — анализируем соответствующие проводки до начала распределения.

    5. При использовании директ-костинга, коэффициенты могут рассчитываться пропорционально выручке, выручке (нетто), количеству реализованных товаров (продукции). Тут собственно предварительно анализируем реализацию.

    6. Коэффициенты для распределения транспортно-заготовительных расходов — рассчитываются на основании движений тех или иных МТР (материально-технических ресурсов) по сумме или количеству. Соответственно анализируем движения по нужным счетам учета МТР.

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

    Reply
  11. Demarsh

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

    Reply
  12. Арчибальд

    (10, 11) Понятно. За пределами темы статьи.

    Reply
  13. Ish_2

    (9) Ага.

    Но А*А=А*b ,где А*-транспонированная, и задача становится выпуклой.

    Нужен был простой и всегда сходящийся, тупой алгоритм.

    Чтоб никаких сложных операций , кроме умножения матрицы на вектор и скалярного произведения ,не было.

    Для 1с достаточно.

    Reply
  14. Ish_2

    (9) Конечно, А*Аx=А*b.

    Reply
  15. Grey

    Похоже от бухгалтерии ушли в численные мат. методы

    Reply
  16. adva

    Спасибо за публикацию, как раз понадобилось решить задачу, в ней описанную, а нет ли еще публикаций на данную тему, что-то кроме этой ничего не выдало?

    Reply

Leave a Comment

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