2. Печать чека
Доступность: с версии 8.18.0
Регистрировать чеки можно только в открытой смене. Если смена закрыта, попытка напечатать чек завершится с ошибкой: "Перед печатью чеков необходимо открыть смену".
Согласно требованиям законодательства, длительность смены составляет 24 часа. По истечении этого времени необходимо закрыть смену.
Печать чека через приложение МодульКассы включает в себя прием оплаты (в том числе используя внешний эквайринг) и фискализацию чека. В качестве результата выполнения операции получим чек с фискальной информацией от ККТ и данными по платежной транзакции. Обработка возникающих ошибок производится на стороне МодульКассы с показом диалогов, требующих разрешения конфликтных ситуаций пользователем. Таким образом, МодульКасса позволяет разрешить возникающие в процессе оплаты коллизии с возможностью полной отмены оплаты. Если ошибку не удается устранить, вызывающее приложение получает ответ с описанием и причиной ошибки.
Перед отправкой чека на печать подготовьте данные в соответствии со структурой Check:
val demoCheck = Check(
id = UUID.randomUUID().toString(),
docType = SALE,
employee = "Иванов Иван Иванович",
printReceipt = true,
email = "some@email.ru",
inventPositions = listOf(
InventPosition(
name = "Материнская плата AS—Rock H32M R3.0, Socket1150, iH81, 2DDR3, PCI-Ex16, 2SATA2, 2SATA3",
price = BigDecimal("200"),
barcode = "2880000023757",
vatTag = TAG_1103,
quantity = BigDecimal.ONE,
measure = PCS,
inventCode = "2880000023757",
inventType = INVENTORY
),
InventPosition(
name = "Жесткий диск",
price = BigDecimal("100"),
barcode = "2880000023757",
vatTag = TAG_1103,
quantity = BigDecimal.ONE,
measure = PCS,
inventCode = "2880000023757"
)
),
moneyPositions = listOf(MoneyPosition(
paymentType = CASH,
sum = BigDecimal("1000")
)),
taxMode = COMMON,
textToPrint = "Текст для дополнительной\nпечати на чеке"
)
Приложение поддерживает два типа чека:
- Чек продажи (
DocumentType.SALE
) - Чек возврата (
DocumentType.RETURN
)
Тип указывается в поле Check.docType
.
В версии 8.66 появилась поддержка еще двух типов чека:
- Чек коррекции прихода (
DocumentType.SALE_CORRECTION
) - Чек коррекции возврата прихода (
DocumentType.SALE_RETURN_CORRECTION
)
Для успешной регистрации чеков коррекции необходимо передавать дополнительную информацию о коррекции в структуре CorrectionInfo в поле чека correctionInfo
.
При формировании чека фактический тип оплаты нужно указать в MoneyPosition
.
Поддерживается два типа оплаты:
- Наличными (
PaymentType.CASH
)
Укажите в MoneyPosition
ту сумму, которую передал покупатель. Если указанная сумма больше, чем сумма по позициям чека, будет автоматически рассчитана сдача.
val demoReturnCheck = Check(
...
moneyPositions = listOf(MoneyPosition(CASH, BigDecimal("1000")))
...
)
- Безналичными (
PaymentType.CARD
)
Укажите в MoneyPosition
сумму, равную сумме товаров по позициям, иначе при регистрации чека вернется ошибка. При оплате с помощью карты указать сдачу невозможно.
val demoReturnCheck = Check(
...
moneyPositions = listOf(MoneyPosition(CARD, BigDecimal("1000")))
...
)
С версии 8.31.0 в безналичной оплате можно указать идентификатор мерчанта, по которому на терминале будет проведена оплата. За эту возможность отвечает поле merchantId. Параметр является необязательным. В одном чеке может быть только одна безналичная оплата с одним идентификатором мерчанта. На стороне МодульКассы проверки на соответствие ID мерчанта и состава чека нет.
- Смешанная оплата
Создайте две MoneyPosition
с разными типами оплат. Сумма денежных позиций должна совпадать с суммой товаров по позициям, иначе при регистрации чека вернется ошибка. В чеке можно указать не более двух оплат, причем оплата с типом PaymentType.CARD
может быть только одна.
val demoReturnCheck = Check(
...
moneyPositions = listOf(
MoneyPosition(CASH, BigDecimal("300")),
MoneyPosition(CARD, BigDecimal("700"))
)
...
)
При создании чека возврата с безналичной оплатой есть возможность создать транзакцию на возврат или отменить транзакцию оплаты. За эту возможность отвечает поле refundThroughCancel. В таком случае также желательно будет заполнить дополнительные реквизиты оригинальной транзакции (linkedId, paymentSystemId, extra). Также, если необходимо, чтобы возврат/отмена проходили по чеку продажи, необходимо указать идентификатор чека в рамках МодульКассы modulKassaId. Если реквизиты не заполнить, то их необходимо будет ввести вручную на внешнем платежном терминале.
На данном этапе сформированные данные отправляются на регистрацию в ККТ. Если был указан безналичный расчет, то перед регистрацией осуществляется прием оплаты по карте - выполнение платежной транзакции - и только в случае успеха происходит регистрация.
- C помощью
CheckManager
сформируйтеIntent
для отправки в приложение МодульКасса. Запустите активити черезstartActivityForResult()
для запуска процесса фискализации чека.
startActivityForResult(
modulKassaClient.checkManager().createPrintCheckIntent(demoCheck),
PRINT_CHECK_REQUEST_CODE
)
- Обработайте результат стандартным для Android способом.
- Если операция прошла успешно, в ответ придет чек типа Check с заполненными фискальными данными и результатом платежной транзакции.
- В случае ошибки, в ответ придет объект типа ResultError с описанием ошибки, ее типом и причиной. С версии 8.40.0 добавлена обработка нового типа ошибок - ANOTHER_REQUEST_IN_PROGRESS. Данная ошибка означает, что запрос на обработку следующего чека поступил во время обработки предыдущего, и нужно дождаться ответа на предыдущий запрос.
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when (requestCode) {
PRINT_CHECK_REQUEST_CODE -> handlePrintCheckAnswer(resultCode, data)
}
}
private fun handlePrintCheckAnswer(resultCode: Int, data: Intent?) {
if (resultCode == Activity.RESULT_OK) {
val printedCheck = modulKassaClient.checkManager().parsePrintCheckSuccess(data ?: Intent())
} else {
val resultError = modulKassaClient.checkManager().parsePrintCheckError(data ?: Intent())
}
}