Опыт интеграции ФР Штрих-М с 1С

Надвигается 1 июля и всем срочно нужны ККМ-онлайн. Публикую свой опыт быстрого и простого решения на базе фискального регистратора Штрих-М для обычных форм.

Предлагаемая публикация — просто некоторые заметки и наработки, позволившие мне быстро и почти безболезненно запустить в работу ККМ-онлайн модели Штрих-М 01Ф. Поскольку драйвер (а значит, и API) у многих моделей схож или вообще одинаков, думаю, можно распространить эти наработки ещё на несколько популярных моделей. На мой взгляд, и аппаратно, и программно указанный ФР прост, надёжен и стабилен (мне вот никакими адскими опытами пока не удалось ввергнуть его в ошибку, блокировку или иную бяку). По продукции Штрих-М на официальном сайте выложено множество документации, в т.ч. хорошее пользовательское описание и отличная документация для разработчиков, которой я и воспользовался. Там даже есть отрывочные примеры, правда, для 7.5 (если кому надо, могу выложить, я делал версию для 7.7 тоже).

Описанное хорошо подойдёт в случае, если разбираться в механизмах подключаемого оборудования БСП некогда, или если речь о конфигурациях на обычных формах, поколения УТ 10.3, как это было у меня. Или для самописных. Сверх опубликованного более ничего не требуется, никакие общие модули (я вообще на пустой конфе проверял сначала).

Установку и регистрацию в ОФД делал приглашённый специалист, но весь этот процесс также описан в руководствах.

Поскольку ничего внятного о тестовой эксплуатации узнать не удалось, работы велись сразу в «боевом» режиме, что обязывало минимизировать ошибки и количество тестовых запусков. Вообще, кто-то утверждает, что в природе есть тестовые фискальные накопители и даже якобы их можно купить, регистрируясь при этом в рабочем кабинете ОФД; некоторые ОФД открыли тестовые площадки приёма-перехвата данных, предоставляемые тоже по отдельному договору за отдельную плату. Но «старый добрый» способ теста — пробивать минимальные суммы — тоже законен и ФНС не напряжёт, и это мне в один голос говорили многие знающие люди. Так и поступил.

Общие принципы

Связь с аппаратом возможна через COM-порт кабелем usb, или через патчкорд по TCP-сокету. Важно, что связь через ком позволяет аппарату легко работать с терминалами. 1С где-то далеко, а рабочее место кассира оснащается ФР и надо лишь поставить драйвер на сам сервер да прокинуть порт (указать в настройках терминала и поправить безопасность, если потребуется), впрочем, эти приёмы обычно хорошо знают системные администраторы.  У меня ФР уже работает с 1С-кой в терминале.

Разумеется, я реализовал только самые первоочерёдно нужные операции, вообще их существенно больше, но общий принцип одинаков. При установке драйвера сразу ставится и программная компонента, подключаемая как внешняя штатным образом (обычно она сама сразу нормально регистрируется в системе). ПО к этому ФР включает пользовательский интерфейс утилиты ручного управления, и, что ценно, его поведение абсолютно совпадает с поведением программного интерфейса этой же утилиты. Т.е. можно сначала безо всякой 1С оформить некую операцию, используя интерфейс утилиты, а затем попробовать отдать аналогичные команды в коде 1С.

При работе используется переменная, содержащая com-объект, чьи свойства и методы, собственно, и используются. Поскольку, по сути, ФР это просто маленький принтер с некоторыми пакетными предзаданными действиями и собственной памятью, мы запрашиваем драйвер о значениях неких свойств, устанавливаем значения этих свойств, вызываем методы. Принята следующая идеология: сначала устанавливаются значения свойств, нужные для вызова действия, потом вызывается метод. Все методы — без параметров. По вызове метода некоторые свойства меняют свои значения.  Есть понятие «состояние ФР», определяющее, что он может и что нет в каждый момент времени. У некоторых из них есть уточняющие «подсостояния». Некоторые методы изменяют состояние ФР согласно своей внутренней логике. Подробнее всё это описано в руководстве для разработчика.

ФР обладает собственной аппаратной памятью, где хранит таблицы — это действительно плоские простые таблицы, никак не связанные между собой и наполненные значениями простых типов. «Настройка свойств» — «Таблицы». Без установленной связи с включённым аппаратом, ясен перец, недоступны. Советую полазить и ознакомиться. Они доступны для чтения и записи из программного кода. При работе с методами тем или иным свойствам указываются обычно числовые ID, соответствующие порядковым номерам строк в этих таблицах.

Почти каждый метод перед выполнением требует авторизации (указания ID пользователя), не ленитесь их указывать. Для выполнения некоторых методов требуется указание 29 (админ) или 30 (системный админ), так, например, простые смертные кассиры не могут закрыть смену и даже снять Х-отчёт. Подробнее эти завихрения разделения прав описаны в руководстве пользователя.

Исходники для основных действий.


// Инициализирует ФР как COM-объект; рекомендуется расположить в модуле "повт.исп." с сохранением в течение сеанса.
Процедура ИнициализироватьФР() Экспорт
Попытка
ПодключитьВнешнююКомпоненту("AddIn.DrvFR"); // достаточно штатной установки драйвера на локальный ПК или сервер
ком=Новый COMОбъект("AddIn.DrvFR"); // никакой более регистрации на современных ОС обычно не требуется
глФР=ком; // экспортная переменная глФР переменная должна быть объявлена в глобальном модуле обычного приложения
Исключение
Сообщить("Ошибка инициализации фискального регистратора кассовых чеков: "+ОписаниеОшибки(),СтатусСообщения.Важное);
КонецПопытки;
КонецПроцедуры

// Зависит от контекста реализации - например, это может быть параметр сеанса или реквизит справочника Пользователи, Кассы, Подразделения;
// возвращает элемент справочника, содержащего сведения о подключаемых устройствах; типовой или сделанный отдельно. Должен содержать
// сведения, необходимые для подключения к конкретному устройству (см. ПодключитьФР).
//
Функция ПолучитьИспользуемыйФР() Экспорт
//
КонецФункции

// Зависит от контекста реализации - например, это может быть параметр сеанса или реквизит справочника Пользователи, Кассы, Подразделения;
// возвращает число от 1 до 30, позицию в таблице пользователей и паролей ФР. Нулевое значение означает обычно невозможность работы.
// Число 29 означает права обычного администратора, 30 - системного администратора (под 30 рекомендуется вести тестирование и спец.операции).
Функция ПолучитьИдПользователя() Экспорт
//
КонецФункции

// Подключает физическое устройство, проверяет связь, приводит в рабочий режим логическое устройство.
// При нестабильной связи или нетривиальном кэшировании данных 1С/ОС, рекомендуется вызывать перед каждым рабочим действием.
//
// Возвращает успешность (булево). При ошибке возвращает Ложь.
//
// Параметры:
//    рУстройство - логическая запись об устройстве (например, элемент справочника), содержащая обычно следующие сведения для подключения:
//BaudRate
//НомерПортаCOM
//Таймаут
//ТаймаутСоединения
//ТаймаутСоединенияTCP
//ПортTCP
//ИмяУстройства
//IPУстройства
//РежимПодключения (см.руководство; например, 0 - ком-порт, 6 - tcp-сокет)
//
//    рКодОшибки - число; на входе 0, на выходе либо 0 (ошибок нет), либо код ошибки.
//    рПояснятьОК - булево; комментировать ли успешное подключение.
//
Функция ПодключитьФР(рУстройство,рКодОшибки=0,рПояснятьОК=Ложь) Экспорт
Попытка
рКодОшибки=0;
Если не ЗначениеЗаполнено(рУстройство) Тогда Возврат Ложь КонецЕсли;

фр=глФР;
фр.Password=30; // можно ещё 29

