---
# System prepended metadata

title: База знаний по проекту Честный знак

---

# База знаний по проекту Честный знак

## Ссылки на ресурсы
* https://честныйзнак.рф
* https://www.gs1ru.org - Ассоциация автоматической идентификации GS1
* https://markirovka.ru/
* https://markirovka.sandbox.crptech.ru/login-kep - Тестовый контур «Песочница» 
* https://markirovka.ru/community/beer_producers/korobochnoe-reshenie-dlya-markirovki-hi-mark-lite - страница по HiMark
* https://up-line.online/ - оф.сайт HiMark
* https://mercury.vetrf.ru/ - оф. сайт Меркурий (система государственного ветеринарного надзора)
* https://ru.wikipedia.org/wiki/Меркурий_(информационная_система) - статья по ФГИС Меркурий

## Материалы по теме
* https://habr.com/ru/post/550466/ - описан хороший подробный план по внедрению маркировки на производстве и недостатки модуля 1С
* https://habr.com/ru/search/?target_type=posts&order=relevance&q=%5Bчестный%20знак%5D - поиск по тегу ЧЗ

## Термины и аббревиатуры
* ВСД - ветеринарно-сопроводительный документ
* ГИС МТ - Государственная информационная система мониторинга товаров в России "Честный знак".
* Код маркировки (КМ) - Уникальный номер, который состоит из кода идентификации и кода проверки. По нему можно получить всю информацию о продукте и его движении. Формирует ГИС МТ.
* Код идентификации (КИ) - Уникальный номер одного экземпляра товара. Его формирует ГИС МТ.
* Код проверки (КП) - Уникальный номер, который позволяет выявить подделку кода идентификации. Его формирует ГИС МТ.
* Модельный ряд - состав однородной продукции по видам, сортам и маркам. Может быть связан с ОКП. Например, по ОКП: 04.04 - Молоко и сливки с содержанием жира более 6%.
* ОКП - общероссийский классификатор продукции, это единая система классификации товаров, которая используется для стандартизации и упрощения процесса обработки информации о продукции.
* ПЛ - производственная линия, комплекс оборудования и технологических процессов, предназначенных для приема, переработки и упаковки молока и молочных продуктов.
* ПЛК - программируемый логический контроллер, управляет датчиками, например, датчик обраковщика (даёт сигнал отбраковщику скинуть продукты) и тд.
* Средство идентификации (СИ) - Двумерный штрихкод в формате DataMatrix, который наносят на товар или упаковку.
* Станция управления заказами (СУЗ) - подмодуль ГИС МТ
* ЦРПТ - Центр развития перспективных технологий, в частности они создали Честный знак.
* DataMatrix - двумерный графический код, похож на QR-код, в отличие от него может хранить больше информации, более криптостойкий, и имеет запас устойчивости до 30 % (если будет повреждён, например, при неправильной траспортировке)
* GTIN (Global Trade Item Number) - Идентификационный номер товара, который получают на сайте ГС1 РУС для каждого модельного ряда.
* остальное https://sbis.ru/help/data_exchange/marking/dictionary

## Прообразы разрабатываемой системы
* личный кабинет на сайте ГИС МТ (вероятно, избыточный функционал - нам не нужны СЭД, чеки и др.функции)
* ПО HiMark (в данный момент используется на УГМЗ)

## Нефункциональные требования
* обеспечение нанесения и считывания маркировки, а также отбраковки на скорости 6 тыс. ед. продукции в час (линия ПЭТ)
* с системой будут работать несколько пользователей, имеющих разные роли 

## Функции системы
1) Осуществление заказов на эмиссию кодов маркировки.
2) Предоставление эмитированных кодов маркировки для нанесения на продукцию.
3) Верификацию нанесения КМ.
4) Агрегацию готовой, упакованной продукции с нанесёнными средствами идентификации (СИ).
5) Списание бракованной продукции.

1) Получение заказов и предоставление эмитированных кодов маркировки.
2) Получение уведомлений об использовании (нанесении) кодов маркировки и регистрация статуса кодов маркировки в Системе товарной группы (Честный знак).
3) Получение уведомлений об агрегации кодов маркировки и регистрация агрегации упакованной продукции в Системе товарной группы.
4) Получение уведомлений об отбраковки продукции и регистрация отбракованной продукции в Системе товарной группы.

