Разделение чека на печатные группы

Каждый раз перед печатью чека покупки, продажи или возврата смарт-терминал рассылает событие PrintGroupRequiredEvent. Обрабатывая это событие, приложения могут разделить соответствующий чек на несколько документов (как фискальных, так и нефискальных). Также, вы можете выбирать какие данные будет содержать тот или иной документ. Например, вы можете добавить в один документ имя и ИНН покупателя, а в другой нет.

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

При этом, если на смарт-терминале установлено несколько приложений, которые могут обработать событие PrintGroupRequiredEvent, пользователь каждый раз вручную выбирает необходимое приложение.

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

Схема разделения чека

Получение события

Создайте службу, которая будет обрабатывать событие, например, SplitReceiptWithPrintGroupsService.

В манифесте приложения, в intent-фильтре службы, укажите событие печати чека:

<service
    android:name=".SplitReceiptWithPrintGroupsService"
    android:enabled="true"
    android:exported="true">
    <intent-filter>
        <!-- будет напечатан чек продажи -->
        <action android:name="evo.v2.receipt.sell.printGroup.REQUIRED" />
        <!-- будет напечатан чек возврата -->
        <action android:name="evo.v2.receipt.payback.printGroup.REQUIRED" />
        <!-- будет напечатан чек покупки -->
        <action android:name="evo.v2.receipt.buy.printGroup.REQUIRED" />
    </intent-filter>
</service>

Обработка события

Для обработки события необходимо использовать метод call(@NonNull String action, @NonNull PaymentSelectedEvent event, @NonNull Callback callback) обработчика PrintGroupRequiredEventProcessor. Методы функции callback, которая передаётся в качестве параметра метода call(), позволяют сохранять результат обработки события (callback.onResult()), запускать операции (callback.startActivity()), а также пропускать обработку события (( callback.skip())) и обрабатывать ошибки (методы callback.onError()).

В результате обработки события PrintGroupRequiredEventResult, который передаётся в качестве параметра метода callback.onResult(), требуется указать список необходимых печатных групп (объекты SetPrintGroup). Каждой из групп соответствует список позиций и платежей, которые передаются в качестве параметров объекта SetPrintGroup.

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

Чтобы обработать событие разделения чека:

  1. Унаследуйте службу SplitReceiptWithPrintGroupsService от класса IntegrationService.
  2. Переопределите метод createProcessors().

    Метод возвращает в смарт терминал коллекцию пар “Событие”:”Обработчик события” (Map<String, ActionProcessor>).

  3. Создайте обработчик события PrintGroupRequiredEvent с помощью класса PrintGroupRequiredEventProcessor.
  4. Используйте методы функции обратного вызова callback, чтобы сохранить данные о результате обработки события (PrintGroupRequiredEventResult).
  5. Сохраните событие и его обработчик в коллекции и верните её в смарт-терминал.

Смарт-терминал создаст необходимые печатные группы в чеке и напечатает те, чей параметр shouldPrintReceipt задан как true.

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