рез=фр.CheckConnection();
Если рез<>0 Тогда
//Сообщить("ПодключитьФР, ошибка предварительной проверки подключения: "+фр.ResultCodeDescription);
//рКодОшибки=фр.ResultCode;
рУжеПодключены=Ложь;
Иначе
Если рПояснятьОК Тогда Сообщить("ПодключитьФР, предварительная проверка подключения успешна.") КонецЕсли;
// смотрим, что она определила
Попытка рУжеПодключены=фр.Connected Исключение рУжеПодключены=Ложь КонецПопытки;
КонецЕсли;
//
Если рУжеПодключены Тогда Возврат Истина КонецЕсли;

Если рУстройство.РежимПодключения=0 Тогда
фр.BaudRate=6;
ИначеЕсли рУстройство.РежимПодключения=6 Тогда
фр.BaudRate=1;
КонецЕсли;
//
фр.ComNumber=рУстройство.НомерПортаCOM;
фр.Timeout=рУстройство.Таймаут;
фр.ConnectionTimeout=рУстройство.ТаймаутСоединения;
фр.TCPConnectionTimeout=рУстройство.ТаймаутСоединенияTCP;
фр.SyncTimeout=0;
фр.ComputerName=рУстройство.ИмяУстройства;
фр.LDIndex=0;
фр.LockTimeout=10000;
фр.TCPPort=рУстройство.ПортTCP;
фр.IPAddress=рУстройство.IPУстройства;
фр.UseIPAddress=False;
фр.ConnectionType=рУстройство.РежимПодключения;
фр.EscapeIP="127.0.0.1";
фр.EscapePort=1000;
фр.EscapeTimeout=1000;
фр.SysAdminPassword=30;
фр.CardPayType=2;
фр.CardPayEnabled=False;
фр.LogCommands=False;
фр.LogMethods=False;
фр.SaleError=False;
фр.MobilePayEnabled=False;
фр.PayDepartment=15;
фр.ParamsPageIndex=0;
фр.RealPayDepartment=1;
фр.WaitForPrintingDelay=1000;
фр.BufferingType=0;
фр.FeedAfterCut=False;
фр.FeedLineCount=3;
фр.StatusCommand=0;
фр.LogMaxFileSize=10;
фр.LogMaxFileCount=10;
фр.CodePage=0;
фр.PrintJournalBeforeZReport=False;
фр.TranslationEnabled=False;
фр.AdjustRITimeout=False;
фр.ReconnectPort=False;
фр.DoNotSendENQ=False;

рез=фр.Connect();
Если рез<>0 Тогда
Сообщить("ПодключитьФР, ошибка собственно подключения: "+фр.ResultCodeDescription);
рКодОшибки=фр.ResultCode;
Возврат Ложь;
Иначе
Если рПояснятьОК Тогда Сообщить("ПодключитьФР, собственно подключение успешно.") КонецЕсли;
КонецЕсли;

Если рез<>0 Тогда
Сообщить("ПодключитьФР, ошибка заключительной проверки подключения: "+фр.ResultCodeDescription);
рКодОшибки=фр.ResultCode;
Возврат Ложь;
Иначе
Если рПояснятьОК Тогда Сообщить("ПодключитьФР, заключительная проверка подключения успешна.") КонецЕсли;
КонецЕсли;

Попытка рУжеПодключены=фр.Connected Исключение рУжеПодключены=Ложь КонецПопытки;
Возврат рУжеПодключены;

Исключение
Сообщить("ПодключитьФР, ошибка: "+ОписаниеОшибки(),СтатусСообщения.Важное);
Возврат Ложь;
КонецПопытки;
КонецФункции

// Возвращает успешность (булево). Необязательное; но важно, что при уничтожении переменной связь разрушается не всегда
// (возможно, проявляется описанное в СП кэширование подключенных объектов внешних компонент в течение всего сеанса).
//
Функция ОтключитьФР(рКодОшибки=0,рПояснятьОК=Ложь) Экспорт
Попытка
рКодОшибки=0;

фр=глФР;
фр.Password=ПолучитьИдПользователя();

Попытка рУжеПодключены=фр.Connected Исключение рУжеПодключены=Ложь КонецПопытки;
Если не рУжеПодключены Тогда Возврат Истина КонецЕсли;

рез=фр.Disconnect(); // собственно главное
Если рез<>0 Тогда
Сообщить("ОтключитьФР, ошибка подключения: "+фр.ResultCodeDescription);
рКодОшибки=фр.ResultCode;
Возврат Ложь;
Иначе
Если рПояснятьОК Тогда Сообщить("ОтключитьФР, подключение успешно.") КонецЕсли;
Возврат Истина;
КонецЕсли;

Исключение
Сообщить("ОтключитьФР, ошибка: "+ОписаниеОшибки(),СтатусСообщения.Важное);
Возврат Ложь;
КонецПопытки;
КонецФункции

// Возвращает структуру вида: НомерОператора, ЕстьЛента, РазрядностьСумм, РазрядностьКоличеств, Режим, ОписаниеРежима,
// Подрежим, ОписаниеПодрежима, СостояниеФН. Если Режим=8 (открытый документ), то добавляется РежимОткрытогоДокумента
// и ОперацийВЧеке.
//
// При ошибке возвращает Неопределено.
//
// Номера и  назначение режимов и статусов (поле ECRMode):
//0 Принтер в рабочем режиме
//1 Выдача данных
//2 Открытая смена, 24 часа не кончились
//3 Открытая смена, 24 часа кончились
//4 Закрытая смена
//5 Блокировка по неправильному паролю налогового инспектора
//6 Ожидание подтверждения ввода даты
//7 Разрешение изменения положения десятичной точки
//8 Открытый документ // Продажа, Покупка, Возврат продажи, Возврат покупки, уточняется через ECRMode8Status
//9 Режим разрешения технологического обнуления (В этот режим ККМ переходит по включению  питания,  если  некорректна  информация  в  энергонезависимом ОЗУ ККМ).
//10 Тестовый прогон
//11 Печать полного фискального отчета
//12 Печать длинного отчета ЭКЛЗ
//13 Работа с фискальным подкладным документом
//14 Печать подкладного документа
//15 Фискальный подкладной документ сформирован
//
Функция ПолучитьРежимФР(рКодОшибки=0) Экспорт
Попытка
рКодОшибки=0;

фр=глФР;
фр.Password=ПолучитьИдПользователя();

Если фр.ECRMode=1 Тогда // вызывать нельзя
Возврат Неопределено;
КонецЕсли;

рРезультат=Новый Структура;

фр.GetDeviceMetrics();
Если фр.CapGetShortECRStatus Тогда
рез=фр.GetShortECRStatus();
Иначе
рез=фр.GetECRStatus(); // длинный полный
КонецЕсли;
Если рез<>0 Тогда
Сообщить("ПолучитьРежимФР, ошибка получения: "+фр.ResultCodeDescription);
рКодОшибки=фр.ResultCode;
Возврат Неопределено;
КонецЕсли;

рРезультат.Вставить("НомерОператора",фр.OperatorNumber);

рРезультат.Вставить("ЕстьЛента",фр.ReceiptRibbonIsPresent); // есть ли лента
рРезультат.Вставить("РазрядностьСумм",?(фр.PointPosition,2,0)); // для сумм, если Истина, то 2 разряда, иначе 0 разрядов
рРезультат.Вставить("РазрядностьКоличеств",?(фр.QuantityPointPosition,3,6)); // для количеств, если Истина, то 3 знака, иначе 6 знаков

рРезультат.Вставить("Режим",фр.ECRMode);
рРезультат.Вставить("ОписаниеРежима",фр.ECRModeDescription);

