Округление суммы каждой строки документа с учетом скидок для конфигурации УТ 11 (версия 11.2 и новее)




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

    А если есть оплата бонусами, округление сработает корректно?

    Reply
  2. Sholl

    Округление происходит до выбора способа оплаты и сработает корректно.

    Если нужно, чтобы оставшаяся сумма оплаты была без копеек, то списывать бонусы нужно так же без копеек.

    Reply
  3. user1158308

    Установить скидку можно будет для конкретного соглашения/склада?

    Reply
  4. Sholl

    На закладке «Условия предоставления», можно добавить условия, как для любого вида скидок.

    Reply
  5. garin

    Создал Новую группу «Округление», но она не верхняя, обязательно требуется указать «Группа совместного применения». Потом сколько не пытаюсь изменить уровень — пишет: Поле «Группа совместного применения» обязательно к заполнению.

    Что делать? Будет так работать обработка или нет?

    Reply
  6. Sholl

    (5) Не обязательно создавать верхнюю группу. Главное, чтобы все настроенные скидки были в группе «Округление» с вариантом «Умножение» и наш вид скидки «Округление» должен быть внизу с наибольшем порядком в своем уровне.

    Reply
  7. burgomister

    (6) Спасибо, всё работает. Только я рассчитывал на другое. Если от общей суммы по документу, которая включает НДС, высчитать НДС (*20/120), то НДС получается другой, чем по строкам, бывает до 20 копеек. Хотелось от этого избавиться, но не совсем без копеек.

    Reply
  8. user856012

    (7)

    Если от общей суммы по документу, которая включает НДС, высчитать НДС (*20/120), то НДС получается другой, чем по строкам, бывает до 20 копеек. Хотелось от этого избавиться

    Для этого придется «избавиться» от математики, которая гласит: «сумма округлений не обязательно равна округлению суммы».

    Кроме того, как вы собираетесь вычислять НДС «от общей суммы по документу», если документ включает в себя позиции со ставками НДС 20% и 10%?

    Reply
  9. burgomister

    (8) 1. У нас нет НДС 10 %. 2. Выходит, выхода нет? А что делают все? Это же не только у нас проблема такая. 3. Предполагал цикл: если общий НДС не идёт с тем что по строкам, то на тех строках, где НДС со знаками после запятой больше чем 2, то в этих строках добавлять или убавлять копейку. Затем сравнивается суммы, и читается если надо следующая строка. Это возможно?

    Reply
  10. burgomister

    А можно добавить ещё одно округление: до копеек, то есть 2 знака после запятой?

    Reply
  11. user856012

    (9)

    1. У нас нет НДС 10 %.

    И что? Это решает проблему? Или наоборот, создает ее?

    А что делают все? Это же не только у нас проблема такая.

    Не скажу за всех, но у вас проблема в незнании предмета.

    Потому что нормальные люди реализуют товары (работы, услуги), и только подобные вам «грамотеи» реализуют документы.

    Разница в том, что первые исчисляют НДС со стоимости товара, а вторые — с суммы документа.

    На каком основании они это делают — я полагаю, спрашивать бесполезно.

    Reply
  12. Sholl

    (10) А разве результат округления «до копеек» не будет равен сумме до округления?

    Reply
  13. burgomister

    Я знаю разницу когда начислять НДС — по строкам или по документу. Бухгалтер требует. Полагаю, не одна она такая. «Я хочу так» — возразить нечего. Ко мне обратились не к первому. Я могу ничего и не делать, мне в общем, всё равно. Полагал, что у вас есть возможность помочь. Нет — переживу. Зря потратил стартмани. Ещё раз прошу меня понять: я знаю почему это происходит с НДС. Мне удивительно, что создали законодатели такую проблему и не хотят её устранить. Извините, что вы зря потратили на меня время.

    Reply
  14. user925364

    Не работает, никак. Сделал все по инструкции — другие автоматические скидки работают, а округление нет. То есть ее даже не видно в списке автоматических скидок при нажатии ‘назначить автоматические скидки наценки’

    Reply
  15. Sholl

    (14) Если нет в списке автоматических скидок, то скорее всего не установлен статус «Действует» на дату документа продажи.

    Reply
  16. AndySB

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

    Исправляем в функции Рассчитать

         ИначеЕсли Настройки.ВариантОкругления=Перечисления.ВариантыОкругления.ВсегдаВПользуКлиента Тогда
    ОкругленнаяСумма=Окр(СуммаСоСкидкой-МинТочность,-Настройки.ТочностьОкругления);
    

    на

         ИначеЕсли Настройки.ВариантОкругления=Перечисления.ВариантыОкругления.ВсегдаВПользуКлиента Тогда
    ОкругленнаяСумма = СуммаСоСкидкой — СуммаСоСкидкой % МинТочность;
    
    
    Reply

Leave a Comment

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