public class SplitReceiptWithPrintGroupsService extends IntegrationService {
    @Nullable
    @Override
    protected Map<String, ActionProcessor> createProcessors() {
        //Создаём реквизиты покупателей, которые участвуют в приобретении товара.
        Purchaser firstLegalEntity = new Purchaser(
                //Наименование покупателя, например, название организации. Данные сохраняются в теге 1227 фискального документа.
                "Legal Entity #1",
                //Номер документа покупателя, например, ИНН или номер паспорта иностранного гражданина. Данные сохраняются в теге 1228 фискального документа.
                "1",
                //Тип покупателя, например, юр. лицо. Не сохраняется в фискальном документе.
                PurchaserType.LEGAL_ENTITY);
        Purchaser secondLegalEntity = new Purchaser("Legal Entity #2", "2", PurchaserType.LEGAL_ENTITY);
        Purchaser thirdLegalEntity = new Purchaser("Legal Entity #3", "3", PurchaserType.LEGAL_ENTITY);

        //Создаём печатные группы (чеки) для каждого покупателя.
        PrintGroup firstReceipt = new PrintGroup(
                //Идентификатор печатной группы (чека покупателя).
                "Print group identifier",
                //Тип чека, например, кассовый чек.
                PrintGroup.Type.CASH_RECEIPT,
                //Наименование покупателя.
                "OOO Vector",
                //ИНН покупателя.
                "012345678912",
                //Адрес покупателя.
                "12, 3k2, Dark street, Nsk, Russia",
                /*
                Система налогообложения, которая применялась при расчёте.
                Смарт-терминал печатает чеки с указанной системой налогообложения, если она попадает в список разрешённых систем. В противном случае смарт-терминал выбирает систему налогообложения, заданную по умолчанию.
                */
                TaxationSystem.COMMON,
                //Указывает на необходимость печати чека.
                true,
                //Реквизиты покупателя.
                firstLegalEntity);
        PrintGroup secondReceipt = new PrintGroup("Print group identifier", PrintGroup.Type.CASH_RECEIPT, "OOO Vector", "012345678912", "12, 3k2, Dark street, Nsk, Russia", TaxationSystem.COMMON, true, secondLegalEntity);
        PrintGroup thirdReceipt = new PrintGroup("Print group identifier", PrintGroup.Type.CASH_RECEIPT, "OOO Vector", "012345678912", "12, 3k2, Dark street, Nsk, Russia", TaxationSystem.COMMON, true, thirdLegalEntity);

        //Списки идентификаторов позиций каждого из покупателей.
        List<String> firstPurchaserpositions = new ArrayList<>();
        firstPurchaserpositions.add("First purchaser positions");
        List<String> secondPurchaserpositions = new ArrayList<>();
        secondPurchaserpositions.add("Second purchaser positions");
        List<String> thirdPurchaserpositions = new ArrayList<>();
        secondPurchaserpositions.add("Third purchaser positions");
        
        //Списки идентификаторов платежей каждого из покупателей.
        List<String> firstPaymentPurposeId = new ArrayList<>();
        firstPaymentPurposeId.add("First purchaser payment ID");
        List<String> secondPaymentPurposeId = new ArrayList<>();
        secondPaymentPurposeId.add("Second purchaser payment ID");
        List<String> thirdPaymentPurposeId = new ArrayList<>();
        thirdPaymentPurposeId.add("Third purchaser payment ID");

        //Чеки каждого из покупателей.
        SetPrintGroup firstPrintGroup = new SetPrintGroup(firstReceipt, firstPaymentPurposeId, firstPurchaserpositions);
        SetPrintGroup secondPrintGroup = new SetPrintGroup(secondReceipt, secondPaymentPurposeId, secondPurchaserpositions);
        SetPrintGroup thirdPrintGroup = new SetPrintGroup(thirdReceipt, thirdPaymentPurposeId, thirdPurchaserpositions);
        final List<SetPrintGroup> setAllPurchaserReceipts = Arrays.asList(firstPrintGroup, secondPrintGroup, thirdPrintGroup);
        
        //Создаём обработчик события печати чеков.
        PrintGroupRequiredEventProcessor eventProcessor = new PrintGroupRequiredEventProcessor() {
            @Override
            public void call(@NonNull String action, @NonNull PrintGroupRequiredEvent event, @NonNull Callback callback) {
                /*
                Все методы функции обратного вызова могут вернуть исключение RemoteException, которое необходимо правильно обработать.
                Например, с помощью конструкции try {} catch () {}.
                 */
                try {
                    /*
                    Вы также можете воспользоваться другими методами функции обратного вызова.
                    Например, запустить операцию с помощью startActivity(Intent intent) или отреагировть на ошибку с помощью одного из методов onError().
                     */
                    callback.onResult(new PrintGroupRequiredEventResult(
                            //Добавляем дополнительные данные в чек.
                            new SetExtra(null),
                            setAllPurchaserReceipts));
                } catch (RemoteException exception) {
                    exception.printStackTrace();
                }

            }
        };

        //Создаём и возвращаем в смарт-терминал результат обработки события в виде коллекиции пар "Событие":"Обработчик события".
        Map<String, ActionProcessor> eventProcessingResult = new HashMap<>();
        eventProcessingResult.put(PrintGroupRequiredEvent.NAME_SELL_RECEIPT, eventProcessor);

        return eventProcessingResult;
    }
}

См. также