#Область ОписаниеПодрежимов
//0 Бумага есть – ККТ не в фазе печати операции – может принимать от хоста команды, связанные с печатью на том ленте, датчик которой сообщает о наличии бумаги.
//1 Пассивное отсутствие бумаги – ККМ не в фазе печати операции – не принимает от хоста команды, связанные с печатью на том ленте,
//   датчик которой сообщает об отсутствии бумаги.
//2 Активное отсутствие бумаги – ККМ в фазе печати операции – принимает только команды, не связанные с печатью. Переход из этого подрежима только в подрежим 3.
//3 После активного отсутствия бумаги – ККМ ждет команду продолжения печати. Кроме этого принимает команды, не связанные с печатью.
//4 Фаза печати операции длинного отчета (полные фискальные отчеты, полные отчеты ЭКЛЗ, печать контрольных лент из ЭКЛЗ) – ККМ не принимает от
//   хоста команды, связанные с печатью, кроме команды прерывания печати.
//5 Фаза печати операции – ККМ не принимает от хоста команды, связанные с печатью.
#КонецОбласти
рРезультат.Вставить("Подрежим",фр.ECRAdvancedMode);
рРезультат.Вставить("ОписаниеПодрежима",фр.ECRAdvancedModeDescription);

Если фр.ECRMode=8 Тогда
// 0 Открыт чек продажи, 1 Открыт чек покупки, 2 Открыт чек возврата продажи, 3 Открыт чек возврата покупки
рРезультат.Вставить("РежимОткрытогоДокумента",фр.ECRMode8Status);
рРезультат.Вставить("ОперацийВЧеке",фр.QuantityOfOperations); // количество операций в текущем чеке
КонецЕсли;

рРезультат.Вставить("СостояниеФН",фр.FMResultCode);

Возврат рРезультат;
Исключение
Сообщить("ПолучитьРежимФР, ошибка: "+ОписаниеОшибки(),СтатусСообщения.Важное);
Возврат Неопределено;
КонецПопытки;
КонецФункции

// Возвращает структуру вида СостояниеСмены (см.руководство программиста), НомерЧека, НомерСмены.
// При ошибке возвращает Неопределено.
//
Функция ПолучитьНомерСменыИЧека(рКодОшибки=0) Экспорт
Попытка
рКодОшибки=0;

фр=глФР;
фр.Password=30; // и только так

рез=фр.FNGetCurrentSessionParams();
Если рез<>0 Тогда
Сообщить("ПолучитьНомерСменыИЧека, ошибка получения: "+фр.ResultCodeDescription+" (использован пароль "+СокрЛП(фр.Password)+").");
рКодОшибки=фр.ResultCode;
Возврат Неопределено;
КонецЕсли;

рРезультат=Новый Структура;
рРезультат.Вставить("СостояниеСмены",фр.FNSessionState);
рРезультат.Вставить("НомерСмены",фр.SessionNumber); // если закрыта, то последней, если открыта, то текущей
рРезультат.Вставить("НомерЧека",фр.ReceiptNumber); // если закрыта, то 1, если открыта, то последниего текущего

Возврат рРезультат;
Исключение
Сообщить("ПолучитьНомерСменыИЧека, ошибка: "+ОписаниеОшибки(),СтатусСообщения.Важное);
Возврат Неопределено;
КонецПопытки;
КонецФункции

// Открывает кассовую смену. Возвращает успешность (булево).
Функция ОткрытьСмену(рКодОшибки=0) Экспорт
Попытка
рКодОшибки=0;

фр=глФР;
фр.Password=ПолучитьИдПользователя();

Если фр.ECRMode<>4 Тогда // смена уже открыта, или некий другой режим
рКодОшибки=99;
Возврат Истина;
КонецЕсли;

рез=фр.OpenSession();
Если рез<>0 Тогда
Сообщить("ОткрытьСмену, ошибка выполнения: "+фр.ResultCodeDescription);
рКодОшибки=фр.ResultCode;
Возврат Ложь;
КонецЕсли;

Сообщить("ОткрытьСмену, смена успешно открыта.");
Возврат Истина;
Исключение
Сообщить("ОткрытьСмену, ошибка: "+ОписаниеОшибки(),СтатусСообщения.Важное);
Возврат Ложь;
КонецПопытки;
КонецФункции

// Закрывает кассовую смену (снимает Z-отчёт). Возвращает успешность (булево).
Функция ЗакрытьСмену(рКодОшибки=0) Экспорт
Попытка
рКодОшибки=0;

фр=глФР;
фр.Password=30; // можно ещё 29

Если фр.ECRMode<>2 и фр.ECRMode<>3 Тогда // смена уже закрыта, или другой режим
рКодОшибки=99;
Возврат Истина;
КонецЕсли;

рез=фр.PrintReportWithCleaning();
Если рез<>0 Тогда
Сообщить("ЗакрытьСмену, ошибка выполнения: "+фр.ResultCodeDescription);
рКодОшибки=фр.ResultCode;
Возврат Ложь;
КонецЕсли;

Сообщить("ЗакрытьСмену, смена успешно закрыта.");
Возврат Истина;
Исключение
Сообщить("ЗакрытьСмену, ошибка: "+ОписаниеОшибки(),СтатусСообщения.Важное);
Возврат Ложь;
КонецПопытки;
КонецФункции

// Возвращает успешность (булево).
Функция СнятьХОтчет(рКодОшибки=0) Экспорт
Попытка
рКодОшибки=0;

фр=глФР;
фр.Password=30; // можно ещё 29

Если фр.ECRMode<>2 и фр.ECRMode<>3 Тогда // смена уже закрыта, или другой режим
Возврат Истина;
КонецЕсли;

рез=фр.PrintReportWithoutCleaning();
Если рез<>0 Тогда
Сообщить("СнятьХОтчет, ошибка снятия отчёта: "+фр.ResultCodeDescription);
рКодОшибки=фр.ResultCode;
Возврат Ложь;
КонецЕсли;

Сообщить("СнятьХОтчет, отчёт успешно снят.");
Возврат Истина;
Исключение
Сообщить("СнятьХОтчет, ошибка: "+ОписаниеОшибки(),СтатусСообщения.Важное);
Возврат Ложь;
КонецПопытки;
КонецФункции

// Выполняет печать чека (продажи, покупки, возврата продажи, возврата покупки)
// Возвращает булево, успешность. При ошибке возвращает Ложь.
// КодСтавкиНДС в данном случае общий на все позиции, т.е. для правильной печати у всех строк должна быть одинаковая ставка НДС.
//
// Параметры:
//    рПараметры - структура с обязательными ключами:
//        ДанныеПродажи (таблица значений или массив структур: колонки ПредставлениеНоменклатуры, Количество, Цена);
//        КодПодразделения (число);
//        КодСтавкиНДС (число), где 1 - 18%, 2 - 10%, 3 - 0%, 4 - Без налога, 5 - 18/118, 6 - 10/110;
//        СуммыОплат (структура: ключ - число, 1 нал, 2 безнал; значение - сумма платежа).
//    рКодОшибки - число, на входе 0, на выходе содержит числовой код ошибки. 0 - ошибок нет.
//
Функция НапечататьЧек(рПараметры,рКодОшибки=0) Экспорт
Попытка
рКодОшибки=0;

фр=глФР;
фр.Password=ПолучитьИдПользователя();

Если фр.ECRMode<>2 и фр.ECRMode<>3 и фр.ECRMode<>4 Тогда // смена уже закрыта, или другой режим
Возврат Истина;
КонецЕсли;

фр.CheckType=рПараметры.РежимЧека; // «0» - продажа, «1» - покупка, «2» - возврат продажи, «3» - возврат покупки.
рез=фр.OpenCheck();
Если рез<>0 Тогда
Сообщить("НапечататьЧек, ошибка открытия нового чека: "+фр.ResultCodeDescription);
рКодОшибки=фр.ResultCode;
Возврат Ложь;
КонецЕсли;

фр.StringForPrinting="============================================";
фр.UseReceiptRibbon=Истина;
фр.UseJournalRibbon=Ложь;
фр.PrintString();

