Коррекция чека в 1С:Розница




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

22 Comments

  1. Tatitutu

    обработка то хорошая , но строго для тех людей кто понимает что делает и делает это во блага (себя любимого — шутка)

    и называется так хороошо «Замена товара в чеке»

    ты представь себе сколько сейчас продавцов скачают и наменяют (а % тебе будут слать — ты БОГАТ)

    менять можно даже если чек пробит по ФР

    ИМХО.Страшная эта штука — она больше вреда принесет , чем пользы.

    Продумай на доступом (лог журнала пусть ведет, бекап(откат) додумай)

    Reply
  2. west__

    (1) Огромное спасибо, за отличные советы! Про лог сразу и не подумал..

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

    Постараюсь в скором времени довести до ума =)

    Reply
  3. Tatitutu

    (2) добавляй проверку прав (как минимум Админ)

    да и Админам это нежно, поверь — приведет только к хаусу

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

    Тот кто продумывал логику программы изначально — ставил условие

    «проведен — не хрен трогать»

    Живи по уставу — завоюешь честь и славу»

    лучше продавцов «пугайте» сильнее за косяки, а то они вообще расслабятся

    Reply
  4. west__

    (3) Чего-то от Ваших слов мне не по себе стало — действительно «монстра» создал. Верно подмечено.

    А ещё сначала думал её администраторам отдать на пользование.. нафиг-нафиг! С историей и бэкапом обязательно разберусь сначала.

    Reply
  5. stalnoypes

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

    Reply
  6. west__

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

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

    Во-вторых, в любом случае чек в базе мы найдём по его номеру. А если мы действительно пробили не тот товар, то пересорт и инвентаризация нам помогут конечно же. Но не во всех случая это возможно, иногда для оперативного контроля в базе необходимо иметь актуальную информацию об остатках, А это возможно только при замене товара в чеке и Z-отчёте. Сам по себе архивный чек не влияет на остаток, так что ничего страшного в итоге мы не делаем, если занимаемся только архивными чеками, но зато получаем верные отчёты по чекам.

    а ещё вот:

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

    Чек нельзя аннулировать после его пробития, это тоже незаконно, можно лишь оформить возврат на товары из чека (до закрытия смены, конечно же).

    Reply
  7. tango

    (6) «эклз мы никак не залезем»

    смените обслуживающую организацию

    Reply
  8. west__

    Ещё разок для не особо внимательных читающих:

    в эклз мы никак не залезем и это запрещено законом
    Reply
  9. tango

    «… и з/п у нас вся пушистая!»

    Reply
  10. west__

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

    Reply
  11. stalnoypes

    О чем я в принципе и говорю, что данные телодвижения запрещены законом… Поэтому я и не вижу в ней смысла, тем более, что я еще ни разу не встречал Розницу без ЭКЛЗ..

    Reply
  12. west__

    (11)С лета прошлого года организациям, переведённым на ЕНВД по отдельным видам деятельности, разрешается не использовать ЭКЛЗ в розничной торговле. Т.к. что пожалуйста. А полезность этой обработки я уже описал (см. комм. №(6)). Если кому ещё не очень понятно, пишите — постараюсь объяснить. 😉

    Reply
  13. aavolkoff

    Здравствуйте!

    Как некогда автор и разработчик механизма статусов чеков ККМ могу сказать, что:

    — Изменение данных архивного документа повлечет за собой несоответствие отчетов по чекам и по регистрам. Для того чтобы этого не произошло необходимо при изменении данных в чеке менять данные в связанном документе «ОтчетОРП» (предварительно убедившись, что «ОтчетОРП» проведется задним числом и нигде ничего не всплывет 🙂 ).

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

    P.S. При разработке механизмов есть такая штука, как цель, требования и задачи. Советую их описать и все станет понятно 🙂

    Александр Волков,

    В прошлом автор и разработчик «1С: Розница 8».

    Reply
  14. west__

    (13)Большое спасибо, приятно послушать мнение разработчика.

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

    А на счёт:

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

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

    Ещё раз спасибо.

    Reply
  15. leon_031275

    СПАСИБО ЗА ОБРАБОТКУ!!!! ОЧЕНЬ ПОМОГЛА. 😀

    Reply
  16. Sk0rp

    Очень помогла.

    Когда сбоит ФР и в документе не ставится отметка о пробитии чека, хотя сам чек вылез и в памяти ККV учтен — это единственная возможность исправить косяк.

    Единственно, я бы удалял и создавал новый чек в транзакции, что бы вдруг не получилось, что старый чек будет удален, а новый не создан.

    Reply
  17. griper

    Очень полезная обработка для исправления чеков. Большое спасибо.

    Reply
  18. overdriver

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

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

    Пример:

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

    Reply
  19. overdriver

    (18) в продолжение. Дописал проверку количества. Ниже кусок кода из процедуры ЗаменаТовараЧека(). Может кому пригодится

     // Если нашли строку со старым товаром,
    // то заменяем в ней товар на Новый Товар с Новой Характеристикой.
    Если СтрокаТовара  <> Неопределено Тогда
    Если СтрокаТовара.Количество=1 тогда
    СтрокаТовара.Номенклатура = ПулТовара.НовыйТовар;
    СтрокаТовара.ХарактеристикаНоменклатуры = ПулТовара.ХарактеристикаНовая;
    ИначеЕсли СтрокаТовара.Количество>1 тогда
    СтрокаТовара.Количество = СтрокаТовара.Количество-1;
    СтрокаТовара2 = Отчет.Товары.Добавить();
    ЗаполнитьЗначенияСвойств(СтрокаТовара2,СтрокаТовара);
    СтрокаТовара2.ХарактеристикаНоменклатуры = ПулТовара.ХарактеристикаНовая;
    Иначе
    Возврат Ложь;
    КонецЕсли;
    Иначе
    Результат = «Не корректно задан старый товар для замены!»;
    Возврат Ложь;
    КонецЕсли;
    

    Показать

    Reply
  20. sazabi

    Планируете ли доработку для массового изменение состояния чеков?

    Reply
  21. west__

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

    Reply
  22. west__

    (19) overdriver, Спасибо, буду учитывать..

    Reply

Leave a Comment

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