- Регистрация
- 21.07.20
- Сообщения
- 40.408
- Реакции
- 1
- Репутация
- 0
В этом году вышло сразу несколько статей о практике работы с новой системой маркировки “Честный знак”. Написаны они “айтишниками” IT-отделов компаний-участников оборота, что отражает их взгляд на ход пилотного проекта и первые дни запуска боевой системы. Например,
Мы решили, пусть и не первыми, опубликовать свой опыт и свои мысли об этом новом амбициозном проекте государства, в котором мы активно участвуем.
Может показаться, что статья — каша, но маркировка в целом такая каша и есть, очень много аспектов сходятся в одном месте.
Кратко о нас
Кому-то может показаться, что вот есть лес, в лесу дерево, на дереве жук, а на жуке живет микроб, и ниша софта для ТСД — это про микробов на жуке.
На это можно ответить, что мобильность персонала — очень крупный растущий рынок, а специальное железо с готовым софтом — это вообще будущее всего текущего железа. В конце концов, любая реально прорывная штука — это результат многих лет труда в узкой нише (
В основном продукты Клеверенс продаются с уже готовой интеграцией с учетными системами, которые (интеграции) мы сами же пишем и поддерживаем (например,
Весь софт и железо стараемся обкатывать на реальных производствах, складах, магазинах и т.д. Например, когда проект маркировки обуви только начинался поехали в Китай, чтобы обкатать бизнес-процессы, параллельно сняли
Что такое система маркировки и «Честный знак»
Грубо говоря, это государственно-частный интернет вещей на штрихкодах и RFID для тотального прослеживания движения единиц товаров.
По системе маркировки существует очень много информации, главным ресурсом является сайт «
Отношение участников рынка к маркировке
Не секрет, что отношение участников рынка к маркировке полярное. От “Россия, вперед!” и “Идея хорошая, но реализация подкачала” до “опять маленьких обижают”.
Из плюсов называется обеление рынка и контроль цепочек поставок. Из минусов — снятие с ЕНВД при торговле маркированным товаром.
Практически весь крупный бизнес за маркировку. Мелкие предприниматели, которые хотят работать красиво и в белую — тоже за маркировку, для них это конкурентное преимущество перед серыми рынками.
Претензии в основном формулируются как “снова душат малый бизнес” или “у вас столько денег и людей, могли бы сразу сделать то-то и то-то”, “бизнес-процесс такой-то не продуман”. Хотя именно на малый бизнес и его процессы были потрачены основные деньги — это сайт с личным кабинетом участника, облачный регистратор эмиссии кодов и т.п.
Отдельно стоит позиция айтишников, о ней ниже.
При этом информационный портал «Честного знака», на котором публикуется информация, сделан просто отлично. Например, где найти информацию на английском языке?
Проблемы на старте, о которых все говорили
Пока шел пилот, в системе было много багов. В основном их успели излечить до 1 июля 2020.
Обещали, что на старте будет работать лучше ЕГАИСа, и в целом правда доступность сервиса выше.
Сейчас в табаке и обуви система всегда доступна, всё отрабатывает быстро, кроме редкого выключения на технологические работы вечером на пару часов.
Но ключевая проблема на старте была в том, что “не запрягши не поедешь”, а 99% числа участников оборота (по количеству) тупо игнорировали эту систему, не регистрировались, не давали нагрузку, ждали судного дня, а потом требовали переноса сроков.
Об этой проблеме все знали, к ней готовились, но когда подошел дедлайн по обуви, всё равно случился коллапс. Некоторые УОТы кинулись выписывать себе бесплатные коды на остатки на 20 лет вперед, это в пике дало увеличение нагрузки на сервера в х40 раз. Такие игрища, конечно, даром не пройдут, потому что система цифровая и, что называется, “все ходы записаны”.
К сожалению, пострадали и пионеры маркировки — это те компании, которые с первого дня были в пилоте маркировки, добросовестно старались, но в конце тоже просили о переносе сроков.
Тут надо сказать, что государственная система — это не айфончик, чтобы с первого дня продаж вызывать восторги. И цель её создания была не в том, чтобы собирать лайки от айтишников или снимать видео-обзоры по типу “вот когда выйдет, тогда и посмотрю, решу для себя, надо ли покупать”.
Почему-то люди ждут, что с первого дня система будет работать так, как будто ей уже 5 лет в продуктиве.
Вообще, если ждать по такой логике, когда всё будет идеально, то надо всё переносить на 2030й, а лучше на после покорения Марса, ага.
Позиция айтишников
В целом в проекте много разного железа и международных стандартов, что приносит классическим айтишникам одни только боль и страдания.
Айтишники — очень въедливые и умные люди, со своим мнением по любому вопросу. И никакого единого мнения по поводу маркировки, кроме претензий по работе API, в общем-то нет.
API системы меняется чаще, чем этого хотелось бы для сценария “сделал и забыл”. Но при этом считается, что в API надо надобавлять еще кучу методов для работы с групповыми упаковками (агрегатами), для упрощенной авторизации и т.п., но это опять означает изменение API.
Мы сами айтишники, и у нас такая же двойная позиция, что в API не хватает методов, но при этом API меняется слишком часто. Тут, как говорится, “
Технические аспекты маркировки
Технические проблемы, с которыми сталкиваются айтишники, в основном сводятся к следующему списку:
Посмотрите, тут и Java, и Reactive (RxJava), и Spring и даже Netflix:
Чтобы составить собственное мнение можно почитать
Авторизация
Авторизация в ИС МП происходит в 2 этапа.
Сначала нужно запросить некий псевдослучайный “ключ”, который нужно подписать и отправить на урл “/api/v3/auth/cert/“ (причем на момент написания этого материала в конце url обязательно должен был стоять слэш “/“, иначе не работало, что выглядит странно).
Получение “ключа” происходит так (нужно подставить нужный хост, их много разных, в зависимости от того, песочница это или боевой, одежда или что-то другое):
// получаем на /api/v3/auth/cert/key “ключ” и данные, необходимые для авторизации
var uri1 = new Uri("/api/v3/auth/cert/key")
var randomDataResponse = REST.Invoke(uri1, "GET", timeout);
Затем нужно подписать этот псевдослучайный “ключ” при помощи выбранного КЭП и отправить в ГИС МТ, чтобы получить в ответ авторизационный токен.
Для этого ищем сертификат КЭП по выбранному пользователем отпечатку (certificateThumb). Сертификат находится в данном случае в “Личных” локальной машины. Также контекст сертификата должен быть связан с хранилищем ключевой пары (такие сертификаты отмечены иконкой ключика в списке сертификатов в оснастке windows):
Получение сертификата в коде для формирования подписи:
X509Certificate2 cert = null;
using(store = new X509Store(StoreName.My, StoreLocation.LocalMachine))
{
store.Open(OpenFlags.ReadOnly);
cert = from c in store.Certificates where string.Compare(c.Thumbprint, certificateThumb, true) == 0 select c;
}
Подписываем таким образом:
// данные для подписи
var content = new ContentInfo(randomDataResponse.Data);
var signedCms = new SignedCms(content, false);
// настраиваем сертификат для подлиси, добавляем дату
var signer = new CmsSigner(SubjectIdentifierType.IssuerAndSerialNumber, cert);
signer.SignedAttributes.Add(new Pkcs9SigningTime(DateTime.Now));
// формируем подпись
signedCms.ComputeSignature(signer, false);
var sign = signedCms.Encode();
Подписанное CMS-сообщение (sign) — это и есть та проверочная подпись, которую нужно отправить для авторизации, предварительно преобразовав в формат Base64.
var tokenRequest = new TokenRequest();
tokenRequest.UUID = randomDataResponse.UUID;
tokenRequest.Data = Convert.ToBase64String(sign);
// получаем токен на /api/v3/auth/cert/
var uri2 = new Uri("/api/v3/auth/cert/")
var tokenResponse = REST.Invoke(uri2, "POST", tokenRequest);
В ответ приходит
К слову, отправляемые документы в дальнейшем подписываются таким же образом, только формируется так называемая “открепленная” подпись:
var signedCms = new SignedCms(content, true);
Вспомогательные классы (со схемой, идентичной XSD-схемам документов из API):
///
/// Ответ на запрос GET /api/v3/auth/cert/key для авторизации.
///
public class RandomDataResponse
{
///
/// уникальный идентификатор сгенерированных случайных данных, тип string
///
[Newtonsoft.Json.JsonProperty(PropertyName = "uuid")]
public string UUID { get; set; }
///
/// случайная строка, тип string
///
[Newtonsoft.Json.JsonProperty(PropertyName = "data")]
public string Data { get; set; }
}
///
/// Данные для запроса авторизационного токена.
/// POST /api/v3/auth/cert/
///
public class TokenRequest
{
///
/// uuid - уникальный идентификатор подписанных данных из /api/v3/auth/cert/key
///
[Newtonsoft.Json.JsonProperty(PropertyName = "uuid")]
public string UUID { get; set; }
///
/// подписанные УКЭП зарегистрированного участника случайные данные в base64
///
[Newtonsoft.Json.JsonProperty(PropertyName = "data")]
public string Data { get; set; }
}
///
/// Ответ на запрос авторизационного токена.
/// POST /api/v3/auth/cert/
///
public class TokenResponse
{
///
/// Авторизационный токен в base64-строке
///
[Newtonsoft.Json.JsonProperty(PropertyName = "token")]
public string EncodedTokenBase64 { get; set; }
}
Если вам удалось авторизоваться — вы прошли небольшой квест.
Проблемы с генерацией и чтением штрихкодов
Система маркировки построена на международных стандартах, за исключением части с криптографией. Это отлично и достойно похвалы.
К сожалению, средний айтишник никаких стандартов не читает, ни про что не изучает, а сразу лепит свои велосипеды из бесплатных компонентов про генерацию штрихкодов, печать, бизнес-процессы и т.п.
Первая же трудность — распечатать штрихкод маркировки в своём дизайне. Из коробки “Честный знак” предоставляет бесплатный инструмент, но с ним никто, конечно, разбираться не стал, ведь есть “online barcode generator” и встроенные редакторы отчетов в 1С/SAP/NAV/DAX.
Засада в том, что современный штрихкод — это не просто графическое представление символов (об этом у нас выйдет отдельная статья). Поэтому сразу всплыли проблемы префиксов, разделителей, кодировок, обязательных непечатемых символов и прочее такое, про что никто знать не знал и разбираться не хотел.
Пример со спецсимволом GS (ASCII 29)
Пример со спецсимволом FNC1 (ASCII 232)
Скриншоты сделаны из приложения «
Вот кусок исходного кода «Чекмарка», который выполняет разбор штрихкода, отсканированного камерой и разобранного нашей платформой:
var km = BarcodeData.GS1;
if (km.Contains("01") && km.Contains("21"))
{
if ((km.Contains("17") || km.Contains("7003")) && !km.Contains("10"))
{
ПризнакМолока = true;
if ((km.GetValue("01").Length == 14) && (km.GetValue("21").Length == 7 ||
km.GetValue("21").Length == 13) && (km.GetValue("17").Length == 6 ||
km.Getvalue("7003").Length == 10) && (km.GetValue("93").Length == 4))
{
ЭтоМолоко = true;
MSG2 = "Является KM ЧЗ молочной продукции.";
if (km.GetValue("21").Length == 7)
MSG2 = "Является КМ ЧЗ групповой упаковки молочной продукции.";
}
else
{
// Проверка наличия группы в коллекции для отображения (EntriesRows)
// В случае отсутствия - добавляем группу с пустым содержимым
EntriesRows = ПоискАI(EntriesRows, Al = 93, BarcodeData);
MSG2Error = "Не является КМ Ч3! Имеет признаки КМ молочной продукции.";
Msg = "#N005" + Msg;
}
}
else if (km.Contains("8005") || km.Contains("93"))
{
ПризнакТабачногоБлока = true;
if (km.GetValue("01").Length == 14 && km.GetValue("21").Length == 7 &&
km.GetValue("8005").Length == 6 && km.GetValue("93").Length == 4)
{
ЭтоТабачныйБлок = true;
MSG2 = "Является КМ ЧЗ табачного блока.";
}
else
{
EntriesRows = ПоискАI(EntriesRows, AI = 8005, BarcodeData)
EntriesRows = ПоискАI(EntriesRows, Al = 93, BarcodeData)
MSG2Error = "Не является КМ Ч3! Имеет признаки КМ табачного блока.";
Msg = "#N004" + Мsg;
}
}
else if (km.Contains("92") && km.Contains("92").Length > 66)
{
ПризнакОбуви = true;
if (km.GetValue("01").Length == 14 && km.GetValue("21").Length == 13 &&
km.GetValue("91").Length == 4 && km.GetValue("92").Length == 88)
{
... (и т.п.) ...
Откуда взялись спецсимволы? Из стандарта. «Честный знак» сделали всё по стандарту, и участникам оборота товаров тоже надо было читать стандарт.
КСТАТИ: Проверку корректности содержимого DataMatrix можно произвести только с помощью сканирования камерой (даже если сканировать с ТСД, нужен доступ к камере). Потому что все сканеры штрихкодов в соответствии со стандартном не должны возвращать 1в1 то, что они считали, как минимум должны выбрасывать первый символ FNC1. В целом, сканеры могут добавлять или убирать важные символы штрихкода при сканировании, переставлять блоки местами, в зависимости от настроек, всё это мешает проверке.
Т.к. системная интеграция — это не про программы, а про людей и про то, как они пишут и читают спецификации, то наличие этих спец символов сразу привело к некоторому разногласию при обмене штрихкодами.
Например, могли, особо не вчитываясь в спецификации, добавлять в штрихкод строку из 4 символов “FNC1” вместо одного символа ASCII 232 (FNC1). А еще, при обмене между подсистемами такие символы часто фильтруются и теряются, до печати доходят уже без таких символов, при этом в обычных текстовых редакторах спец. символы часто не отображаются и люди удивляются, почему же что-то не так, если штрихкоды совпадают.
Так же, если не указывать символ FNC1 в штрихкоде, некоторое оборудование или ПО может не понять что это такое и как его разбирать, т.к. этот символ вначале штрихкода как раз указывает на то, что это формат GS1 DataMatrix.
Один из последних примеров, на котором споткнулись почти все, было появление скобок и знаков препинания в серийном номере.
Откуда в серийном номере скобки и знаки препинания? Из стандарта! Стандарт GS1 позволяет их использовать. Т.к. серийный номер в длину имеет всего 13 символов, а товаров под маркировку очень много, приходится использовать все доступные символы.
Отдельные лулзы — скобки в серийном номере. Они там разрешены стандартом, но никто их не ждал. В так называемой человеко-читаемой форме представления (HID) скобки имеют специальный смысл: они обрамляют номера значимых групп символов. Например, “(21)” означает, что дальше в строке будет идти серийный номер.
Если наивно думать, что в штрихкоде хранится просто строка символов, то в строке “(21)abcd12(3)d(1,(91)” серийным номером видится “abcd12”, а часть про “(1,” кажется вообще ошибкой.
На самом деле серийный номер тут “abcd12(3)d(1,”, а после запятой стоит нечитаемый символ GS. И дело не в том, что серийный номер должен быть 13 символов (потому что формально длина серийника в GS1 DataMatrix может быть другой, и в шинах, например, она бывает 20 символов). Дело именно в невидимом GS, который надо учитывать, и который в полях любой учетной системы не выводится, не принимается для ввода и вообще запрещен (и в обычном Блокноте его тоже не видно, не выводится, нужен Notepad++).
Наличие таких спец символов накладывает ограничение на передачу и хранение данных штрихкодов, их нужно экранировать или кодировать, например в Base64.
КСТАТИ: существует стандарт на хранение и передачу таких штрихкодов в виде строки (ISO/IEC 15424-2018), но почему-то им никто не пользуется. Данные штрихкода GS1 DataMatrix, хранимые в виде строки, должны начинаться на “]d2”.
Сейчас почти все исправили свои компоненты печати штрихкодов (наверное). Но кто вообще читает стандарты, правда?
На проверку, домашнее задание: вот эта тема, что если поле фиксированной длины, то GS вставлять не нужно, а если длина переменная, и значение поля не максимальной длины, то вставлять нужно. На самом деле это правило работает не так. Спецсимвол GS не вставляется только если AI начинается с пары цифр из этой вот таблицы:
А во всех остальных случаях вставляется. Ваш код генерации/разбора ШК работает так же?
Еще одна проблема — сканирование штрихкода маркировки ламерскими средствами типа “сканер в разрыв клавиатуры”. До маркировки самой большой проблемой было, что где-то обрезается или вставляется лишний ноль. Со введением новых кодов маркировки тулзы со сканированием выведены на совершенно новый уровень.
Зачастую это не проблемы самого сканера или его настроек, а проблемы с отсутствием опыта и понимаем принципов штрихкодирования.
Например, при подключении сканера «в разрыв клавиатуры» (или при эмуляции такого режима), а также при подключении сканера как HID-устройства, возможны проблемы с заменой одних символов в считанном штрихкоде на другие или пропадание определенных символов.
Схема подключения сканера в разрыв клавиатуры
При работе в указанных режимах сканер передаёт компьютеру не сами символы из штрихкода (sic!), а коды нажатий клавиш клавиатуры, которые нужно было бы нажать, чтобы набрать на клавиатуре символы из этого штрихкода.
При этом очевидно, что одной клавише клавиатуры может соответствовать сразу несколько возможных символов, в зависимости от языка раскладки и нажатий клавиш-модификаторов (Shift, Caps Lock, Alt и Ctrl).
Например, при нажатии на вот эту клавишу в нижней правой части клавиатуры:
Результатом может быть любой из символов ‘?’, ‘/’, ‘,’ или ‘.’, в зависимости от выбранной раскладки и использования клавиш-модификаторов. Какой конкретный введётся символ — определяется настройками клавиатуры операционной системы, а не сканером.
Именно из-за этого вместо одних серийников на кассе выбывают совершенно другие, либо код вообще “не найден”.
Кстати, этих проблем можно было бы избежать, если бы в серийный была чексумма, когда по последней цифре можно проверить, правильный ли код, правильно ли он считался/ввелся. У расчетных счетов, ИНН, номеров карт, у EAN13, у всего последняя цифра является чексуммой для проверки, чтобы люди и машины не ошибались при вводе.
Очевидно, тут понадеялись на то, что DataMatrix самопроверяемый, плюс есть криптохвост. Но одно дело весь штрихкод, самопроверяемый, и другое дело огрызок кода с серийником, который вообще могли ввести с клавиатуры.
Отдельные споры айтишников вызвал так называемый «криптохвост».
«Криптохвост» — это необходимая часть штрихкода маркировки, благодаря которой можно по симметричному ключу проверить, что серийный номер единицы товара не высосан из пальца.
Криптохвост есть только в штрихкоде и не хранится в базе маркировки, чтобы никакой хакер не мог подломить базу и печатать чужие штрихкоды.
Т.е. это своеобразная цифровая подпись. Но т.к. штрихкод не резиновый, а товаров много, то длина этой цифровой подписи небольшая, что не позволяет пользоваться открытыми для всех ключами шифрования.
Конечно, все серийные номера лежат в базе данных маркировки, но если проверять по ней в онлайне, то при любом падении интернета сразу встанут все склады и магазины.
Криптохвост призван решить эту проблему, но пока (на лето 2020 года) не заработал в полную силу.
Дело в том, что криптография российская и привязана к железкам. Но альтернативы российской крипте всё равно нет, государственная российская система не может использовать иностранную крипту, это будет
С этим столкнулись все, кто попробовал интегрироваться с API маркировки. Было очень много вопросов в чатах типа “Почему не авторизуется?”, “Как подписать?”, “Поделитесь примером!”, “Подпись сформировали но приходит отказ, почему?” и много других.
Чаще всего ошибки были банальны. Например, после подписи изменяли данные, либо терялся пробел или как-то несущественный символ, но для подписи это критично, и после отправки в API приходил отказ без объяснений, т.к. подпись не проходила проверку.
К счастью в чатах чаще всего помогали и отвечали на такие вопросы. В целом, все эти проблемы лечатся или уже были излечены к 1 июля 2020.
Что мы сами думаем о маркировке
Мы в Клеверенсе думаем, что софтовые проблемы не главное. Хуже то, что участники оборота товаров до сих пор не понимают сути изменений. Это гораздо большая проблема, чем софтверные баги.
Люди относятся к маркировке как к еще одному бухгалтерскому отчету, который можно составлять сидя у компа в 1С/SAP/NAV/DAX, корректировать, менять задним числом и т.п. Типа пользоваться будут бухгалтеры и логисты, а айтишники должны “запилить” под это нужные модули и обработки.
Главный запрос наших клиентов в том, чтобы склад/китайцы/тетямаша что-то насканировали, а потом это “корректно” загрузилось в 1С/SAP/NAV/DAX. И мы это успешно делаем.
Но это очевидная ошибка, которая вскроется, когда компании начнут сводить остатки друг с другом, а государство начнет штрафовать.
Что такое на самом деле система маркировки
Маркировка товаров — это система отражения реальных движений.
Реальные проблемы с маркировкой
Это чисто наше IMHO.
Все реальные проблемы автоматом вытекают из того, для чем на самом деле является система маркировки, а именно, системой отражения реальных движений.
Во-первых, реальный учет движений противоречит текущим принципам учета по всей цепочке, когда всё учитывается по SKU, по партии или по среднему. Задним числом сводить и исправлять — наше всё.
Учетная система в любой компании — представляет собой причесанную и исправленную сказку о том, как всё здорово получилось после 100500 созвонов, исправлений, перепроведений и вычищения ошибок.
На одной из расширенных встреч у крупного иностранного дистрибутора лекарств только после часа обсуждения главный логист, наконец, округлил глаза и сказал “это что же, разные штрихкоды у каждой пачки?”. А слова “уникальный”, “серийный номер”, “каждый экземпляр”, “всё сканировать” и т.п., видимо, пролетели мимо.
Во-вторых, реальный учет движений противоречит текущим бизнес-практикам и принципам разделения ответственности.
Даже если компания крупная и у сотрудника нет прав на правку каких-то документов — есть телефон, можно позвонить или написать тому, кто может поправить.
Или, например, документы подписываются КЭП директора каким-то низовым сотрудником, а если есть двухэтапная аутентификация, то через пересылку SMS. В системе маркировки есть блок про пользователей и их права, можно выдавать всем отдельные КЭП, но люди этого делать не спешат.
Это явная проблема, которая будет решаться предоставлением всё больших прав и инструментов учета тем простым сотрудникам, которые находятся прямо рядом с маркированным товаром.
Сверх того, правила расчета себестоимости или учета движений в учетной системе основаны на усреднениях и упрощениях типа FIFO/LIFO и средней цены. И те принципы учета, которые повсеместно десятилетиями применяются от производства до розницы, основаны на этих упрощениях и идут в разрез с реальным прослеживаем уникальных единиц.
Из-за этого на практике получается, например, что в систему маркировки товары отправляются по FIFO/LIFO, а реально отгружается то, что стояло ближе в выходу.
Это тоже решается специальным оборудованием и софтом для простых сотрудников, которые по роду своей работы не могут сидеть у компа.
Еще одна проблема — это попытка “натянуть сову на глобус” и втащить коды маркировки во все стандартные документы ERP, чтобы там их видел бухгалтер, логист или ответственный менеджер.
Хотя смотреть ему на них не за чем, сделать он с ними ничего не может.
И правда, ну как может бухгалтер или менеджер, глядя в монитор может понять, что там вчера насканировал склад, и почему тут выделенные красным расхождения по трем штучкам сигарет из тысяч?
Это тоже решается инструментами для низового персонала с доступом ко всей нужной информации.
Выводы
Самый главный плюс маркировки в том, что государство заставило всех цифровизироваться и переходить на ЭДО с цифровыми подписями и криптографией.
«Прилив поднимает все лодки», и переход всего рынка на общие рельсы дает большой синергетический эффект.
Всем удачной автоматизации!
You must be registered for see links
и
You must be registered for see links
.Систему часто критиковали и критикуют, в основном из-за частых изменений API, багов личного кабинета и белых пятен в некоторых процессах.
Мы решили, пусть и не первыми, опубликовать свой опыт и свои мысли об этом новом амбициозном проекте государства, в котором мы активно участвуем.
Может показаться, что статья — каша, но маркировка в целом такая каша и есть, очень много аспектов сходятся в одном месте.

Кратко о нас
You must be registered for see links
занимаемся софтом для мобильных работников, в основном под специальное оборудование терминалов сбора данных (ТСД) и регистраторов выбытия (РВ).Кому-то может показаться, что вот есть лес, в лесу дерево, на дереве жук, а на жуке живет микроб, и ниша софта для ТСД — это про микробов на жуке.
На это можно ответить, что мобильность персонала — очень крупный растущий рынок, а специальное железо с готовым софтом — это вообще будущее всего текущего железа. В конце концов, любая реально прорывная штука — это результат многих лет труда в узкой нише (
You must be registered for see links
про мобильный YouTube).В основном продукты Клеверенс продаются с уже готовой интеграцией с учетными системами, которые (интеграции) мы сами же пишем и поддерживаем (например,
You must be registered for see links
).Весь софт и железо стараемся обкатывать на реальных производствах, складах, магазинах и т.д. Например, когда проект маркировки обуви только начинался поехали в Китай, чтобы обкатать бизнес-процессы, параллельно сняли
You must be registered for see links
об этом.Что такое система маркировки и «Честный знак»
Грубо говоря, это государственно-частный интернет вещей на штрихкодах и RFID для тотального прослеживания движения единиц товаров.
По системе маркировки существует очень много информации, главным ресурсом является сайт «
You must be registered for see links
».
Отношение участников рынка к маркировке
Не секрет, что отношение участников рынка к маркировке полярное. От “Россия, вперед!” и “Идея хорошая, но реализация подкачала” до “опять маленьких обижают”.
Из плюсов называется обеление рынка и контроль цепочек поставок. Из минусов — снятие с ЕНВД при торговле маркированным товаром.
Практически весь крупный бизнес за маркировку. Мелкие предприниматели, которые хотят работать красиво и в белую — тоже за маркировку, для них это конкурентное преимущество перед серыми рынками.
Против маркировки в основном малый и средний бизнес, который считает всё это лишней нагрузкой для себя.
Претензии в основном формулируются как “снова душат малый бизнес” или “у вас столько денег и людей, могли бы сразу сделать то-то и то-то”, “бизнес-процесс такой-то не продуман”. Хотя именно на малый бизнес и его процессы были потрачены основные деньги — это сайт с личным кабинетом участника, облачный регистратор эмиссии кодов и т.п.
Отдельно стоит позиция айтишников, о ней ниже.
При этом информационный портал «Честного знака», на котором публикуется информация, сделан просто отлично. Например, где найти информацию на английском языке?
You must be registered for see links
. А на китайском?
You must be registered for see links
.Проблемы на старте, о которых все говорили
Пока шел пилот, в системе было много багов. В основном их успели излечить до 1 июля 2020.
Обещали, что на старте будет работать лучше ЕГАИСа, и в целом правда доступность сервиса выше.
Сейчас в табаке и обуви система всегда доступна, всё отрабатывает быстро, кроме редкого выключения на технологические работы вечером на пару часов.

Но ключевая проблема на старте была в том, что “не запрягши не поедешь”, а 99% числа участников оборота (по количеству) тупо игнорировали эту систему, не регистрировались, не давали нагрузку, ждали судного дня, а потом требовали переноса сроков.
Еще летом 2019 года мы тестировали нагрузку в нашей «
Но тогда в системе было зарегистрировано крайне мало участников, и было видно, что народ начнет шевелиться чуть ли не в самый последний день.
You must be registered for see links
» и смотрели, как маркировка отреагирует на заказ и выпуск 10 млн кодов, единоразово (сейчас уже так делать нельзя). Процесс занял меньше 10 минут.Но тогда в системе было зарегистрировано крайне мало участников, и было видно, что народ начнет шевелиться чуть ли не в самый последний день.
Об этой проблеме все знали, к ней готовились, но когда подошел дедлайн по обуви, всё равно случился коллапс. Некоторые УОТы кинулись выписывать себе бесплатные коды на остатки на 20 лет вперед, это в пике дало увеличение нагрузки на сервера в х40 раз. Такие игрища, конечно, даром не пройдут, потому что система цифровая и, что называется, “все ходы записаны”.
К сожалению, пострадали и пионеры маркировки — это те компании, которые с первого дня были в пилоте маркировки, добросовестно старались, но в конце тоже просили о переносе сроков.
Тут надо сказать, что государственная система — это не айфончик, чтобы с первого дня продаж вызывать восторги. И цель её создания была не в том, чтобы собирать лайки от айтишников или снимать видео-обзоры по типу “вот когда выйдет, тогда и посмотрю, решу для себя, надо ли покупать”.
Почему-то люди ждут, что с первого дня система будет работать так, как будто ей уже 5 лет в продуктиве.
Вообще, если ждать по такой логике, когда всё будет идеально, то надо всё переносить на 2030й, а лучше на после покорения Марса, ага.
Позиция айтишников
Позиция айтишников не “за” и не “против”, а “дайте”. Требуют заранее анонсировать все изменения, требуют лучшей документации, больше тестовых примеров, песочниц, меньше ограничений.
В целом в проекте много разного железа и международных стандартов, что приносит классическим айтишникам одни только боль и страдания.
Айтишники — очень въедливые и умные люди, со своим мнением по любому вопросу. И никакого единого мнения по поводу маркировки, кроме претензий по работе API, в общем-то нет.
API системы меняется чаще, чем этого хотелось бы для сценария “сделал и забыл”. Но при этом считается, что в API надо надобавлять еще кучу методов для работы с групповыми упаковками (агрегатами), для упрощенной авторизации и т.п., но это опять означает изменение API.
Мы сами айтишники, и у нас такая же двойная позиция, что в API не хватает методов, но при этом API меняется слишком часто. Тут, как говорится, “
You must be registered for see links
”.В общем, API улучшать надо, но желательно предупреждать об этом за 1-2 месяца и давать людям время на внесение изменений в свои системы. А то было время, когда на боевом контуре табачной маркировки стояла более новая версия API, чем в тестовом контуре.
Технические аспекты маркировки
Технические проблемы, с которыми сталкиваются айтишники, в основном сводятся к следующему списку:
- Сисадминские вопросы с УКЭП, которые были и будут до тех пор, пока есть фрагментация по версиям операционных систем и браузеров
- Кодерские вопросы, которые нельзя решить путем гугления на StackOverflow, потому что система новая и уникальная, несмотря на использование открытого ПО
- Внедренческие вопросы, когда люди пользуют “online barcode generator” или “сканер в разрыв клавиатуры”, а потом удивляются, почему вышла ерунда
Посмотрите, тут и Java, и Reactive (RxJava), и Spring и даже Netflix:

Чтобы составить собственное мнение можно почитать
You must be registered for see links
.Авторизация
Авторизация в ИС МП происходит в 2 этапа.
Сначала нужно запросить некий псевдослучайный “ключ”, который нужно подписать и отправить на урл “/api/v3/auth/cert/“ (причем на момент написания этого материала в конце url обязательно должен был стоять слэш “/“, иначе не работало, что выглядит странно).
Получение “ключа” происходит так (нужно подставить нужный хост, их много разных, в зависимости от того, песочница это или боевой, одежда или что-то другое):
// получаем на /api/v3/auth/cert/key “ключ” и данные, необходимые для авторизации
var uri1 = new Uri("/api/v3/auth/cert/key")
var randomDataResponse = REST.Invoke(uri1, "GET", timeout);
Затем нужно подписать этот псевдослучайный “ключ” при помощи выбранного КЭП и отправить в ГИС МТ, чтобы получить в ответ авторизационный токен.
Для этого ищем сертификат КЭП по выбранному пользователем отпечатку (certificateThumb). Сертификат находится в данном случае в “Личных” локальной машины. Также контекст сертификата должен быть связан с хранилищем ключевой пары (такие сертификаты отмечены иконкой ключика в списке сертификатов в оснастке windows):

Получение сертификата в коде для формирования подписи:
X509Certificate2 cert = null;
using(store = new X509Store(StoreName.My, StoreLocation.LocalMachine))
{
store.Open(OpenFlags.ReadOnly);
cert = from c in store.Certificates where string.Compare(c.Thumbprint, certificateThumb, true) == 0 select c;
}
Подписываем таким образом:
// данные для подписи
var content = new ContentInfo(randomDataResponse.Data);
var signedCms = new SignedCms(content, false);
// настраиваем сертификат для подлиси, добавляем дату
var signer = new CmsSigner(SubjectIdentifierType.IssuerAndSerialNumber, cert);
signer.SignedAttributes.Add(new Pkcs9SigningTime(DateTime.Now));
// формируем подпись
signedCms.ComputeSignature(signer, false);
var sign = signedCms.Encode();
Подписанное CMS-сообщение (sign) — это и есть та проверочная подпись, которую нужно отправить для авторизации, предварительно преобразовав в формат Base64.
var tokenRequest = new TokenRequest();
tokenRequest.UUID = randomDataResponse.UUID;
tokenRequest.Data = Convert.ToBase64String(sign);
// получаем токен на /api/v3/auth/cert/
var uri2 = new Uri("/api/v3/auth/cert/")
var tokenResponse = REST.Invoke(uri2, "POST", tokenRequest);
В ответ приходит
You must be registered for see links
токен, закодированный в Base64.К слову, отправляемые документы в дальнейшем подписываются таким же образом, только формируется так называемая “открепленная” подпись:
var signedCms = new SignedCms(content, true);
Вспомогательные классы (со схемой, идентичной XSD-схемам документов из API):
///
/// Ответ на запрос GET /api/v3/auth/cert/key для авторизации.
///
public class RandomDataResponse
{
///
/// уникальный идентификатор сгенерированных случайных данных, тип string
///
[Newtonsoft.Json.JsonProperty(PropertyName = "uuid")]
public string UUID { get; set; }
///
/// случайная строка, тип string
///
[Newtonsoft.Json.JsonProperty(PropertyName = "data")]
public string Data { get; set; }
}
///
/// Данные для запроса авторизационного токена.
/// POST /api/v3/auth/cert/
///
public class TokenRequest
{
///
/// uuid - уникальный идентификатор подписанных данных из /api/v3/auth/cert/key
///
[Newtonsoft.Json.JsonProperty(PropertyName = "uuid")]
public string UUID { get; set; }
///
/// подписанные УКЭП зарегистрированного участника случайные данные в base64
///
[Newtonsoft.Json.JsonProperty(PropertyName = "data")]
public string Data { get; set; }
}
///
/// Ответ на запрос авторизационного токена.
/// POST /api/v3/auth/cert/
///
public class TokenResponse
{
///
/// Авторизационный токен в base64-строке
///
[Newtonsoft.Json.JsonProperty(PropertyName = "token")]
public string EncodedTokenBase64 { get; set; }
}
Если вам удалось авторизоваться — вы прошли небольшой квест.
Проблемы с генерацией и чтением штрихкодов
Система маркировки построена на международных стандартах, за исключением части с криптографией. Это отлично и достойно похвалы.
К сожалению, средний айтишник никаких стандартов не читает, ни про что не изучает, а сразу лепит свои велосипеды из бесплатных компонентов про генерацию штрихкодов, печать, бизнес-процессы и т.п.
Первая же трудность — распечатать штрихкод маркировки в своём дизайне. Из коробки “Честный знак” предоставляет бесплатный инструмент, но с ним никто, конечно, разбираться не стал, ведь есть “online barcode generator” и встроенные редакторы отчетов в 1С/SAP/NAV/DAX.
Засада в том, что современный штрихкод — это не просто графическое представление символов (об этом у нас выйдет отдельная статья). Поэтому сразу всплыли проблемы префиксов, разделителей, кодировок, обязательных непечатемых символов и прочее такое, про что никто знать не знал и разбираться не хотел.
Пример со спецсимволом GS (ASCII 29)

Пример со спецсимволом FNC1 (ASCII 232)

Скриншоты сделаны из приложения «
You must be registered for see links
».Вот кусок исходного кода «Чекмарка», который выполняет разбор штрихкода, отсканированного камерой и разобранного нашей платформой:
var km = BarcodeData.GS1;
if (km.Contains("01") && km.Contains("21"))
{
if ((km.Contains("17") || km.Contains("7003")) && !km.Contains("10"))
{
ПризнакМолока = true;
if ((km.GetValue("01").Length == 14) && (km.GetValue("21").Length == 7 ||
km.GetValue("21").Length == 13) && (km.GetValue("17").Length == 6 ||
km.Getvalue("7003").Length == 10) && (km.GetValue("93").Length == 4))
{
ЭтоМолоко = true;
MSG2 = "Является KM ЧЗ молочной продукции.";
if (km.GetValue("21").Length == 7)
MSG2 = "Является КМ ЧЗ групповой упаковки молочной продукции.";
}
else
{
// Проверка наличия группы в коллекции для отображения (EntriesRows)
// В случае отсутствия - добавляем группу с пустым содержимым
EntriesRows = ПоискАI(EntriesRows, Al = 93, BarcodeData);
MSG2Error = "Не является КМ Ч3! Имеет признаки КМ молочной продукции.";
Msg = "#N005" + Msg;
}
}
else if (km.Contains("8005") || km.Contains("93"))
{
ПризнакТабачногоБлока = true;
if (km.GetValue("01").Length == 14 && km.GetValue("21").Length == 7 &&
km.GetValue("8005").Length == 6 && km.GetValue("93").Length == 4)
{
ЭтоТабачныйБлок = true;
MSG2 = "Является КМ ЧЗ табачного блока.";
}
else
{
EntriesRows = ПоискАI(EntriesRows, AI = 8005, BarcodeData)
EntriesRows = ПоискАI(EntriesRows, Al = 93, BarcodeData)
MSG2Error = "Не является КМ Ч3! Имеет признаки КМ табачного блока.";
Msg = "#N004" + Мsg;
}
}
else if (km.Contains("92") && km.Contains("92").Length > 66)
{
ПризнакОбуви = true;
if (km.GetValue("01").Length == 14 && km.GetValue("21").Length == 13 &&
km.GetValue("91").Length == 4 && km.GetValue("92").Length == 88)
{
... (и т.п.) ...
Откуда взялись спецсимволы? Из стандарта. «Честный знак» сделали всё по стандарту, и участникам оборота товаров тоже надо было читать стандарт.
КСТАТИ: Проверку корректности содержимого DataMatrix можно произвести только с помощью сканирования камерой (даже если сканировать с ТСД, нужен доступ к камере). Потому что все сканеры штрихкодов в соответствии со стандартном не должны возвращать 1в1 то, что они считали, как минимум должны выбрасывать первый символ FNC1. В целом, сканеры могут добавлять или убирать важные символы штрихкода при сканировании, переставлять блоки местами, в зависимости от настроек, всё это мешает проверке.
Т.к. системная интеграция — это не про программы, а про людей и про то, как они пишут и читают спецификации, то наличие этих спец символов сразу привело к некоторому разногласию при обмене штрихкодами.
Например, могли, особо не вчитываясь в спецификации, добавлять в штрихкод строку из 4 символов “FNC1” вместо одного символа ASCII 232 (FNC1). А еще, при обмене между подсистемами такие символы часто фильтруются и теряются, до печати доходят уже без таких символов, при этом в обычных текстовых редакторах спец. символы часто не отображаются и люди удивляются, почему же что-то не так, если штрихкоды совпадают.
Так же, если не указывать символ FNC1 в штрихкоде, некоторое оборудование или ПО может не понять что это такое и как его разбирать, т.к. этот символ вначале штрихкода как раз указывает на то, что это формат GS1 DataMatrix.
Один из последних примеров, на котором споткнулись почти все, было появление скобок и знаков препинания в серийном номере.

Откуда в серийном номере скобки и знаки препинания? Из стандарта! Стандарт GS1 позволяет их использовать. Т.к. серийный номер в длину имеет всего 13 символов, а товаров под маркировку очень много, приходится использовать все доступные символы.
Отдельные лулзы — скобки в серийном номере. Они там разрешены стандартом, но никто их не ждал. В так называемой человеко-читаемой форме представления (HID) скобки имеют специальный смысл: они обрамляют номера значимых групп символов. Например, “(21)” означает, что дальше в строке будет идти серийный номер.
Если наивно думать, что в штрихкоде хранится просто строка символов, то в строке “(21)abcd12(3)d(1,(91)” серийным номером видится “abcd12”, а часть про “(1,” кажется вообще ошибкой.
На самом деле серийный номер тут “abcd12(3)d(1,”, а после запятой стоит нечитаемый символ GS. И дело не в том, что серийный номер должен быть 13 символов (потому что формально длина серийника в GS1 DataMatrix может быть другой, и в шинах, например, она бывает 20 символов). Дело именно в невидимом GS, который надо учитывать, и который в полях любой учетной системы не выводится, не принимается для ввода и вообще запрещен (и в обычном Блокноте его тоже не видно, не выводится, нужен Notepad++).
Наличие таких спец символов накладывает ограничение на передачу и хранение данных штрихкодов, их нужно экранировать или кодировать, например в Base64.
КСТАТИ: существует стандарт на хранение и передачу таких штрихкодов в виде строки (ISO/IEC 15424-2018), но почему-то им никто не пользуется. Данные штрихкода GS1 DataMatrix, хранимые в виде строки, должны начинаться на “]d2”.
Сейчас почти все исправили свои компоненты печати штрихкодов (наверное). Но кто вообще читает стандарты, правда?
На проверку, домашнее задание: вот эта тема, что если поле фиксированной длины, то GS вставлять не нужно, а если длина переменная, и значение поля не максимальной длины, то вставлять нужно. На самом деле это правило работает не так. Спецсимвол GS не вставляется только если AI начинается с пары цифр из этой вот таблицы:

А во всех остальных случаях вставляется. Ваш код генерации/разбора ШК работает так же?
Еще одна проблема — сканирование штрихкода маркировки ламерскими средствами типа “сканер в разрыв клавиатуры”. До маркировки самой большой проблемой было, что где-то обрезается или вставляется лишний ноль. Со введением новых кодов маркировки тулзы со сканированием выведены на совершенно новый уровень.
Зачастую это не проблемы самого сканера или его настроек, а проблемы с отсутствием опыта и понимаем принципов штрихкодирования.
Например, при подключении сканера «в разрыв клавиатуры» (или при эмуляции такого режима), а также при подключении сканера как HID-устройства, возможны проблемы с заменой одних символов в считанном штрихкоде на другие или пропадание определенных символов.

Схема подключения сканера в разрыв клавиатуры
При работе в указанных режимах сканер передаёт компьютеру не сами символы из штрихкода (sic!), а коды нажатий клавиш клавиатуры, которые нужно было бы нажать, чтобы набрать на клавиатуре символы из этого штрихкода.
При этом очевидно, что одной клавише клавиатуры может соответствовать сразу несколько возможных символов, в зависимости от языка раскладки и нажатий клавиш-модификаторов (Shift, Caps Lock, Alt и Ctrl).
Например, при нажатии на вот эту клавишу в нижней правой части клавиатуры:

Результатом может быть любой из символов ‘?’, ‘/’, ‘,’ или ‘.’, в зависимости от выбранной раскладки и использования клавиш-модификаторов. Какой конкретный введётся символ — определяется настройками клавиатуры операционной системы, а не сканером.
Именно из-за этого вместо одних серийников на кассе выбывают совершенно другие, либо код вообще “не найден”.
Кстати, этих проблем можно было бы избежать, если бы в серийный была чексумма, когда по последней цифре можно проверить, правильный ли код, правильно ли он считался/ввелся. У расчетных счетов, ИНН, номеров карт, у EAN13, у всего последняя цифра является чексуммой для проверки, чтобы люди и машины не ошибались при вводе.

Очевидно, тут понадеялись на то, что DataMatrix самопроверяемый, плюс есть криптохвост. Но одно дело весь штрихкод, самопроверяемый, и другое дело огрызок кода с серийником, который вообще могли ввести с клавиатуры.
Отдельные споры айтишников вызвал так называемый «криптохвост».
«Криптохвост» — это необходимая часть штрихкода маркировки, благодаря которой можно по симметричному ключу проверить, что серийный номер единицы товара не высосан из пальца.

Криптохвост есть только в штрихкоде и не хранится в базе маркировки, чтобы никакой хакер не мог подломить базу и печатать чужие штрихкоды.
Т.е. это своеобразная цифровая подпись. Но т.к. штрихкод не резиновый, а товаров много, то длина этой цифровой подписи небольшая, что не позволяет пользоваться открытыми для всех ключами шифрования.
Конечно, все серийные номера лежат в базе данных маркировки, но если проверять по ней в онлайне, то при любом падении интернета сразу встанут все склады и магазины.
Криптохвост призван решить эту проблему, но пока (на лето 2020 года) не заработал в полную силу.
Дело в том, что криптография российская и привязана к железкам. Но альтернативы российской крипте всё равно нет, государственная российская система не может использовать иностранную крипту, это будет
You must be registered for see links
. Поэтому придется терпеть российскую, это разумно и не сложно.Вообще криптография — тема очень сложная. Информации много и очень тяжело найти описание того, как нужно подписать или зашифровать данные в конкретном случае.
С этим столкнулись все, кто попробовал интегрироваться с API маркировки. Было очень много вопросов в чатах типа “Почему не авторизуется?”, “Как подписать?”, “Поделитесь примером!”, “Подпись сформировали но приходит отказ, почему?” и много других.
Чаще всего ошибки были банальны. Например, после подписи изменяли данные, либо терялся пробел или как-то несущественный символ, но для подписи это критично, и после отправки в API приходил отказ без объяснений, т.к. подпись не проходила проверку.
К счастью в чатах чаще всего помогали и отвечали на такие вопросы. В целом, все эти проблемы лечатся или уже были излечены к 1 июля 2020.
В части “Честного знака” к 1му июля 2020 весь процесс от производства товара до его выбытия через кассу или доставку интернет-магазина был продуман, расписан, протестирован и запущен в боевом контуре. Например, у нас есть
You must be registered for see links
.Что мы сами думаем о маркировке
Мы в Клеверенсе думаем, что софтовые проблемы не главное. Хуже то, что участники оборота товаров до сих пор не понимают сути изменений. Это гораздо большая проблема, чем софтверные баги.
Люди относятся к маркировке как к еще одному бухгалтерскому отчету, который можно составлять сидя у компа в 1С/SAP/NAV/DAX, корректировать, менять задним числом и т.п. Типа пользоваться будут бухгалтеры и логисты, а айтишники должны “запилить” под это нужные модули и обработки.
Главный запрос наших клиентов в том, чтобы склад/китайцы/тетямаша что-то насканировали, а потом это “корректно” загрузилось в 1С/SAP/NAV/DAX. И мы это успешно делаем.
Но это очевидная ошибка, которая вскроется, когда компании начнут сводить остатки друг с другом, а государство начнет штрафовать.
Что такое на самом деле система маркировки
Маркировка товаров — это система отражения реальных движений.
Реальные проблемы с маркировкой
Это чисто наше IMHO.
Все реальные проблемы автоматом вытекают из того, для чем на самом деле является система маркировки, а именно, системой отражения реальных движений.
Во-первых, реальный учет движений противоречит текущим принципам учета по всей цепочке, когда всё учитывается по SKU, по партии или по среднему. Задним числом сводить и исправлять — наше всё.
Учетная система в любой компании — представляет собой причесанную и исправленную сказку о том, как всё здорово получилось после 100500 созвонов, исправлений, перепроведений и вычищения ошибок.
На одной из расширенных встреч у крупного иностранного дистрибутора лекарств только после часа обсуждения главный логист, наконец, округлил глаза и сказал “это что же, разные штрихкоды у каждой пачки?”. А слова “уникальный”, “серийный номер”, “каждый экземпляр”, “всё сканировать” и т.п., видимо, пролетели мимо.
Во-вторых, реальный учет движений противоречит текущим бизнес-практикам и принципам разделения ответственности.
Даже если компания крупная и у сотрудника нет прав на правку каких-то документов — есть телефон, можно позвонить или написать тому, кто может поправить.
Или, например, документы подписываются КЭП директора каким-то низовым сотрудником, а если есть двухэтапная аутентификация, то через пересылку SMS. В системе маркировки есть блок про пользователей и их права, можно выдавать всем отдельные КЭП, но люди этого делать не спешат.
Это явная проблема, которая будет решаться предоставлением всё больших прав и инструментов учета тем простым сотрудникам, которые находятся прямо рядом с маркированным товаром.
Сверх того, правила расчета себестоимости или учета движений в учетной системе основаны на усреднениях и упрощениях типа FIFO/LIFO и средней цены. И те принципы учета, которые повсеместно десятилетиями применяются от производства до розницы, основаны на этих упрощениях и идут в разрез с реальным прослеживаем уникальных единиц.
Из-за этого на практике получается, например, что в систему маркировки товары отправляются по FIFO/LIFO, а реально отгружается то, что стояло ближе в выходу.
Это тоже решается специальным оборудованием и софтом для простых сотрудников, которые по роду своей работы не могут сидеть у компа.
Еще одна проблема — это попытка “натянуть сову на глобус” и втащить коды маркировки во все стандартные документы ERP, чтобы там их видел бухгалтер, логист или ответственный менеджер.
Хотя смотреть ему на них не за чем, сделать он с ними ничего не может.
И правда, ну как может бухгалтер или менеджер, глядя в монитор может понять, что там вчера насканировал склад, и почему тут выделенные красным расхождения по трем штучкам сигарет из тысяч?
Это тоже решается инструментами для низового персонала с доступом ко всей нужной информации.
Ну т.е. это не технические проблемы каких-то систем, которые в целом к 1 июля 2020 уже были исправлены, а вопросы перестройки работы компаний на новые рельсы.
Выводы
Самый главный плюс маркировки в том, что государство заставило всех цифровизироваться и переходить на ЭДО с цифровыми подписями и криптографией.
«Прилив поднимает все лодки», и переход всего рынка на общие рельсы дает большой синергетический эффект.
Всем удачной автоматизации!