Для каждого строДанных Из рПараметры.ДанныеПродажи Цикл
фр.Quantity=строДанных.Количество;
фр.Price=строДанных.Цена;
фр.Department=рПараметры.КодПодразделения;
фр.Tax1=рПараметры.КодСтавкиНДС;
фр.Tax2=0;
фр.Tax3=0;
фр.Tax4=0;
фр.StringForPrinting=СокрЛП(строДанных.ПредставлениеНоменклатуры);
//Работает в режимах 2 (проверка на окончание 24 часов производится запросом из ФП до
//выполнения операции), 4, 7, 8 (если статус 8-го режима ККМ=0) и 9
Если рПараметры.РежимЧека=0 Тогда
рез=фр.Sale(); // продажа
ИначеЕсли рПараметры.РежимЧека=1 Тогда
рез=фр.Buy(); // покупка
ИначеЕсли рПараметры.РежимЧека=2 Тогда
рез=фр.ReturnSale(); // возврат продажи
ИначеЕсли рПараметры.РежимЧека=3 Тогда
рез=фр.ReturnBuy(); // возврат покупки
КонецЕсли;
Если рез<>0 Тогда
Сообщить("НапечататьЧек, ошибка оформления записи продажи для "+СокрЛП(строДанных.ПредставлениеНоменклатуры)+": "+фр.ResultCodeDescription);
рКодОшибки=фр.ResultCode;
Возврат Ложь;
КонецЕсли;
КонецЦикла;
//
рез=фр.CheckSubTotal();
Если рез<>0 Тогда
Сообщить("НапечататьЧек, ошибка получения подытога чека: "+фр.ResultCodeDescription);
рКодОшибки=фр.ResultCode;
Возврат Ложь;
КонецЕсли;

фр.Summ1=0;
фр.Summ2=0;
фр.Summ3=0;
фр.Summ4=0;
Попытка фр.Summ1=рПараметры.СуммыОплат.Получить(1) Исключение КонецПопытки;
Попытка фр.Summ2=рПараметры.СуммыОплат.Получить(2) Исключение КонецПопытки;
Попытка фр.Summ2=рПараметры.СуммыОплат.Получить(3) Исключение КонецПопытки;
Попытка фр.Summ2=рПараметры.СуммыОплат.Получить(4) Исключение КонецПопытки;
фр.DiscountOnCheck=0; // в данной версии считается, что скидка уже заложена в изменённых ценах
фр.Tax1=рПараметры.КодСтавкиНДС;
фр.Tax2=0;

фр.StringForPrinting="============================================";
рез=фр.CloseCheck();
Если рез<>0 Тогда
Сообщить("НапечататьЧек, ошибка закрытия чека: "+фр.ResultCodeDescription);
рКодОшибки=фр.ResultCode;
Возврат Ложь;
КонецЕсли;

Возврат Истина;
Исключение
Сообщить("НапечататьЧек, ошибка: "+ОписаниеОшибки(),СтатусСообщения.Важное);
Возврат Ложь;
КонецПопытки;
КонецФункции

// Возвращает успешность (булево).
Функция АннулироватьЧек(рЗакрытиеАдминистратора=Ложь,рКодОшибки=0) Экспорт
Попытка
рКодОшибки=0;

фр=глФР;
Если рЗакрытиеАдминистратора Тогда
фр.Password=30; // системный
Иначе
фр.Password=ПолучитьИдПользователя();
КонецЕсли;

Если фр.ECRMode<>8 Тогда // чек не открыт
Возврат Истина;
КонецЕсли;

Если рЗакрытиеАдминистратора Тогда
рез=фр.SysAdminCancelCheck();
Иначе
рез=фр.CancelCheck();
КонецЕсли;
Если рез<>0 Тогда
Сообщить("АннулироватьЧек, ошибка отмены чека: "+фр.ResultCodeDescription);
рКодОшибки=фр.ResultCode;
Возврат Ложь;
КонецЕсли;

Сообщить("АннулироватьЧек, чек успешно аннулирован.");
Возврат Истина;
Исключение
Сообщить("АннулироватьЧек, ошибка: "+ОписаниеОшибки(),СтатусСообщения.Важное);
Возврат Ложь;
КонецПопытки;
КонецФункции

Я не стал реализовывать множество других команд, вроде «ПродолжитьПечать» или «ОтрезатьЧек», т.к. принцип, думаю, ясен, и сделать их самостоятельно не проблема. Кстати, «ПродолжитьПечать» (ContinuePrint) бывает архиполезна, если посередине печати чека, пока он открыт, случилась ошибка, а аннулирование чека (в т.ч. под админом) не прокатывает.

Примечания

Некоторые советы сверх комментариев в коде.

1. Если Вам непонятно, что делается со свойствами в момент выполнения некоей команды, вызываемой из тестовой утилиты, включите ведение лога («Настройка свойств» — «Дополнит.параметры» — «Лог») в свой файл, и внимательно прочитайте, что запишется при вызове команды. Так можно доподлинно узнать, «чего ему надо». Учтите, что программные вызовы драйвера (из вашей 1С) в лог не пишутся, только действия из интерфейса утилиты.

2. Большинство кнопок и некоторые поля в интерфейсе утилиты снабжено всплывающими подсказками, которые отображают имя команды API. Это удобно, чтобы понять, а что же скрывается за той или иной кнопкой, не нажимая её, безо всякого лога.

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

4. Используйте только латинские варианты свойств и методов. Русскоязычные — себе на уме.

5. Некоторые сообщения не то, чем кажутся. Например, ошибка несоответствия суммы подытога напрямую указанной сумме чека может выглядеть как отсутствие бумаги — и по коду, и по тексту ошибки, и по состоянию, в котором окажется ФР.

6. Если смена закрыта, то действия по чекам её открывают автоматически.

7. В зависимости от совокупности факторов (кэширование 1С, кэширование ОС) период жизни соединения колеблется, поэтому иногда приходится вызывать установку связи перед каждым полезным действием, а иногда и так прокатывает. Но, при этом, см. пункт 8.

8. Драйвер не понимает более 1 активного соединения, и неважно, это ваш COMОбъект или его родная утилита. Утилиту можно открыть «на посмотреть», но она вряд ли установит связь, пока существует соединение (ваша переменная в памяти 1С), и наоборот. Соединение в таких случаях не устанавливается, а наиболее характерная ошибка — таймаут. Не ставьте большой таймаут — всё равно не додумается. Чтобы запустить что-то, вам понадобится закрыть (выгрузить из памяти) что-то другое. В ряде случаев — ещё и выключить/включить сам ФР.

9. Методы и поля, представленные в интерфейсе утилиты, не жёсткая данность. Например, CheckSubTotal всегда вносит сумму в поле «summ1», но она может быть насильно перебита на другой тип оплаты. Учтите, «защита от дурака» у интерфейса утилиты понадёжнее, чем у методов API.

10. Не ленитесь прокручивать таблицы ФР при просмотре. Верхние строки могут быть пусты, а где-то внизу, строке на тридцатой, может поджидать интересный сюрприз.

Разумеется, весь этот примитивный код малополезен без инфраструктуры более высокого уровня — справочников, хранящих сведения об ФР и прочих кодах, документов вроде Кассовой смены, Чека ККМ итд. Но сие уж слишком зависит от конкретики, а опубликованное — оно общее.

Недостатки

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

1. Не допускается наличие в составе одного чека товаров с разными ставками НДС. Кому будет надо — это можно довольно легко доработать, но уже с упором на более высокоуровневые конструкции (табчасти документов, механику расчёта НДС итд).

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

3. Не раскрыты возможности оформления чеков и печати штрихкодов. Ну, тут уж мануал в руки и запасную катушку ленты в аппарат)

4. Проверка проводилась только на 3 модификациях ФР Штрих-М, и я не очень уверен, что на чём-то заковыристом абсолютно всё будет аналогично.

