РМК в 1С:Розница — рабочее место кассира: экран, где кассир сканирует товар, принимает наличные и карты и пробивает чек на онлайн-кассе. Ниже — настройка, кассовая смена, цены и скидки, работа при потере связи и четыре доработки РМК расширением с кодом.
Код и имена объектов сверены по выгрузке УТ 11.4, где РМК — форма «ФормаДокументаРМК» документа «Чек ККМ». В 1С:Розница 3.0 рабочее место переработано, поэтому имена форм и процедур перед переносом сверяйте в своей конфигурации.
РМК рассчитан на поток покупателей: крупные кнопки, горячие клавиши, работа без мыши — для любого магазина с онлайн-кассой и сканером. В УТ 11.4 РМК работает с ККТ, сканером штрихкодов, эквайринговым терминалом, весами, дисплеем покупателя и считывателем магнитных карт.
В 1С:Розница 3.0 РМК с версии 3.0.2 получил плиточный подбор, избранные товары и вход без открытия смены. Есть и отдельная программа «1С:РМК» — внешнее рабочее место кассира для 1С:Касса, Розницы, УНФ, УТ, КА и ERP, которое работает только вместе с ними.
Чтобы настроить РМК в 1С, пройдите шаги по порядку. Пути меню — для УТ 11.4.
Цена и скидки в чеке. Скидки по акциям РМК рассчитывает при оплате или по кнопке «Рассчитать скидки», ручную скидку кассир даёт кнопкой «Ручные скидки» в пределах своего процента.
По методической статье 1С для версий 3.0.2 и новее путь такой: «Настройки» → «Администрирование» → «РМК и подключаемое оборудование» → «Рабочие места кассиров» → «Настройки РМК». В группах «Интерфейс», «Общие настройки» и «Формирование чека» включают расширенную форму подбора, строку быстрого добавления товара, сворачивание строк при печати чека. Для кассы без подключения ККТ в карточке кассы ККМ ставят флажок «Без подключения».
| Действие | Клавиши в УТ 11.4 |
|---|---|
| Поиск по штрихкоду | F7 |
| Поиск (подбор товаров) | Ctrl+Shift+F2 |
| Оплатить наличными | Ctrl+Shift+F7 |
| Оплатить картой | Ctrl+Shift+F8 |
| Смешанная оплата | Ctrl+Shift+F10 |
| Возврат | Ctrl+Shift+F5 |
| Новый чек | Ctrl+F12 |
| Операции с ККМ | Ctrl+Shift+F11 |
| Рассчитать скидки | Ctrl+Shift+F4 |
| Получить вес | Ctrl+Alt+F8 |
Раскладку меняют в элементе справочника «Горячие клавиши», выбранном в настройках РМК: клавиша с Ctrl, Shift или Alt для каждой команды, флажок «Скрывать» убирает кнопку, но оставляет клавишу. Там же заводят быстрые товары — кнопки для ходовых позиций.
Смену открывают и закрывают в меню «Операции с ККМ», там же «Внесение», «Выемка» и «Открыть денежный ящик». Если смена закрыта, при оплате УТ 11.4 спросит «Перед выполнением операции требуется открыть новую кассовую смену.» и откроет её на ККТ. Смена живёт не больше 24 часов. При закрытии ККТ снимает Z-отчёт, а 1С формирует «Отчет о розничных продажах». В Рознице 3.0 в РМК можно войти без открытия смены: её открывают вручную или при выборе оплаты.
Чаще всего просят остатки по другим магазинам, запрет продажи по условию, строку в чеке и сводку по сменам. Всё это делается расширением — типовая остаётся на поддержке (подробнее — в статье о расширениях конфигурации). Префикс в примерах — Расш1_.
Для Розницы 3.0 сначала найдите модуль РМК своей версии: глобальный поиск конфигуратора (Ctrl+Shift+F) по тексту сообщения с экрана кассира приведёт в нужный модуль, а по вызовам — к форме РМК и процедурам оплаты.
Добавьте в расширение форму «ФормаДокументаРМК» документа «Чек ККМ», на вкладке «Команды» создайте Расш1_ОстаткиВМагазинах с сочетанием Ctrl+Alt+F9 (в раскладке УТ 11.4 оно свободно) и перетащите её в группу ГруппаНижняяКоманднаяПанельКонтекстныеКоманды4 — типовой код сам разложит кнопки нижней панели. Размеры кнопки скопируйте с соседней.
// Листинг 1. Расширение: модуль формы Документ.ЧекККМ.Форма.ФормаДокументаРМК.
// В форму расширения добавлена команда Расш1_ОстаткиВМагазинах
// (действие Расш1_ОстаткиВМагазинах, сочетание клавиш Ctrl+Alt+F9),
// кнопка лежит в группе ГруппаНижняяКоманднаяПанельКонтекстныеКоманды4.
&НаКлиенте
Процедура Расш1_ОстаткиВМагазинах(Команда)
ТекущиеДанные = Элементы.Товары.ТекущиеДанные;
Если ТекущиеДанные = Неопределено
Или Не ЗначениеЗаполнено(ТекущиеДанные.Номенклатура) Тогда
ПоказатьПредупреждение(, НСтр("ru = 'Встаньте на строку с товаром.'"));
Возврат;
КонецЕсли;
ТекстОстатков = Расш1_ОстаткиПоМагазинам(
ТекущиеДанные.Номенклатура,
ТекущиеДанные.Характеристика,
Объект.Склад);
ПоказатьПредупреждение(, ТекстОстатков, , Строка(ТекущиеДанные.Номенклатура));
КонецПроцедуры
// Остатки в единицах хранения по всем розничным магазинам.
&НаСервереБезКонтекста
Функция Расш1_ОстаткиПоМагазинам(Номенклатура, Характеристика, ТекущийСклад)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗРЕШЕННЫЕ
| Остатки.Склад КАК Склад,
| СУММА(Остатки.ВНаличииОстаток) КАК ВНаличии
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки(
| ,
| Номенклатура = &Номенклатура
| И Характеристика = &Характеристика
| И Склад.ТипСклада = ЗНАЧЕНИЕ(Перечисление.ТипыСкладов.РозничныйМагазин)) КАК Остатки
|
|СГРУППИРОВАТЬ ПО
| Остатки.Склад
|
|ИМЕЮЩИЕ
| СУММА(Остатки.ВНаличииОстаток) > 0
|
|УПОРЯДОЧИТЬ ПО
| ВНаличии УБЫВ";
Запрос.УстановитьПараметр("Номенклатура", Номенклатура);
Запрос.УстановитьПараметр("Характеристика", Характеристика);
Строки = Новый Массив;
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
СтрокаОстатка = СтрШаблон("%1: %2", Выборка.Склад, Выборка.ВНаличии);
Если Выборка.Склад = ТекущийСклад Тогда
СтрокаОстатка = СтрокаОстатка + " " + НСтр("ru = '(этот магазин)'");
КонецЕсли;
Строки.Добавить(СтрокаОстатка);
КонецЦикла;
Если Строки.Количество() = 0 Тогда
Возврат НСтр("ru = 'В магазинах этого товара нет.'");
КонецЕсли;
Возврат СтрСоединить(Строки, Символы.ПС);
КонецФункции
По коду УТ 11.4 перед оплатой РМК проводит чек, деньги с карты списываются раньше печати, а после печати чек проводится ещё раз со статусом «Пробит». Поэтому проверка стоит в ОбработкаПроверкиЗаполнения модуля объекта, а форма вызывает её до оплаты (листинг 3). Пример запрещает товар без цены и алкоголь с 23:00 до 8:00.
// Листинг 2. Расширение: модуль объекта документа ЧекККМ.
#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда
#Область ОбработчикиСобытий
&После("ОбработкаПроверкиЗаполнения")
Процедура Расш1_ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
// После печати на ККТ типовая проводит чек повторно со статусом «Пробит».
// Отказ в этот момент оставит чек пробитым на кассе, но не записанным
// в базе, поэтому пробитые чеки не проверяем.
Если Статус = Перечисления.СтатусыЧековККМ.Пробит Тогда
Возврат;
КонецЕсли;
Расш1_ПроверитьНулевыеЦены(Отказ);
Расш1_ПроверитьВремяПродажиАлкоголя(Отказ);
КонецПроцедуры
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
// Подарки по нулевой цене, если они бывают, исключите отдельным условием.
Процедура Расш1_ПроверитьНулевыеЦены(Отказ)
Для Каждого СтрокаТовара Из Товары Цикл
Если СтрокаТовара.Цена > 0 Тогда
Продолжить;
КонецЕсли;
ТекстОшибки = СтрШаблон(
НСтр("ru = 'Строка %1: у товара «%2» нет цены. Проверьте розничный вид цены магазина.'"),
СтрокаТовара.НомерСтроки,
СтрокаТовара.Номенклатура);
ОбщегоНазначения.СообщитьПользователю(ТекстОшибки, ЭтотОбъект,
ОбщегоНазначенияКлиентСервер.ПутьКТабличнойЧасти("Товары", СтрокаТовара.НомерСтроки, "Цена"), , Отказ);
КонецЦикла;
КонецПроцедуры
Процедура Расш1_ПроверитьВремяПродажиАлкоголя(Отказ)
Запрет = Расш1_ЧасыЗапретаПродажиАлкоголя();
// Час по часовому поясу сеанса: закон говорит о местном времени.
ЧасСейчас = Час(ТекущаяДатаСеанса());
Если ЧасСейчас >= Запрет.Конец И ЧасСейчас < Запрет.Начало Тогда
Возврат; // дневное время, ограничений нет
КонецЕсли;
// Флажок «Алкогольная (спиртосодержащая) продукция» ставят и спиртосодержащим
// товарам; если их продают ночью, уточните отбор по виду продукции.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Номенклатура
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Ссылка В (&Товары)
| И Номенклатура.АлкогольнаяПродукция";
Запрос.УстановитьПараметр("Товары", Товары.ВыгрузитьКолонку("Номенклатура"));
Алкоголь = Новый Соответствие;
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Алкоголь.Вставить(Выборка.Номенклатура, Истина);
КонецЦикла;
Если Алкоголь.Количество() = 0 Тогда
Возврат;
КонецЕсли;
Для Каждого СтрокаТовара Из Товары Цикл
Если Алкоголь[СтрокаТовара.Номенклатура] <> Истина Тогда
Продолжить;
КонецЕсли;
ТекстОшибки = СтрШаблон(
НСтр("ru = 'Строка %1: «%2» нельзя продавать с %3:00 до %4:00.'"),
СтрокаТовара.НомерСтроки,
СтрокаТовара.Номенклатура,
Запрет.Начало,
Запрет.Конец);
ОбщегоНазначения.СообщитьПользователю(ТекстОшибки, ЭтотОбъект,
ОбщегоНазначенияКлиентСервер.ПутьКТабличнойЧасти("Товары", СтрокаТовара.НомерСтроки, "Номенклатура"), , Отказ);
КонецЦикла;
КонецПроцедуры
// Начало запрета — вечерний час, конец — утренний. По 171-ФЗ розничная
// продажа алкоголя запрещена с 23 до 8 часов; регион может ужесточить.
Функция Расш1_ЧасыЗапретаПродажиАлкоголя()
Возврат Новый Структура("Начало, Конец", 23, 8);
КонецФункции
#КонецОбласти
#КонецЕсли
ВыполнитьРасчет вызывают все команды оплаты до открытия формы оплаты, ПараметрыОперацииФискализацииЧека собирает данные для ККТ. Продавец уходит в чек дополнительным реквизитом пользователя (тег 1084) — касса напечатает «Продавец: …», если драйвер поддерживает этот реквизит.
// Листинг 3. Расширение: модуль формы Документ.ЧекККМ.Форма.ФормаДокументаРМК
// (тот же модуль, что в листинге 1).
// ВыполнитьРасчет вызывают команды оплаты наличными, картой, смешанной
// оплаты и сертификатом — до формы оплаты и до обращения к терминалу.
&НаКлиенте
&Вместо("ВыполнитьРасчет")
Процедура Расш1_ВыполнитьРасчет(ДополнительныеПараметры)
// ПроверитьЗаполнение() выполнит ОбработкаПроверкиЗаполнения модуля
// объекта вместе с проверками листинга 2 и покажет сообщения кассиру.
Если Не ПроверитьЗаполнение() Тогда
Возврат; // оплата не начнется, с карты ничего не спишется
КонецЕсли;
ПродолжитьВызов(ДополнительныеПараметры);
КонецПроцедуры
// Строка «Продавец: ...» в чеке через дополнительный реквизит
// пользователя (тег 1084). БПО передает его драйверу ККТ.
&НаКлиенте
&Вместо("ПараметрыОперацииФискализацииЧека")
Функция Расш1_ПараметрыОперацииФискализацииЧека()
ПараметрыЧека = ПродолжитьВызов();
Продавец = Расш1_ПродавецЧека();
Если ЗначениеЗаполнено(Продавец) И Продавец <> Объект.Кассир Тогда
Реквизит = ПараметрыЧека.ДополнительныйРеквизитПользователя;
Реквизит.Наименование = НСтр("ru = 'Продавец'");
Реквизит.Значение = Лев(Строка(Продавец), 64); // длину ограничивает формат ФД
КонецЕсли;
Возврат ПараметрыЧека;
КонецФункции
&НаКлиенте
Функция Расш1_ПродавецЧека()
// Продавец хранится в строках корзины, берем первую заполненную.
Для Каждого СтрокаТовара Из Объект.Товары Цикл
Если ЗначениеЗаполнено(СтрокаТовара.Продавец) Тогда
Возврат СтрокаТовара.Продавец;
КонецЕсли;
КонецЦикла;
Возврат Неопределено;
КонецФункции
Сводка за период по каждой смене: число чеков, продажи, из них картой, возвраты и выручка. Запрос годится для консоли и набора данных СКД, функция — для серверного кода.
// Листинг 4. Общий модуль расширения Расш1_ОтчетыКассы (флажок «Сервер»).
// Сводка по кассовым сменам: чеки, продажи, оплата картами, возвраты.
// В СКД условие на кассу уберите и отбирайте кассу отбором отчета.
Функция СводкаПоСменам(НачалоПериода, КонецПериода, КассаККМ = Неопределено) Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Смены.Ссылка КАК КассоваяСмена,
| Смены.КассаККМ КАК КассаККМ,
| Смены.НомерСменыККТ КАК НомерСменыККТ,
| Смены.НачалоКассовойСмены КАК Начало,
| Смены.ОкончаниеКассовойСмены КАК Окончание,
| Смены.Статус КАК Статус
|ПОМЕСТИТЬ Смены
|ИЗ
| Документ.КассоваяСмена КАК Смены
|ГДЕ
| Смены.Проведен
| И Смены.НачалоКассовойСмены МЕЖДУ &НачалоПериода И &КонецПериода
| И (&КассаККМ = НЕОПРЕДЕЛЕНО
| ИЛИ Смены.КассаККМ = &КассаККМ)
|
|ИНДЕКСИРОВАТЬ ПО
| КассоваяСмена
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| Чеки.КассоваяСмена КАК КассоваяСмена,
| КОЛИЧЕСТВО(Чеки.Ссылка) КАК ЧековПродажи,
| СУММА(Чеки.СуммаДокумента) КАК СуммаПродаж
|ПОМЕСТИТЬ Продажи
|ИЗ
| Документ.ЧекККМ КАК Чеки
|ГДЕ
| Чеки.КассоваяСмена В
| (ВЫБРАТЬ
| Т.КассоваяСмена
| ИЗ
| Смены КАК Т)
| И Чеки.Проведен
| И Чеки.Статус = ЗНАЧЕНИЕ(Перечисление.СтатусыЧековККМ.Пробит)
|
|СГРУППИРОВАТЬ ПО
| Чеки.КассоваяСмена
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| Оплаты.Ссылка.КассоваяСмена КАК КассоваяСмена,
| СУММА(Оплаты.Сумма) КАК СуммаКартой
|ПОМЕСТИТЬ Карты
|ИЗ
| Документ.ЧекККМ.ОплатаПлатежнымиКартами КАК Оплаты
|ГДЕ
| Оплаты.Ссылка.КассоваяСмена В
| (ВЫБРАТЬ
| Т.КассоваяСмена
| ИЗ
| Смены КАК Т)
| И Оплаты.Ссылка.Проведен
| И Оплаты.Ссылка.Статус = ЗНАЧЕНИЕ(Перечисление.СтатусыЧековККМ.Пробит)
|
|СГРУППИРОВАТЬ ПО
| Оплаты.Ссылка.КассоваяСмена
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| Возвраты.КассоваяСмена КАК КассоваяСмена,
| КОЛИЧЕСТВО(Возвраты.Ссылка) КАК ЧековВозврата,
| СУММА(Возвраты.СуммаДокумента) КАК СуммаВозвратов
|ПОМЕСТИТЬ ВозвратыПоСменам
|ИЗ
| Документ.ЧекККМВозврат КАК Возвраты
|ГДЕ
| Возвраты.КассоваяСмена В
| (ВЫБРАТЬ
| Т.КассоваяСмена
| ИЗ
| Смены КАК Т)
| И Возвраты.Проведен
| И Возвраты.Статус = ЗНАЧЕНИЕ(Перечисление.СтатусыЧековККМ.Пробит)
|
|СГРУППИРОВАТЬ ПО
| Возвраты.КассоваяСмена
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| Смены.КассаККМ КАК КассаККМ,
| Смены.КассоваяСмена КАК КассоваяСмена,
| Смены.НомерСменыККТ КАК НомерСменыККТ,
| Смены.Начало КАК Начало,
| Смены.Окончание КАК Окончание,
| Смены.Статус КАК Статус,
| ЕСТЬNULL(Продажи.ЧековПродажи, 0) КАК ЧековПродажи,
| ЕСТЬNULL(Продажи.СуммаПродаж, 0) КАК СуммаПродаж,
| ЕСТЬNULL(Карты.СуммаКартой, 0) КАК ИзНихКартой,
| ЕСТЬNULL(ВозвратыПоСменам.ЧековВозврата, 0) КАК ЧековВозврата,
| ЕСТЬNULL(ВозвратыПоСменам.СуммаВозвратов, 0) КАК СуммаВозвратов,
| ЕСТЬNULL(Продажи.СуммаПродаж, 0) - ЕСТЬNULL(ВозвратыПоСменам.СуммаВозвратов, 0) КАК Выручка
|ИЗ
| Смены КАК Смены
| ЛЕВОЕ СОЕДИНЕНИЕ Продажи КАК Продажи
| ПО Смены.КассоваяСмена = Продажи.КассоваяСмена
| ЛЕВОЕ СОЕДИНЕНИЕ Карты КАК Карты
| ПО Смены.КассоваяСмена = Карты.КассоваяСмена
| ЛЕВОЕ СОЕДИНЕНИЕ ВозвратыПоСменам КАК ВозвратыПоСменам
| ПО Смены.КассоваяСмена = ВозвратыПоСменам.КассоваяСмена
|
|УПОРЯДОЧИТЬ ПО
| КассаККМ,
| Начало";
Запрос.УстановитьПараметр("НачалоПериода", НачалоДня(НачалоПериода));
Запрос.УстановитьПараметр("КонецПериода", КонецДня(КонецПериода));
Запрос.УстановитьПараметр("КассаККМ", ?(ЗначениеЗаполнено(КассаККМ), КассаККМ, Неопределено));
Возврат Запрос.Выполнить().Выгрузить();
КонецФункции
&НаСервереБезКонтекста — форма РМК тяжёлая, контекстный вызов гонял бы на сервер все её данные.Остатки(...), а не в ГДЕ: остатки считаются только по нужному товару. РАЗРЕШЕННЫЕ спасает от ошибки, если доступ кассира ограничен по складам.&После("ОбработкаПроверкиЗаполнения") — наши проверки идут после типовых; имя в кавычках обязано совпадать с процедурой типового модуля, иначе расширение не применится.Если Статус = ...Пробит Тогда Возврат — главная строка листинга 2: без неё отказ при повторном проведении даст чек, пробитый на ККТ, но не записанный в базе.&Вместо без ПродолжитьВызов() отменяет типовую процедуру — так листинг 3 останавливает оплату до обращения к терминалу.Тексты сообщений — из кода УТ 11.4, в Рознице 3.0 формулировки могут отличаться.
Интерфейсом и настройками: в Рознице 3.0 плиточный подбор и вход без открытия смены, в УТ 11 РМК — форма документа «Чек ККМ» с классической раскладкой. Приёмы доработки те же, имена объектов разные.
Да. В УТ 11.4 — флажок «Использовать без подключения оборудования» в настройках РМК, в Рознице 3.0 — «Без подключения» в кассе ККМ. Чек пробивают на автономной кассе, а 1С учитывает продажу и при закрытии смены формирует отчёт о розничных продажах.
Проверьте набор «Горячих клавиш» в настройках РМК этого рабочего места и дубли сочетаний: даже в форме РМК УТ 11.4 Ctrl+Shift+F2 задано и подбору, и отмене оплат картами. В веб-клиенте часть клавиш перехватывает браузер — запускайте РМК в тонком клиенте.
РМК берёт действующую цену розничного вида цены магазина. Изменили цены, но не перепечатали ценники — будет расхождение; печать ценников разобрана в статье о ценниках в Рознице 3.0.
Если РМК нужно связать с бонусной программой, сайтом или маркетплейсами, добавить свои проверки и строки в чек, а своего программиста нет, задачу проще отдать исполнителю: доработка 1С на заказ. Опишите её на странице размещения задания — оценка бесплатная, ответ в течение рабочего дня.
Станьте частью сообщества!
Войдите или зарегистрируйтесь, и вы сможете участвовать в обсуждениях.