п. 1.1 Руководства программиста

## Диаграмма развёртывания (структурная схема)
![](https://i.imgur.com/fBbPnTp.png)

## Диаграмма состояний КМ
![](https://hackmd.io/_uploads/BkCHBo1B2.png)



## Алгоритм валидации КМ
![](https://i.imgur.com/lj4GMR6.png)



## Алгоритм проверки на дубликаты
1. Если код имеет один из статусов (Expired, Invalid, Valid), то создаём запись сущности Reject (Брак), причина "дубликат".




### Примечания
* Модуль диспетчеризации запросов может быть реализован как стандартный брокер сообщений (message broker - RabbitMQ)
* Модуль синхронизации данных - можно реализовать с помощью стандартных механизмов PostgreSQL
* Модуль интеграции с ЧЗ и АРМ администратора взаимодействуют через стандартный брокер сообщений (message broker - RabbitMQ)
* Модуль диспетчеризации и АРМ оператора взаимодействуют через стандартный брокер сообщений (message broker - RabbitMQ)
* Модуль диспетчеризации взаимодействует с модулями аппаратной части через соответствующие протоколы (TCP и тд)

# Режимы запуска

## Режим отладки:

* запуск установки,
* коды печатаются,
* отбраковщик не пропускает товар.
* Мы не фиксируем эти коды.

Интерфейс - либо отдельной кнопкой, либо галочку.

Также есть переключатель на физическом уровне. 

Если не совпадает логический и физический режимы, то выводим сообщение “…”.

## Режим работа:

* наносим коды
* считываем коды
* отбраковщик работает

С возможностью аварийного стопа. В этом случае останавливаем производственную линию.

## Структура кода маркировки для молочной продукции
Длина кода (включая символы GS) - 31

Потребительская и групповая упаковка
• AI01–2
• Код товара – 14
• AI21–2
• Серийный номер – 1 символ код страны + 5 символов S/N + 1 символ <GS>
• AI93–2
• Код проверки – 4
    
Состав кодов маркировки DataMatrix молочных продуктов
Расшифровка кода маркировки молока и молочной продукции это процедура идентификации. Идентификация молочной продукции происходит по четырем группам данных AI (идентификаторы применения) в соответствии со стандартом GS1 DataMatrix.

* В начале каждого кода маркировки всегда присутствует символ GS1 DataMatrix FNC1 (ASCll 232).

* Первая группа. Al (01) состоит из 14 цифр и содержит код товара.
* Вторая группа. Al (21) состоит из 6 символов и содержит индивидуальный серийный номер упаковки товара. Заканчивается разделителем FNC1 (ASCII 29).
* Третья группа (является опциональной). 
** Если срок хранения продукта более 72 часов, то используется Al (17), состоящий из 6 цифр: ГГММДД.
** Если срок хранения продукта менее 72 часов, то используется Al (73), состоящий из 10 цифр: ГГММДДЧЧММ.
* Четвертая группа. Al (93) состоит из 4-х символов и содержит код проверки.
    
## ПО
Программа для настройки веб-камеры: AMCap https://amcap.ru.uptodown.com/windows/download
    


## Материалы
* Описание структуры кодов датаматрикс: https://честныйзнак.рф/upload/Структура%20DataMatrix.pdf
* Состав кодов маркировки DataMatrix молочных продуктов: https://getmark.ru/blog/o-markirovke/kod-markirovki-molochnoj-produkcii-chto-soderzhit-rasshifrovka/
* Работа с модулём ввода-вывода https://owen-prom.ru/files/re_mk210-301-311_1-ru-22947-1.15.pdf
    
## Delta камера
* Ip-адрес:192.168.0.210
* логин, пароль от веб клиента: admin, admin
    
# Сканирование детали
размер кадра в мм:
* по горизонтали 57.5
* по вертикали 38 мм
    
    
## Состав модулей системы
* модуль связи с ГИС МТ (должен выполнятся на Windows)
* АРМ администратора
* модуль интеграции с аппаратным блоком ввода-вывода дискретных сигналов (для работы с датчиком наличия продукта на линии и отбраковщиком)
* модуль получения считанных КМ с камеры
* модуль печати КМ на принтере
* АРМ оператора
    
## Схема получения авторизационного токена ГИС МТ
* отправляется GET запрос на URL https://sandbox.crptech.ru/api/v3/auth/cert/key, в ответ в формате json приходят 2 параметра: uuid и data
Пример:
{
    "uuid": "4565e659-87c7-466e-b102-a50bc1bda44f",
    "data": "SHZNTAOGVKXZPIPCZHDRMLUUTFVQSP"
}
* Далее необходимо подписать полученную строку "data" электронной цифровой подписью и закодировать в base64.
* Отправить POST запрос на URL https://sandbox.crptech.ru/api/v3/auth/cert/{omsId}
Примечание: omsId является идентификатором соединения, получить его можно на сайте Честного знака. В меню "Управление заказами" выбирается подпункт "Устройства", создаётся новое и копируется свойство "идентификатор соединения"
![](https://i.imgur.com/LaZle16.png)
В headers запроса Content-Type устанавливается на "application/json". в body в формате json отправляется "uuid" из прошлого запроса без изменений и "data", после подписания ЭЦП в кодировке base64.
![](https://i.imgur.com/OntJ4mf.png)
Примечание: в документации указывается время жизни токена 10 часов. Ссылка на форум с подробностями на 1С: https://infostart.ru/1c/articles/1506206/
* В дальнейшем полученный токен (Пример: "52cd4633-4f18-4580-bb4b-6b1bc45d270d") помещается в Header запроса под ключом "ClientToken". Так же некоторые запросы требуют отсоединенной электронной цифровой подписи в формате base64. Можно подписать пустую строку ЭЦП и положить в заголовок запроса под ключом "X-Signature".
![](https://i.imgur.com/XGU5ORY.png)
Проверить подключение к api можно GET запросом https://suz.sandbox.crptech.ru/api/v3/ping?omsId=1bcc4b12-92e6-492d-b359-b3650a979888, требует передачи clientToken в заголовке и omsId в строке URL.
    
    
## Основные запросы к ГИС МТ
* Создать заказ на эмиссию кодов маркировки (См. пункт 4.4.1).
* Получить статус массива КМ из заказа (См. пункт 4.4.2).
* Получить КМ из заказа (См. пункт 4.4.3).
* Отправить отчёт об использовании КМ (См. пункт 4.4.11).
* Отправить отчёт об агрегации КМ (См. пункт 4.4.10).
* Отправить отчёт о выбытии/отбраковке КМ (См. пункт 4.4.2)


## Основные коды ошибок, возвращаются из модуля интеграции в АРМ Администратора


| error_code | error_description |
| -------- | -------- |
| 1     | Честный знак не отвечает     |
| 2     | Честный знак вернул ошибку, {текст ошибки от ЧЗ}, {код ошибки от ЧЗ}     |
| 3     | Ошибка в системе ({stacktrace})     |
| 4     | Дата производства задания {дата задания} (номер={id}) не равна текущей дате {текущая дата}    |
| 5     | Аварийная остановка производственной линии (номер={id}), причина {причина}|
    

# Протокол взаимодействия между модулем интеграции и АРМ администратора

## Соглашения

    * Все запросы из АРМ в модуль пишутся в очередь с суффиксом _requests
    * Все запросы из модуля в АРМ пишутся в очередь с суффиксом _responses
    * Если ошибка запроса в ЧЗ, то делаем 3 попытки с таймаутом в 1 сек., пишем ошибку в лог - текущую дату-время в UTC, сообщение и stacktrace ошибки (если есть)
    * Если 3 попытки запроса не удались, то пишем соответствующий error_code и error_description 
    
## Создание заказа на эмиссию КМ
    
### Формат сообщения в очередь create_order_requests:
    {"gtin": 04627189191006, "count": 5}
    
### Формат сообщения в очередь create_order_responses:
    {'orderId': 'a-b-c', "gtin": 04627189191006, "count": 5}

## Обновление bufferStatus заказа КМ
    
### Формат сообщения в очередь update_order_buffer_status_requests:
    * orderId
    
### Формат сообщения в очередь update_order_buffer_status_responses:
    [{'orderId': 'a-b-c', 'leftInBuffer': 1, 'totalCodes': 1, 'poolsExhausted': False, 'unavailableCodes': 0, 'availableCodes': 1, 'gtin': '04627189191006', 'bufferStatus': 'ACTIVE', 'totalPassed': 0, 'expiredDate': 1683234003213}]
    
## Получение массива КМ из заказа
    
### Формат сообщения в очередь codes_requests:
    * orderId, gtin, count
    
### Формат сообщения в очередь codes_responses:
    ["codes": ["0104627189191006215CX/Fe 9365o5","0104627189191006215sVYzI 93LH+k"]

## Синхронизация национального каталога
    
### Формат сообщения в очередь national_catalogue_requests:
    * любое сообщение
    
### Формат сообщения в очередь national_catalogue_responses: 
    *{
        "goods": [
            {
                "good_id": 226269816,
                "gtin": "4627189191006",
                "good_name": "Молоко питьевое стерилизованное (для тестирования интеграции)",
                "tnved": "0401",
                "brand_name": "Test",
                "good_status": "published",
                "good_detailed_status": [
                    "published"
                ],
                "updated_date": "2023-04-01 13:20:37"
            },
            {
                "good_id": 229176570,
                "gtin": "4627189191020",
                "good_name": "Молоко питьевое пастеризованное (для тестирования интеграции)",
                "tnved": "0401",
                "brand_name": "Test",
                "good_status": "published",
                "good_detailed_status": [
                    "published"
                ],
                "updated_date": "2023-04-03 23:20:53"
            }
        ]
    }
    
## Получаем информацию о товаре
**срок годности и полный ТН ВЭД**
### Формат сообщения в очередь product_requests:
* gtin: string
    
### Формат сообщения в очередь product_responses:    
{
gtin: string
expDateValue: string
expDateType: string (ч., сут., нед., мес.)
tnved: string
}

## Синхронизация СУЗ
    
### Формат сообщения в очередь orders_requests:
    * updatedAt (null, если ни разу не обновляли)
    
### Формат сообщения в очередь orders_responses: 
    * ordersIds - массив ид заказов КМ
    
## Полная синхронизация СУЗ
    
### Формат сообщения в очередь full_oms_sync_requests:
    * updatedAt (null, если ни разу не обновляли)
    
### Формат сообщения в очередь full_oms_sync_responses: 
    * Массив объектов
    [{
    "orderId": "123", // ид заказа
    "codes": ["a", "b", "c"] // массив кодов
    }]
    
    
## Отправляем отчёт о нанесении
### Формат сообщения в очередь marking_reports_requests
    * codes - массив КМ
    * expDate - Дата окончания срока годности продукции (срок хранения более 72 часов).
    Допустимые форматы: dd.MM.yyyy / yyMMdd (Пример: 03.04.2023 / 230403)

    
### Формат сообщения в очередь marking_reports_responses
    * reportId - Идентификатор отчёта из ЧЗ, пример "ca71216d-6bc5-4604-8ceb-ed896888abe1"
    * codes - массив КМ
    * expDate - Дата окончания срока годности продукции (срок хранения более 72 часов).
    
## Отправляем отчёт о вводе в оборот
### Формат сообщения в очередь turnover_reports_requests
    {        
             "task_id": "task123456", # Идентификатор задания на производство
             "participant_inn": "027816074958", # ИНН участника оборота товаров (аккаунт Честного Знака)
             "producer_inn": "027816074958", # ИНН производителя
             "owner_inn": "027816074958", # ИНН владельца товара
             "production_date": "2023-04-21", # дата производства
             "products": [ # массив продуктов (каждый код маркировки передается отдельно)
             {
               	"uit_code": "0104627189191020215P<lqR", # код маркировки без криптохвоста (24-значный)
               	"production_date": "2023-04-21", # дата производства конкретного продукта (делать одинаковой с общей production_date)
               	"tnved_code": "0401201109", # 10-значный ТН ВЭД код (берется из информации о продукте)
               	"vsd_number": "1AAA-1A11-AAAA-11AA-A1A1-1AAA-AA11-1111" # GUID ветеринарного сопроводительного сертификата (берется из ФГИС Меркурий)
             },
             {
               	"uit_code": "0104627189191020215'V/RO",
             	"production_date": "2023-04-21",
             	"tnved_code": "0401201109",
             	"vsd_number": "1AAA-1A11-AAAA-11AA-A1A1-1AAA-AA11-1111"    
             }
            ]
    }
                            
### Формат сообщения в очередь turnover_reports_responses
    {
    	"reportId": "82da88ec-2984-4837-a658-704dca8921c4",
    	"owner_inn": "027816074958",
    	"producer_inn": "027816074958",
    	"participant_inn": "027816074958",
    	"production_date": "2023-04-21",
    	"products":
            [
    	    {
    	    	"uit_code": "0104627189191020215P<lqR",
    	    	"production_date": "2023-04-21",
    	    	"tnved_code": "0401201109",
    	    	"vsd_number": "1AAA-1A11-AAAA-11AA-A1A1-1AAA-AA11-1111"},
    	    {
    	        "uit_code": "0104627189191020215\'V/RO",
    	        "production_date": "2023-04-21",
    	        "tnved_code": "0401201109",
    	        "vsd_number": "1AAA-1A11-AAAA-11AA-A1A1-1AAA-AA11-1111"
    	    }
    	], 
    }
    
## Отправляем отчёт об отбраковке
### Формат сообщения в очередь invalidation_reports_requests
    * codes - массив КМ
### Формат сообщения в очередь invalidation_reports_responses
    * reportId - Идентификатор отчёта из ЧЗ, пример "ca71216d-6bc5-4604-8ceb-ed896888abe1"
    * codes - массив КМ
    
    
    
## Обновление статусов отчётов (отчёт о нанесении)
### Формат сообщения в очередь update_report_status_requests
reportId (пример: b8432625-b2fa-4a08-8d09-8779f70fcdf7)


### Формат сообщения в очередь update_report_status_responses
{
    "omsId": "9c427558-0d14-4cf4-9a16-b98aedf4cb88",
    "reportId": "b8432625-b2fa-4a08-8d09-8779f70fcdf7",
    "reportStatus": "FAILED"
}
    
## Обновление статусов документов (отчёт о вводе в оборот)
### Формат сообщения в очередь update_document_status_requests
{
     "document_id": "82da88ec-2984-4837-a658-704dca8921c4"   
}


### Формат сообщения в очередь update_document_status_responses
    {
     "document_id": "82da88ec-2984-4837-a658-704dca8921c4",
     "document_status": "CHECKED_NOT_OK",
     "downloadDesc": "66: Одно или несколько значений поля \"Идентификатор ВСД\" [1AAA-1A11-AAAA-11AA-A1A1-1AAA-AA11-1111] не найдено в базе данных ФГИС \"ВетИС\".",
    },
    Значение downloadDesc может быть пустым, если при обработке отчёта не будет ошибок при проверке Честным Знаком.
    
    

## Отправляем отчёт о балансе
### Формат сообщения в очередь balance_requests
{
 "productGroupId": 8
}
P.S.(8 - молочная продукция)
### Формат сообщения в очередь balance_responses
{
"balance": 9760, (в копейках)
"contractId": 1564095,
"organisationId": 11001530518,
"productGroupId": 8
}

    
    
# Протокол взаимодействия между модулем диспетчеризации и АРМ оператора

## Запуск задания на нанесение кодов

### Формат сообщения в очередь operation_requests:
* event: "start_line"
* GTIN
* expiredDate: date | null
* taskId - long, номер текущего задания
* plc: 
    * productSensorAddress (int, адрес датчика продукта)
    * redLightAddress (int, адрес красного цвета светофора)
    * yellowLightAddress (int, адрес жёлтого цвета светофора)
    * greenLightAddress (int, адрес зелёного цвета светофора)
    * rejectorAddress (int, адрес отбраковщика)
    * emergencyStopAddress (int, адрес аварийного стопа)
    * cameraTimeout (int, время задержки до съёмки камеры)
    * processTimeout (int, время задержки до обработки)
    * rejectTimeout (int, задержка перед отбраковкой)
    * rejectImpulseLength (int, длина импульса на отбраковку, в миллисек., задаёт силу удара, дистанция отлёта продукта)
    * etikerAddress (int, адрес датчика этикеровщика)
    * IP* (string)
    * port* (int)
* camera:
    * IP
    * port
* codes: [
  {
    code,
    status
  }
]
* rejector:
    * invertLogic (bool, инвертирование логики отбраковщика)


    
### Формат сообщения в очередь operation_responses:
**Пока не используем**
* event: "start_line"

                   
## Остановка заданий
### Формат сообщения в очередь operation_requests
* event: "stop_line"
* plc: 
    * productSensorAddress (int, адрес датчика продукта)
    * redLightAddress (int, адрес красного цвета светофора)
    * yellowLightAddress (int, адрес жёлтого цвета светофора)
    * greenLightAddress (int, адрес зелёного цвета светофора)
    * rejectorAddress (int, адрес отбраковщика)
    * emergencyStopAddress (int, адрес аварийного стопа)
    * cameraTimeout (int, время задержки до съёмки камеры)
    * processTimeout (int, время задержки до обработки)
    * rejectTimeout (int, задержка перед отбраковкой)
    * rejectImpulseLength (int, длина импульса на отбраковку, в миллисек., задаёт силу удара, дистанция отлёта продукта)
    * etikerAddress (int, адрес датчика этикеровщика)
    * IP* (string)
    * port* (int)                
                    


### Формат сообщения в очередь operation_responses
**Пока не используем**
                
* event: "stop_line"
* updatedAt: datetime (дата-время остановки)
* ok: bool
* error_code: int | null 
* error_description: string | null
                    
## Остановка заданий
### Формат сообщения в очередь operation_responses
event: "emergency_stop_line"
                    
## Валидация
### Формат сообщения в очередь validate_codes_responses
* rejected: bool
* code: bytea | null
* updatedAt: datetime
* cause: enum (string)
* taskId: long
                    
## Возвращаем коды в режиме отладки
### Формат сообщения в очередь debug_codes_responses
* code: bytea | null
* updatedAt: datetime

                    
## Наладка
### Формат сообщения в очередь operation_requests
event: "debug"

### Формат сообщения в очередь operation_responses
**Пока не используем**
* event: "debug"
* updatedAt: datetime (дата-время наладки)
* ok: bool
* error_code: int | null 
* error_description: string | null

# Структура базы данных

## Соглашения
* с помощью * отмечены обязательные поля
* название БД - milk_factory_db

## Task Задание:

* productLine - внешний ключ на ProductionLine
* product - внешний ключ на Product 
* number* - уникальный номер
* mcCount - кол-во КМ (в коробе)
* createdAt - дата-время создания задания (заполняется автоматически)
* startedAt - дата-время фактического начала выполнения задания
* finishedAt - дата-время фактического окончания выполнения задания
* duration - продолжительность выполнения задания, в сек.
* veterinaryAccompanyingDocument - ветеринарный сопроводительный документ, ВСД
* status - enum:
    * New (Новая, по умолчанию)
    * Started (В работе)
    * Finished (Закрыта)
* productionDate* - дата производства
* packingDate* - дата упаковки (дата нанесения)
* planCount - плановое количество
* factCount - фактическое количество



## Order (Заказ)
* gtin (string)
* count (long)
* createAt (date)
* bufferStatus CREATED("Создан"),
    PENDING("Обрабатывается"),
    ACTIVE("Создан"),
    EXHAUSTED("Закончились коды"),
    REJECTED("Не доступен"),
    CLOSED("Закрыт")
* serviceProvider - (many to one) связь с сервис-провайдером
* expiredDate - дата окончания срока годности кодов маркировки

## Product (Продукт)
* brand (товарный знак)
* category (многие к 1 на Category)
* GTIN (например, 04675093352013, уникален)
* threshold count (пороговое значение)
* mcResiduals (остаток КМ)
* name (название)
* expDateValue (string, продолжительность жизни продукта)
* expDateType (enum string, единица измерения продолжительности жизни продукта)
    * HOUR (ч. в интеграторе)
    * DAY (сут. в интеграторе)
    * WEEK (нед. в интеграторе)
    * MONTH (мес. в интеграторе)
                    
## Category
* title* (подкатегория, пока строка “молоко в первичных упаковках нетто-объемом не более 0,35 л, для детского питания”)
* description
* tnved* (ТНВЭД, например, 0401201101)
    
## Отчёт Report (отчёт о нанесении)
* reportId* (получаем с ЧЗ)
* createdAt* (datetime)
* task* (many to one на Task)
* status* (CREATED (наш статус), DRAFT, PENDING, READY_TO_SEND, REJECTED, SENT, CHECK, SUCCESS, FAILED, PARTIALLY)
![](https://i.imgur.com/eglpglg.png)
 
## Документ Document (отчёт о вводе в оборот)
* documentId* (получаем с ЧЗ)
* createdAt* (datetime)
* task* (many to one на Task)
* status* (CREATED (наш статус), IN_PROGRESS, CHECKED_OK, CHECKED_NOT_OK, PROCESSING_ERROR, PARSE_ERROR, WAIT_FOR_CONTINUATION)
![](https://i.imgur.com/35n362i.png)
                    
## ProductionLine
см. https://github.com/energovision/milk-factory-admin/tree/main/common-jpa/src/main/java/com/energovision/entity



## MarkingCode (Коды маркировки)
* order - many to one на Order
* task - many to one на Task
* report - many to one на Report
* document - many to one на Report
* code - массив байт 
* status* (Emitted (Получен), Ready_for_production (Добавлен в задание на производство), Printing (Отправлен на печать), Approved (Отсканирован), Expired (Просрочен), Invalid (Отбракован), Valid (Валиден), Marked (Отправлен в отчёт о нанесении), Turnovered (Введён в оборот)), см. https://hackmd.io/NUbsjS2CSSaE8YX9iiwKdQ?view#Диаграмма-состояний-КМ
* createdAt (datetime, автоматически заполняем по текущей дате-времени)
* ...
                    
## DebugMarkingCode (Коды маркировки в режиме отладки)
**нужны только для того, чтобы их выводить в режиме реального времени**
* code - массив байт
* updatedAt - datetime


## ServiceProvider (Сервис провайдер)
* UUID - String(36)
    
## Камера Camera
* IP*
* port*
                    
## Programmable Logic Controller (программируемый логический контроллер)
* productSensorAddress (int, адрес датчика продукта)
* redLightAddress (int, адрес красного цвета светофора)
* yellowLightAddress (int, адрес жёлтого цвета светофора)
* greenLightAddress (int, адрес зелёного цвета светофора)
* rejectorAddress (int, адрес отбраковщика)
* emergencyStopAddress (int, адрес аварийного стопа)
* cameraTimeout (int, время задержки до съёмки камеры)
* processTimeout (int, время задержки до обработки)
* rejectTimeout (int, задержка перед отбраковкой)
* rejectImpulseLength (int, длина импульса на отбраковку, в миллисек., задаёт силу удара, дистанция отлёта продукта)
* IP* (string)
* port* (int)
* productionLine (1 к 1, производственная линия)
                    

## Reject (Брак)
* code* - многие к одному к сущности MarkingCode
* cause* - enum (string, причина отбраковки)
  * GTIN (некорректный GTIN)
  * Doubling (дублирование)
  * NotRead (не считан)
  * Expired (просрочен)
* createdAt* (когда создан, заполняется автоматически)
                    
    
## Соответствие статусов КМ и типов отчётов
| Статус КМ | Тип отчёта |
| -------- | -------- |
| Введён в оборот     | Ввод в оборот     |
| Нанесён     | Нанесение     |
| Недействителен     | Отбраковка     |

                    
## Конфиг АРМ оператора
* productionLine
    * id (ид производственной линии)
* plc 
    * productSensorAddress (int, адрес датчика продукта)
    * redLightAddress (int, адрес красного цвета светофора)
    * yellowLightAddress (int, адрес жёлтого цвета светофора)
    * greenLightAddress (int, адрес зелёного цвета светофора)
    * rejectorAddress (int, адрес отбраковщика)
    * emergencyStopAddress (int, адрес аварийного стопа)
    * etikerAddress (int, адрес датчика этикеровщика)
    * IP (string)
    * port (int)
* camera
    * IP 
    * port
* rejector:
    * invertLogic (bool, инвертирование логики отбраковщика)