При небольшом допиливании или вовсе без него, должно работать и на 8.1, также уже гонял этот код с небольшими доработками под УФ на УТ 11.3 (заказчик не возжелал обновляться на типовую, ибо конфа весьма покуроченная).

Планирую докопаться до ФР АТОЛ, но у них с драйверами и их программными интерфейсами несколько больший разнобой, так что это пока наполеоновские планы.

Приглашаю всех к обсуждению. Если где накосячил, жду тухлых помидоров)

79 Comments

  1. Rik30

    Вопрос, а как реализован механизм отправки электронного чека в виде СМС и письма на эл.почту?

    Клиент вправе потребовать — электронный чек, помимо бумажного

    Reply
  2. Yashazz

    (1) В руководстве программиста на эту тему есть целый блок, но я его пока не курил. Авось позже доберусь.

    Reply
  3. Rik30

    как хоть называется? А то 308 листов мне тоже курить как то не хочется.

    Reply
  4. Yashazz

    (3) Опаньки, а нету… Где ж я видел-то… Ну, значит, в любом случае можно реализовать самостоятельно — почту через штатную 1С, а sms через любой подходящий сервис. Вопрос в чём — как Вы, к примеру, через sms передадите чек? Что там будет в этой sms?

    Reply
  5. Rik30

    Сервисы то есть штатные…СМС отправить не проблема…Но это должен делать ОФД, иначе как клиент поймёт,что это официальный чек. А как ОФД поймёт что нужно электронный чек клиенту отправить????

    Reply
  6. Yashazz

    (5) Честно? Пока хз.

    Reply
  7. e.kogan

    Руководство пользователя и программиста — Штрих-Мовские? Тогда лучше бы ссылками на скачивание на оф.сайте.

    Reply
  8. smurf2315

    (5)

    В реквизитах чека есть почта покупателя, если она заполнена то ОФД следовательно надо отсылать письмо

    В письме не сам чек а ссылка на чек в ОФД

    Reply
  9. hibico

    То есть, с Онлайн Штрихами работают старые методы?

    Из новых у Вас используется только «состояние смены».

    И грубо говоря, в старые обработки после открытия чека нужно только добавить ввод телефона, почты?

    Типа:

    //Отправка данных о покупателе
    Driver.CustomerEmail = Телефон;  //В качестве параметра можно передавать или телефон (+7хххххххххх) или e-mail: test@test.com
    Driver.FNSendCustomerEmail();
    Reply
  10. Yashazz

    Ну типа да, наверное. А собственно, кроме оплаты связи и работы с ФН, что уж такого принципиально нового?

    Reply
  11. hibico

    Самому проверить пока на чем.

    Очень смущает куча новых методов с префиксом «FN» без какого-то описания в документации.

    Например, если есть «OpenSession», тогда зачем и что значат «FNBeginOpenSession» и «FNOpenSession».

    Reply
  12. Yashazz

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

    (11) Думаю, это сессии отправки данных и работы именно ФН, а не кассовые смены.

    Reply
  13. Tatitutu

    «Согласно 54-ФЗ при расчётах продавец обязан выдать кассовый чек покупателю на бумажном носителе или в электронном виде по sms или e-mail (если есть техническая возможность).

    ООО «Такском», выступая в роли оператора фискальных данных, автоматически отправляет электронные чеки в электронном виде по sms или e-mail, если они содержат адрес получателя.

    Обратите внимание: Согласно 63-ФЗ «О связи» от покупателя необходимо получить письменное согласие или заявление на получение sms-рассылки до момента расчёта

    Reply
  14. tjurikov_ivan

    Думаю в крупных магазинах никто не будет заморачиваться с вводом при оплате почты или телефона, еще и согласие печатать и подписывать. Скачал приложение проверка чека в ФНС, отсканил QR-код, нажал получить чек, ввел данные и все. Кому надо тот пускай сам его и получает.

    Reply
  15. hibico

    Подскажите пожалуйста, у кого есть Штриховские онлайн кассы.

    Каким «типом устройства» драйвер определяет онлайн кассы?

    Можно посмотреть в «Тест драйвера» — «Состояние» -> «Параметры устройства».

    Перерыл все доки, нигде нет. Есть предположение, что по аналогии тип устройства должен быть «7», но нужно точно.

    Reply
  16. Alex

    Из всего найденного это самый простой и результативный подход.. Так что спасибо автору. И вопрос.. Попытался сделать скидку на чек.. ругается, не хочет. Вы пробовали скидки?

    Reply
  17. Yashazz

    (16) Пробовал, построчные и в целом на чек. Печатает. А что у Вас ругается?

    Reply
  18. Alex

    Команды по скидкам не отрабатываются. Ни построчно, ни на чек в целом. Но, возможно, это из-за прошивки. На одной кассе вообще не работала, пока апрельскую прошивку не поставили.

    Reply
  19. atdonya

    (18) Возможно дело в драйвере ККТ. У меня, например, в версии 4.13 ругался на вывод денег из кассы (что-то о недопустимой длине наименования), поставил 4.12 — все заработало нормально

    Reply
  20. ah7777777

    Хорошая статья! Я через это прошел лет 10 назад, правда на Дельфи и вот что выродил к 54ФЗ

    http://infostart.ru/public/609030/

    Reply
  21. Alex

    (19)Самое прикольное, что при одинаковом драйвере на win 7 скидки работают, а на win 10 нет.. Веселуха !

    Reply
  22. Alex

    В чеке выходит система налогообложения ЕНВД.. как ее поменять? Перерыл все.. тупик.. В стандартных 1с-овских программах она меняется.. а как это сделать командно не могу найти.. может кто подскажет.

    Reply
  23. Yashazz

    (22) Могу рассказать только «от корней». Запустите проверку драйвера Штрих-М, т.е. его встроенную утилиту (аппарат должен быть включён и доступен на связи), нажмите «Таблицы» и посмотрите, что у Вас в таблице «Налоговые ставки». Если там есть такая строка вроде «ЕНВД», то смотрите, какой номер секции передаёт 1С драйверу и откуда ноги растут у этого номера секции. Если такой строки нет — сообщите, где (в каком месте) проявляется, что это ЕНВД. Где это на чеке итд.

    Reply
  24. Yashazz

    (20) Мы практически совпали в подходе. Я сделал независимое от мудрёностей БСП и типовых конфигов, а ты сделал вообще не на 1С (кстати, была такая мысль тоже). И что 1С любит усложнять, соглашусь.

    Вообще что хочу сказать: читайте мануал юзера и программиста от Штрих-М, юзайте утилиту проверки драйвера, и будет щастье. Там всё просто.

    Reply
  25. nike-arz

    (22) ситема налогооблажения меняется в 18 таблице

    Объект.Пароль = Пароль;
    Объект.TableNumber = 18;
    Объект.RowNumber = 1;
    Объект.FieldNumber = 5;
    Объект.ValueofFieldInteger = ПараметрыККТ.КодНалогооблажения;
    Объект.GetFieldStruct();
    Объект.WriteTable();
    Если Объект.Результат <> 0 Тогда
    Результат = Объект.ОписаниеРезультата;
    Возврат Результат;
    КонецЕсли;

    Показать

    Reply
  26. Alex

    (25)Спасибо. Попробую.

    Reply
  27. autosvg

    (25)

    В этой таблице хранится система налогообложения, с которой касса регистрировалась. Там может стоять например «10» это ЕНВД + УСН Доход.

    (22)

    Чтобы пробить чек с определенной СНО нужно чек формировать командами FNOperation, закрывать командой FNCloseCheckEx предварительно указав TaxType

    ФР.CheckType = 0; //приход, продажа
    ФР.StringForPrinting =  Товар;
    ФР.Price  = Цена;
    ФР.Quantity = Количество;
    ФР.Tax1 = 4;
    ФР.FNOperation();
    
    ФР.CustomerEmail = АбАдрес;  //В качестве параметра можно передавать или телефон (+7хххххххххх) или e-mail: test@test.com
    ФР.FNSendCustomerEmail();
    
    ФР.Tax1=4;
    
    ФР.TaxType = 4;  // 2 — УСН Доход,  4 — УСН Доход-Расход, 8 — ЕНВД
    
    ФР.Summ1 = ОплатаНалом;
    ФР.Summ4 = ОплатаКартой;
    ФР.FNCloseCheckEx();
    
    

    Показать

    Reply
  28. Yashazz

    НалогооблАжение от слова Лажа? )))

    По сути да, верно. И это описано в руководстве)

    Reply
  29. user648052_it

    Подскажите пожалуйста, для операции FNOperation в каких реквизитах указывать такие поля как «Сумма по чеку постоплатой (кредит)» и «Сумма по чеку наличными» ? И еще в этой же операции есть реквизит Summ1, что в него необходимо записывать при частичных оплатах на опте?

    Reply
  30. sssss_aaaaa_2011

    Какая может быть сумма по ЧЕКУ в ТОВАРНОЙ строке? Какие еще виды платы в ТОВАРНОЙ строке?

    Reply
  31. user648052_it

    На форуме ФНС есть примеры реализаций для оптовиков, так вот там в Части 3 есть пример с предоплатой и постоплатой (отсрочкой оплаты с частичными погашениями). Исходя из этих примеров оптовик при первой отгрузке клиенту печатает чек с указанием для каждой товарной позиции признака способа расчета «Передача в кредит», далее когда клиент приносит часть оплаты за отгрузку, оптовик печатает чек с выборочными позициями, в котором напротив каждой погашаемой позиции указывается признак способа расчета «Оплата кредита», а в подвале чека помимо графы «Сумма чека наличными» печатается графа «Сумма по чеку постоплатой (кредит)» в которой указывается сумма долга по отгрузке. Так вот вопрос: как это реализовать в рамках операции FNOperation ? Берем документацию от 18.05.2017 Драйвера ККТ 4.13 и видим в разделе для операции FNoperation, указывается реквизит Summ1, когда пытаюсь в Summ1 указать сумму по каждой позиции то при вызове FNCloseCheckEx выдается ошибка что сумма всех оплат меньше итога. Но я же указываю признак «Передача в кредит», в чем ошибка?

    Reply
  32. sssss_aaaaa_2011

    (31) В том, что пример на форуме ФНС не имеет ничего общего с реальной жизнью драйвера от Штрих.

    Reply
  33. sssss_aaaaa_2011

    (31)

    Но я же указываю признак «Передача в кредит»,

    Кстати, где и как указываете?

    Reply
  34. nike-arz

    Совершенно верно. Ошибка будет. Первое: данные действия должны происходить только при использовании ФФД 1.05 или 1.1 На данный момент все используют ФФД 1.0. Второе недостающую сумму, которую вы указывали как предоплату или аванс надо заносить в 15 или 16 (точно не помню) операционный регистр. Но при любых действиях сумма товара и сумма оплат должна совпадать.

    Reply
  35. user648052_it

    (33)

    Кстати, где и как указываете?

    FR.PaymentTypeSign = 6; // 7 — Оплата Кредита

    Reply
  36. user648052_it

    (34)

    Совершенно верно. Ошибка будет. Первое: данные действия должны происходить только при использовании ФФД 1.05 или 1.1 На данный момент все используют ФФД 1.0. Второе недостающую сумму, которую вы указывали как предоплату или аванс надо заносить в 15 или 16 (точно не помню) операционный регистр. Но при любых действиях сумма товара и сумма оплат должна совпадать.

    Фискальный переведен в режим ФФД 1.05 через Таблицу 17. Можно поподробнее про операционные регистры, это в обход команды FNoperation ?

    Reply
  37. user648052_it

    (32)

    том, что пример на форуме ФНС не имеет ничего общего с реальной жизнью драйвера от Штрих.

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

    Reply
  38. nike-arz
    Объект.Сумма1 = ?(ПараметрыККТ.ПолученоНал = 0,0,ПараметрыККТ.ПолученоНал); //Наличная оплата
    Объект.Сумма2 = 0; //Оплата платежной картой
    Объект.Сумма3 = 0; //Оплата платежной картой
    Объект.Сумма4 = ?(ПараметрыККТ.ПолученоБезНал = 0,0,ПараметрыККТ.ПолученоБезНал); //Оплата платежной картой
    Объект.Сумма5 = 0; //
    Объект.Сумма6 = 0; //
    Объект.Сумма7 = 0; //
    Объект.Сумма8 = 0; //
    Объект.Сумма9 = 0; //
    Объект.Сумма10 = 0; //
    Объект.Сумма11 = 0; //
    Объект.Сумма12 = 0; //
    Объект.Сумма13 = ?(ПараметрыККТ.СуммаДисконта = 0,0,ПараметрыККТ.СуммаДисконта); //Оплата дисконтом
    Объект.Сумма14 = 0;//
    Объект.Сумма15 = ?(ПараметрыККТ.Предоплата + ПараметрыККТ.СуммаСертификатов = 0,0,ПараметрыККТ.Предоплата + ПараметрыККТ.СуммаСертификатов);//Оплата предоплатой и сертификатом
    Объект.Сумма16 = 0;//последующая Оплата кредитом

    Показать

    К сожалению использую ФФД 1.0 и более подробно рассказать не могу.

    Reply
  39. sssss_aaaaa_2011

    (37)

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

    Что за чушь? И что мешает работать с наличкой на ФФД 1.0? При чем тут признаки типа оплаты на каждой товарной строке и т.д.?

    Reply
  40. nike-arz

    На ФФД 1.0 признаки способа расчета не работают. Данные теги не передаются в ОФД и так далее в ФНС. Поэтому на ФФД 1.0 авансовые платежи не учитываются.

    Reply
  41. user648052_it

    (39)

    Что за чушь? И что мешает работать с наличкой на ФФД 1.0? При чем тут признаки типа оплаты на каждой товарной строке и т.д.?

    По закону можно проводить чеки если оплата полная, т.е. сумма отгрузки равна сумме внесенной наличности (ну или больше, со сдачей). Если же приходит часть суммы наличкой, то как аванс мы ее проводить не можем, т.к. по сути авансом это не является, и предоплата на ФФД 1.0 не работает…какие еще варианты?

    Reply
  42. user648052_it

    (40)

    На ФФД 1.0 признаки способа расчета не работают. Данные теги не передаются в ОФД и так далее в ФНС. Поэтому на ФФД 1.0 авансовые платежи не учитываются.

    насколько актуальная данная информация? ОФД не принимаю все или все такие какие то принимают?

    Reply
  43. nike-arz

    (42) Все зависит на каком ФФД работает ваш Фискальный накопитель. Насколько мне известно ФН для 1.05 начали изготавливать совсем недавно. У меня 7 касс и на всех стоят ФН с ФФД 1.0

    Reply
  44. user648052_it

    (43) В таблице 17 в графе 17 стоит 2, что согласно вот этому описанию https://forum.shtrih-m-partners.ru/index.php?topic=32170.0 означает ФФД 1.05

    Reply
  45. user648052_it

    (38)

    Попробовал передать сумму постоплаты через поле Сумма16, в офд пришел чек, а в подвале сумма указана «Сумма по чеку встречным представлением», попробовал потом через поле Сумма15 — чек вообще не пробивается, ругается на сумму безналичной оплаты…где передавать сумму постоплаты?

    Reply
  46. sssss_aaaaa_2011

    (45) Может таки дождаться готовности ВСЕХ участников процесса к работе с ФФД 1.05 и не бежать впереди паровоза?

    Reply
  47. sssss_aaaaa_2011

    (44) Это означает настройку кассы работать с этим форматом. ФН — не касса и его работа этой настройкой не регулируется. ФН, как уже было указано, пока все работают только с ФФД-1.0

    Reply
  48. user648052_it

    (46)

    Уже разобрался с Суммой15, а насчет дождаться — не получается, частичные платежи массово идут, а в ФФД 1.0 я не нашел способа их проведения

    Reply
  49. nike-arz

    (48)Как со всем разберешься. Опиши опыт в теме. Думаю всем будет интересно.

    Reply
  50. sssss_aaaaa_2011

    (48)

    Уже разобрался с Суммой15

    И что там было?

    Reply
  51. sssss_aaaaa_2011

    (35)

    FR.PaymentTypeSign = 6; // 7 — Оплата Кредита

    И где сие описано? Или методом научного тыка?

    Reply
  52. user648052_it

    (50)

    Не аннулировал предыдущие неудачные попытки продаж

    Reply
  53. user648052_it

    (51)

    это написано в Части3 примеров выложенных ФНС на официальном форуме

    ссылка: https://forum.nalog.ru/index.php?showtopic=782331

    Reply
  54. user648052_it

    Выкладываю итоговый результат работы:

    чтобы пробить частичную оплату необходимо сначала в ФнОперация передать 6 в качестве признака способа расчета и вызвать ВыпуститьЧекНомер1 передав ему сумму всей накладной, далее при каждом платеже вызывать ФнОперация с указанием 7 в качестве признака способа расчета и ВыпуститьЧек с суммой которую вносит покупатель.

    Вроде все согласно метод рекомендациямот фнс, если что-то напутал, поправьте

    //**************************************************************************************************
    Процедура ФнОперация(ТипЧека,Цена,Количество,Налог,Сумма, ПризнакСпособаРасчета, ПризнакПредметаРасчета, Наименование)
    FR2.CheckType = ТипЧека;
    FR2.Price = Цена;
    FR2.Quantity = Количество;
    FR2.Tax1 = Налог;
    FR2.Department = 1;
    FR2.Summ1 = Сумма;
    FR2.PaymentTypeSign = ПризнакСпособаРасчета;
    FR2.PaymentItemSign = ПризнакПредметаРасчета;
    FR2.StringForPrinting = Наименование;
    FR2.FNOperation();
    КонецПроцедуры
    
    //**************************************************************************************************
    Процедура ВыпуститьЧекНомер1(Сумма)
    FR2.Summ15 = Сумма;
    FR2.StringForPrinting = » «;
    FR2.FNCloseCheckEx();
    КонецПроцедуры
    
    //**************************************************************************************************
    Процедура ВыпуститьЧек(Сумма)
    FR2.Summ1 = Сумма;
    FR2.StringForPrinting = » «;
    FR2.FNCloseCheckEx();
    КонецПроцедуры

    Показать

    Reply
  55. sssss_aaaaa_2011

    (53) 1. Вы отдаете себе отчет, что это только проект и он может еще 100500 раз поменяться?

    2. Похоже, дают его тоьлко избранным, в число которых я не вхожу. Еще один повод не закладываться на него.

    Reply
  56. user648052_it

    (55)

    К сожалению я долго искал ответ на вопрос как проводить частичные продажи, чтобы они соответствовали 54-ФЗ, т.е. в чеках были полные наименования товаров и прочее, но не нашел ответа даже у самих налоговиков, и единственное что осталось это реализовать ФФД 1.05

    Reply
  57. zels

    Кто знает, как настроить ШТРИХ-М 01Ф, чтобы НДС печатался в каждой строке товара? В таблице 1 задавал Исчисление, Печать налогов

    0,1 — только итог

    1,1 — ошибка 35h

    0,2 — только итог

    1,2 — ошибка 35h

    Reply
  58. sssss_aaaaa_2011

    (57) Внимательно смотрим таблицу 17

    Reply
  59. zels

    (58) Региональные настройки?

    Reply
  60. zels

    (58) СПАСИБО огромное. В таблице 17 в строке «печать налога в операции» надо поставить 1.

    Reply
  61. gragden

    Яков, прошу прощения, я случайно минус поставил, отличная статья

    Reply
  62. rougudz

    Хелп кто писал самоитоятельно, сие касается авансов т.е. расчета подарочными сертификатами, пришлось при закрытии чека метод CloseCheck() заменить на FNCloseCheckEx()

    выглядит теперь сие вот так:

    FR.Пароль=30;
    FR.Summ1 = ВнесеноНаличных;
    FR.Summ2 = 0;
    FR.Summ3 = 0;
    FR.Summ4 = ВнесеноПоПластиковойКарте;
    FR.Summ14 = СуммаПредварителнойОплаты; // аванс (расчет подорочным сертификатом)
    //FR.Summ15 = 0; // кредит
    FR.DiscountOnCheck=0; // скидка на чек
    FR.PrintString();
    //FR.CloseCheck();
    FR.FNCloseCheckEx();

    Показать

    но в налоговую теперь все стало уходить как оплата по предоплате, т.е. как будто в Summ14 я передаю всю сумму оплаты. хотя там ноль, а вся сумма в Summ4 или Summ1.

    ни кто не сталкивался с такой проблемой?

    Reply
  63. Iriha_ko

    с 01 июля обязательные реквизиты ИНН покупателя и ИНН кассира. Кто-нибудь вносил их в чек? Какой командой или реквизитом это делается?

    Reply
  64. Yashazz

    (63) Если API ещё не допилили, то, думаю, просто как вывод произвольной строки на чек. Хоть в шапку или подвал засунуть)

    Reply
  65. Serge_ASB

    (63)

    ИНН Кассира передается тегом 1203.

    Передача тега — после открытия чека

    Примерно так:

    Прль = ФР.Пароль;
    ФР.Пароль = 30;
    ФР.НомерТега = 1203;    //TagNumber
    ФР.ТипТега = 7;            //TagType
    ФР.ЗначениеТегаСтрока = СокрЛП(ИННКассира);  //TagValueStr
    ФР.FNSendTag(); // отправка тега
    ФР.СтрокаДляПечати = «»;
    ФР.Пароль = Прль;

    Показать

    ИНН Кассира — как вариант — реквизит справочника Сотрудники (коим кассир является)

    А вот ИНН покупателя — он откуда возьмется, при розничной продаже?

    Reply
  66. Serge_ASB

    (54)

    А если мне нужно просто заполнить PaymentTypeSign и PaymentItemSign, нужно ли обязательно заполнять все остальные поля, поскольку они выводятся Командой «Продажа»?

    Для чего, вообще, предназначена команда ФНОперация?

    Reply
  67. Seeker

    (63)

    С чего вы решили что ИНН Кассира обязательное поле?

    согласно вот этому документу https://its.1c.ru/db/kkt#content:104:hdoc ИНН кассира (тег 1203) не обязательно или как пишет 1С «может присутствовать».

    Reply
  68. VSY666

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

    например: сумма 100 р. , ндс 5 р. т.к. ставка ндс 18/118

    написал код, и не могу понять почему фискальник ругается на некорректные данные

    Рез=неопределено;
    
    Если фр.ECRMode<>2 и фр.ECRMode<>3 и фр.ECRMode<>4 и фр.ECRMode<>8 Тогда // смена уже закрыта, или другой режим
    Возврат
    КонецЕсли;
    
    //фр.CheckType=рПараметры.РежимЧека; // «0» — продажа, «1» — покупка, «2» — возврат продажи, «3» — возврат покупки.
    КодОшибкиОборудования=фр.ResultCode;
    // Возврат Ложь;
    //КонецЕсли;
    
    //фр.StringForPrinting=»=========================================­===»;
    фр.UseReceiptRibbon=Истина;
    фр.UseJournalRibbon=Ложь;
    
    //фр.PrintString();
    
    фр.Quantity=Количество;
    фр.Price=Цена;
    фр.Department=Отдел;
    фр.Tax1=НомерНалога;
    фр.Tax2=0;
    фр.Tax3=0;
    фр.Tax4=0;
    фр.StringForPrinting=СокрЛП(Наименование);
    ФР.ЗначениеНалога1Вкл = РучнойРасчетНалогов;
    
    Если НомерНалога = 5 Тогда //если это группа 5 т.е 18/118 ндс
    фр.summ1 = Товар.Сумма;
    фр.Summ1Enabled = 1;
    //Если Summ1Enabled имеет значение «ложь», то сумма операции рассчитывается кассой как
    //цена* количество, в противном случае сумма операции берётся из значения Summ1 и не должна
    //отличаться более чем на +-1 коп от рассчитанной кассой
    фр.TaxValue1  = Товар.СуммаНалога1;
    ФР.ЗначениеНалога1Вкл = 1;
    фр.Summ14  = Товар.Сумма;
    фр.ИтогЧека = Товар.Сумма;
    КонецЕсли;
    
    //Работает в режимах 2 (проверка на окончание 24 часов производится запросом из ФП до
    //выполнения операции), 4, 7, 8 (если статус 8-го режима ККМ=0) и 9
    Если фр.CheckType=0 Тогда
    рез=фр.Sale(); // продажа
    ИначеЕсли фр.CheckType=1 Тогда
    рез=фр.Buy(); // покупка
    ИначеЕсли фр.CheckType=2 Тогда
    рез=фр.ReturnSale(); // возврат продажи
    ИначеЕсли фр.CheckType=3 Тогда
    рез=фр.ReturnBuy(); // возврат покупки
    КонецЕсли;
    
    
    ФР.ПризнакПредметаРасчета = ПризнакПредметаРасчета;
    ФР.ПризнакСпособаРасчета = ПризнакСпособаРасчета;
    
    
    Если рез<>0 Тогда
    Сообщить(«НапечататьЧек, ошибка оформления записи продажи для «+СокрЛП(Наименование)+»: «+фр.ResultCodeDescription);
    рКодОшибки=фр.ResultCode;
    Возврат
    КонецЕсли;
    
    
    
    рез=фр.CheckSubTotal();
    Если рез<>0 Тогда
    Сообщить(«НапечататьЧек, ошибка получения подытога чека: «+фр.ResultCodeDescription);
    рКодОшибки=фр.ResultCode;
    Возврат
    КонецЕсли;
    
    фр.DiscountOnCheck=0; // в данной версии считается, что скидка уже заложена в изменённых ценах

    Показать

    Reply
  69. Yashazz

    А в какой момент он ругается-то, на каком операторе? На CheckSubTotal?

    Reply
  70. VSY666

    (69) вот в этот момент выдает что передаются неверные параметры и возвращает ошибку рез=фр.Sale(); // продажа

    Reply
  71. VSY666

    (69) почитал на разных источниках не нашел что именно передавать при ручном расчете налогов, а ведь нужно очень при ставке 18/118 передавать наш расчитанный НДС который естественно меньше от общей суммы

    вот тут почитал https://forum.infostart.ru/forum81/topic176078/ пишут что атол без проблем принимает ставку, а у штриха это вроде как не работает. Но ведь сам то параметр есть включения и отключения ручного расчета налогов

    Reply
  72. Raideres

    КАК ПЕРЕДАТЬ В Z ОТЧЕТ ФАМИЛИЮ КАССИРА

    Reply
  73. atdonya

    (72)

    КАССИРА

    Насколько я понял, никак — отчеты печатаются только от администратора

    Reply
  74. Yashazz

    (72) Однозначно никак. Действительно, только от админа всё. Ну разве что можно в утилите в рабочих таблицах менять строковое представление, кто есть админ, т.е. обладатель кодов 29 и 30. Это и программно можно сделать.

    Reply
  75. foliage

    Использую AddCashIn.Context, функцию РегистрацияПродажи (Документация к штриховскому Кассиру 5)

    Кассовый аппарат Штрих RR-01

    Функция РегистрцияПродажи( Знач БлокСтрок, Знач СтрокаККМ, Знач Сумма_дрб, Знач Количество_дрб, Знач Секция_инт, Знач Налоги, КодОшибки_инт = 0, Знач Регистрация_Форма = Null, Знач ДопПараметры=Null) Экспорт

    Что такое ДопПараметры и для чего их можно использовать?

    Задача — передавать в ОФД дополнительные данные, которые должны отображаться в чеке ОФД.

    «Доппараметры» подойдут?

    Reply
  76. newtandy

    Добрый день!

    Ни как не могу разобраться с отправкой в кассовый аппарат ШТРИХ-М-02Ф тега 1229 (сумма акциза)

    Использую драйвер 4.14.0.772

    Судя по документации штриха тег 1229 имеет тип 3 (Тип VLN). Для тегов этого типа необходимо использовать поле TagValueBin (тип строка ) для передачи суммы акциза.

    ККМ.Password = ПарольКассира ;

    ККМ.TagNumber = 1229 ;

    ККМ.TagType = 3 ;

    ККМ.TagValueBin = ЗначениеТега ;

    ККМ.TagValueLength = 6 ;

    ККМ.FNSendTagOperation() ;

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

    Попробовал отправлять этот тег через программу «Тест драйвера».

    Судя по всему в значение тега в этой программе необходимо указывать строку без разделителей дробной части — для 45.00 — указываем «4500» — из теста драйвера в чек в этом случае попадет 45.00

    В логе теста драйвера прописывается следующая информация:

    [03.10.2019 10:19:12.369] [00008328] [DEBUG] TDrvFR Set_TagNumber

    [03.10.2019 10:19:12.369] [00008328] [DEBUG] TDrvFR Set_TagNumber: 1229

    [03.10.2019 10:19:12.369] [00008328] [DEBUG] TDrvFR Set_TagType

    [03.10.2019 10:19:12.369] [00008328] [DEBUG] TDrvFR Set_TagType: 3

    [03.10.2019 10:19:12.369] [00008328] [DEBUG] TDrvFR Set_TagValueBin

    [03.10.2019 10:19:12.369] [00008328] [DEBUG] TDrvFR Set_TagValueBin: ь

    [03.10.2019 10:19:12.369] [00008328] [DEBUG] TDrvFR Set_TagValueLength

    [03.10.2019 10:19:12.369] [00008328] [DEBUG] TDrvFR Set_TagValueLength: 6

    [03.10.2019 10:19:12.369] [00008328] [DEBUG] TDrvFR FNSendTagOperation

    Нужна помощь — какая информация должна быть передана в переменной ЗначениеТега, для корректной установки суммы акциза

    Reply
  77. Yashazz

    (76) Сам сейчас занимаюсь этим же вопросом, только для 1227 и 1228; смогу сообщить что-то внятное — отпишусь.

    Reply
  78. newtandy

    (77)теги 1227 и 1228 имеют тип строка — для них все просто

    ККМ.Password = ПарольКассира ;
    ККМ.TagNumber = 1227 ;
    ККМ.TagType = 7 ;
    ККМ.TagValueStr= «НАИМЕНОВАНИЕ_ ПОКУПАТЕЛЯ»;
    ККМ.FNSendTag()   ; 

    причем эти теги привязаны к чеку а не к операции в чеке — поэтому ККМ.FNSendTag()

    Reply
  79. newtandy

    (76)После отправки запроса на суппорт штриха решение нашлось:

    «Да, есть ньюанс в драйвере. Попробуйте так:

    Driver.TagNumber = 1229;

    Driver.TagType = 3;

    Driver.TagValueLength = 6;

    Driver.TagValueVLN = «4500»;

    Driver.FNSendTagOperation();

    Т.е. вместо TagValueBin используем TagValueVLN.»

    Reply

Leave a Comment

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