Всем доброго дня.
Уверен, что многие еще столкнутся с данной проблемой, после перепрошивки кассовых аппаратов АТОЛ на версию формата фискальных данных 1.2. Эта информация в основном для тех, кто поддерживает самописные конфигурации.
Ранее мы просто брали GTIN и серийный номер из маркировки, формировали 16-ричный код и записывали его в реквизит 1162.
Теперь этот путь закрыт.
Основная суть изменившегося подхода при пробитии чека - мы должны занести в память кассового аппарата полный код маркировки с криптохвостом, проверить его и проверенный код пробить в чеке, чтобы получить заветный [M+].
Мой код для отражения продажи/возврата маркированной продукции,передаваемой в Честный Знак, тестировалось на драйвере DTO 10.9.1.0:
//Переменные на входе
// Кассир - ФИО кассира
// ВидЧека - "ПРОДАЖА" или "ВОЗВРАТ"
// Телефон - телефон контрагента
// ШтрихкодМаркировки - маркировка товара из системы Честный Знак
// Номенклатура - название товара
// Цена,Количество,СуммаНДС (в примере 20%)
// СуммаАванса,СуммаНал,СуммаБезнал
//Переменные на выходе
// НомерЧека, НомерДокумента
//Обращаемся к объекту драйвера DTO10
//Инициализируем параметры кассы.
FR = Новый COMОбъект("AddIn.Fptr10");
FR.setSingleSetting(FR.LIBFPTR_SETTING_MODEL, Строка(FR.LIBFPTR_MODEL_ATOL_AUTO));
FR.setSingleSetting(FR.LIBFPTR_SETTING_PORT, FR.LIBFPTR_PORT_COM);
FR.setSingleSetting(FR.LIBFPTR_SETTING_COM_FILE, 1);
FR.setSingleSetting(FR.LIBFPTR_SETTING_BAUDRATE, 9600);
FR.setSingleSetting(FR.LIBFPTR_SETTING_ACCESS_PASSWORD, "0");
FR.setSingleSetting(FR.LIBFPTR_SETTING_USER_PASSWORD, 1);
FR.applySingleSettings();
Если FR.open()<>0 тогда //Соединение с ККТ
Сообщить("Ответ: "+FR.errorCode()+" Ошибка: "+FR.errorDescription());
возврат;
КонецЕсли;
FR.setParam(1021, СокрЛП(Кассир));
FR.operatorLogin();
// После прошивки - важный параметр "Система налогообложения",
// который слетает в неопределенность.
// Либо ставьте в драйверве в регистрации по умолчанию, либо указывайте явно
FR.setParam(1055, FR.LIBFPTR_TT_OSN);
//FR.setParam(1055, fptr.LIBFPTR_TT_ENVD);
Попытка
//стираем все запрошенные маркировки из памяти кассового аппарата
FR.clearMarkingCodeValidationResult();
Исключение
КонецПопытки;
Если ВидЧека = "ВОЗВРАТ" тогда
FR.setParam(FR.LIBFPTR_PARAM_RECEIPT_TYPE, FR.LIBFPTR_RT_SELL_RETURN);
Иначе
FR.setParam(FR.LIBFPTR_PARAM_RECEIPT_TYPE, FR.LIBFPTR_RT_SELL);
КонецеСли;
FR.setParam(FR.LIBFPTR_PARAM_RECEIPT_ELECTRONICALLY, false);
Если не СокрЛП(Телефон) = "" тогда
FR.setParam(1008, СокрЛП(Телефон));
КонецЕСли;
FR.openReceipt();
status = 1;
Разделитель = Символ(29);
ПодготовленныйШК = СокрЛП(ШтрихкодМаркировки);
ПодготовленныйШК = СтрЗаменить(ПодготовленныйШК,Разделитель,"");
КМ = Лев(ПодготовленныйШК, 31) + Разделитель + Сред(ПодготовленныйШК, 32, 6) + Разделитель + Сред(ПодготовленныйШК, 38);
//Получился код маркировки с восстановленными знаками GS1, если вдруг их не было в строке
//Много где было сказано, что надо использовать только 16-ричную кодировку. Это не так.
FR.setParam(FR.LIBFPTR_PARAM_MARKING_CODE_TYPE, FR.LIBFPTR_MCT12_AUTO);
FR.setParam(FR.LIBFPTR_PARAM_MARKING_CODE, КМ);
FR.setParam(FR.LIBFPTR_PARAM_MARKING_CODE_STATUS, status);
FR.setParam(FR.LIBFPTR_PARAM_MARKING_WAIT_FOR_VALIDATION_RESULT, Истина);
FR.setParam(FR.LIBFPTR_PARAM_MARKING_PROCESSING_MODE, 0);
FR.beginMarkingCodeValidation();
ВремяНачала = ТекущаяДата();
ВремяОжидания = 100;
// Начало проверки
Пока истина Цикл
FR.getMarkingCodeValidationStatus();
Если FR.getParamBool(FR.LIBFPTR_PARAM_MARKING_CODE_VALIDATION_READY) тогда
прервать;
КонецЕсли;
Если ТекущаяДата() - ВремяНачала > ВремяОжидания тогда
прервать;
КонецЕсли;
КонецЦикла;
validationResult = FR.getParamInt(FR.LIBFPTR_PARAM_MARKING_CODE_ONLINE_VALIDATION_RESULT);
FR.acceptMarkingCode();
//Наш штрихкод проверен и занесен в память аппарата
// Теперь его ОБЯЗАТЕЛЬНО надо повторить в самой продаже
// Если этого не сделать - то ничего и не отошлется
FR.setParam(FR.LIBFPTR_PARAM_COMMODITY_NAME,СокрЛП(Номенклатура));
FR.setParam(FR.LIBFPTR_PARAM_PRICE, Окр(Цена,2));
FR.setParam(FR.LIBFPTR_PARAM_QUANTITY, Количество);
FR.setParam(FR.LIBFPTR_PARAM_TAX_TYPE,FR.LIBFPTR_TAX_VAT20);
FR.setParam(FR.LIBFPTR_PARAM_TAX_SUM, СуммаНДС);
FR.setParam(FR.LIBFPTR_PARAM_MARKING_CODE, КМ);
FR.setParam(FR.LIBFPTR_PARAM_MARKING_CODE_STATUS, status);
FR.setParam(FR.LIBFPTR_PARAM_MARKING_CODE_ONLINE_VALIDATION_RESULT, validationResult);
FR.setParam(FR.LIBFPTR_PARAM_MARKING_PROCESSING_MODE, 0);
Если FR.registration() <> 0 тогда
Сообщить("Ответ: "+FR.errorCode()+" Ошибка: "+FR.errorDescription());
FR.cancelReceipt();
Возврат;
КонецЕсли;
//Оплата
Если СуммаАванса>0 тогда
FR.setParam(FR.LIBFPTR_PARAM_PAYMENT_TYPE, FR.LIBFPTR_PT_PREPAID);
FR.setParam(FR.LIBFPTR_PARAM_PAYMENT_SUM, СуммаАванса);
FR.payment();
КонецеСли;
Если СуммаНал>0 тогда
FR.setParam(FR.LIBFPTR_PARAM_PAYMENT_TYPE, FR.LIBFPTR_PT_CASH);
FR.setParam(FR.LIBFPTR_PARAM_PAYMENT_SUM, СуммаНал);
FR.payment();
КонецеСли;
Если СуммаБезнал>0 тогда
FR.setParam(FR.LIBFPTR_PARAM_PAYMENT_TYPE, FR.LIBFPTR_PT_ELECTRONICALLY);
FR.setParam(FR.LIBFPTR_PARAM_PAYMENT_SUM, СуммаБезнал);
FR.payment();
КонецеСли;
FR.closeReceipt();
//открыть ящик
FR.openDrawer();
FR.setParam(FR.LIBFPTR_PARAM_DATA_TYPE, FR.LIBFPTR_DT_STATUS);
FR.queryData();
НомерЧека = FR.getParamInt(FR.LIBFPTR_PARAM_RECEIPT_NUMBER);
НомерДокумента = FR.getParamInt(FR.LIBFPTR_PARAM_DOCUMENT_NUMBER);