Имя: Пароль:
1C
 
1С и API ЧЗ
0 ChMikle
 
07.11.25
09:46
Добрый день. Кто-нибудь не реализовывал следующую задачу. По API из ЛК ЧЗ выбирать товар с подходящим сроком годности и формировать соответствующий документ вывод из оборота, для дальнейшего его вывода ?
1 MWWRuza
 
гуру
07.11.25
11:17
Там не все так просто...
По API можно получить сроки годности, но по списку марок, вообще нет проблем. На вход этого запроса нужно передать этот список. А вот тут проблема... Где этот список взять?
ЧЗ не отдает список марок по API... Там только через "выгрузку" можно получить. Тоесть, по API мы заказываем выгрузку по нужным нам критериям, и в ответ, через какое-то время(как заблагорассудится ЧЗ), прилетает сформированный файл-выгрузка, с запрошенными данными. С ним уже можем работать, его загружать и брать из него нужные нам данные. Тоесть, это не совсем по API получается.
Но, в принципе, можно реализовать.
2 mishaPH
 
07.11.25
11:22
(1) ну список марок же должен быть известен. вы же товар откуда то получали
3 ChMikle
 
07.11.25
11:27
(1) суть в том , чтобы автоматически выводить из оборота просроченную продукцию
4 Табуретко
 
07.11.25
11:41
https://infostart.ru/1c/articles/1506206/
см. 7 комментарий
5 timurhv
 
07.11.25
12:49
(4) осталось вернуться в 2021 год, чтобы метод работал
6 timurhv
 
07.11.25
12:54
5.1.1. Метод получения информации о списке КИ по заданным фильтрам
/api/v4/true-api/cises/search

Можно передать в параметрах отбор по дате производства, GTIN и тд, но дату окончания срока годности - нет.
7 ChMikle
 
07.11.25
14:14
Печально
8 Маленький Вопросик
 
07.11.25
14:34
Товарищи подскажите, здесь какой токен можно использовать?

 &НаКлиенте
Функция СвойствоКМ(ТокенДоступа)
            
    ЗащищенноеСоединение = Новый ЗащищенноеСоединениеOpenSSL(Неопределено, Новый СертификатыУдостоверяющихЦентровОС());

    HTTPСоединение = Новый HTTPСоединение("markirovka.crpt.ru",443,,,,60,ЗащищенноеСоединение);

    ЗаголовокHTTP = Новый Соответствие();
    ЗаголовокHTTP.Вставить("Content-Type", "application/json; charset=UTF-8");
    ЗаголовокHTTP.Вставить("Accept", "application/json");
    ЗаголовокHTTP.Вставить("Accept-Charset", "utf-8");
    ЗаголовокHTTP.Вставить("Authorization",   "Bearer " + ТокенДоступа);
        
    ПараметрыURL = Новый Массив;         ///Отбор запроса
    ПараметрыURL.Добавить("pg=milk");                               ///Группа - молочная продукция
    ПараметрыURL.Добавить("cisStatus=EMITTED");               ///Статус - Эмитирован.Выпущен
    ПараметрыURL.Добавить("limit=20");                              ////Лимит списка - 20 
    
    
    ///api/v3/true-api/cises/listV2?pg=milk&cisStatus=EMITTED&limit=999
    URLЗапроса = СтрШаблон("/api/v3/true-api/cises/listV2?%1",СтрСоединить(ПараметрыURL, "&"));
    
    HTTPЗапрос  = Новый HTTPЗапрос(URLЗапроса, ЗаголовокHTTP);
        
    Ответ = HTTPСоединение.Получить(HTTPЗапрос);
    
    ИДДок = Ответ.ПолучитьТелоКакСтроку();

    Чтение = Новый ЧтениеJSON;
    Чтение.УстановитьСтроку(ИДДок);
    
    РезультатРазбора = ПрочитатьJSON(Чтение, ложь);
        
    
    Возврат РезультатРазбора;
    
КонецФункции 
9 ProxyInspector
 
07.11.25
14:39
(6) Получи список марок с датой производства ранее, чем несколько месяцев, а потом по этому списку получи список марок, у которых истек срок годности. Опять же через ЧЗ
10 timurhv
 
07.11.25
14:49
(9) В больших организациях не подойдет, надо будет еще отборы накладывать, т.к. можно получить не больше 10млн марок, поэтому:
+ productGroups (отобрать группы товаров, по которым просроченным марки могут висеть)
+ status (добавить без выбывших)

Если марок очень много, то тогда только отбирать дополнительно по всем датам производства в цикле (по периодам в 1 мес, 3 мес)
2024-01-01 - 2024-01-31
...
2024-09-01 - 2024-12-31
и тд
11 MWWRuza
 
гуру
07.11.25
16:25
Это все не пойдет.
Общением с ТС выяснилось, что речь идет о молочке.
А она учитывается по ОСУ.
Нет у него в ЧЗ марок по интересующей ТГ на нем. Вообще.
Они все на производителе, которым он не является.
Списывать просто нечего.
Тут, только если сканировать фактически имеющиеся в наличии(можно с помощью ТСД, если есть 2D). И по этому списку уже проверять сроки годности. Но, делать этого ни кто не будет, трудозатраты не сопоставимы с результатом.

(10) Да, именно так. Для этого выгрузку и придумали.

А так, да.... Сейчас посморел, в V4 появились методы запроса марок. Но, по конкретному GTIN. Но, все это сработает только для ВЛАДЕЛЬЦА марок. Что в случае ОСУ, = производителю...
12 MWWRuza
 
гуру
07.11.25
16:54
(8) Товарищи подскажите, здесь какой токен можно использовать?

А в чем сомнения? Такой-же как и для всего TrueAPI, или "единый в формате UUID", или "длинный" в формате JWT(до 01.03.2026).

Только если посмотреть на это:
ПараметрыURL.Добавить("pg=milk"); ///Группа - молочная продукция
то даже, если метод и отработает, что тоже ? - там они отключали устаревшие методы, то марок вы не увидите, если конечно вы не производитель, который их сам в СУЗ заказал, нанес и ввел в оборот.
13 Маленький Вопросик
 
07.11.25
17:10
Как тогда увидеть собственные марки?
14 d4rkmesa
 
07.11.25
17:15
(11) >>Но, все это сработает только для ВЛАДЕЛЬЦА марок. Что в случае ОСУ, = производителю...

Любопытно, в партионном учете ЧЗ такой же принцип будет?
15 MWWRuza
 
гуру
07.11.25
17:27
(14) Что там с "партионным" придумали, я пока не разбирался. А то, про что я выше писал, вот, скриншот из описания метода TrueAPI:

16 MWWRuza
 
гуру
07.11.25
17:46
(13) Как тогда увидеть собственные марки?

Собственные - это какие?
Вы кто такой - производитель, импортер, оптовик, розница?
В случае молочки, соков и т.п. товаров ОСУ - у вас нет собственных марок.(нет, они есть у производителей и импортеров, которые их сами заказали в СУЗ, нанесли, и ввели в оборот).
Соответственно - ни как. Так, как у вас их нет.
А все, что есть - увидеть можно только "глазами"(сканером)... В живую.
В базах ЧЗ они на вас не числятся. Зайдтите в ЛК ЧЗ, в нужную ТГ, нажмите закладку "марки", и увидите, что там пусто.
Вот:


Нет, я конечно Вас не знаю, может Вы производитель... Тогда есть методы, читайте описание TrueAPI, только не эти устаревшие V2, а новые, V4, которые пришли им на замену. Но, судя по вопросам - вряд-ли :-)
17 MWWRuza
 
гуру
07.11.25
17:56
+(16) Вот, для той-же организации, по воде:


Там их очень много, в разных статусах(это розница).
18 timurhv
 
07.11.25
18:09
(16) "Соответственно - ни как. Так, как у вас их нет."
Нужно выводить по ОСУ: GTIN + Количество
В некоторых случаях еще и вес.
Откройте вкладку "СКЛАД" в ЛК.

При фасовке передается марка + цена, а при использовании в производство = ОСУ.
19 Маленький Вопросик
 
07.11.25
18:16
Владельцем марок не может являться розница, закупившая партию молочки или соков? И получившая их через ЧЗ?
20 АгентБезопасной Нацио
 
07.11.25
18:25
(19) Нет. Рознице отдали "количество марок".
21 MWWRuza
 
гуру
07.11.25
18:30
+(20) "количество марок"

И объъем/вес продукции, в случае разливного/развесного товара :-)
22 MWWRuza
 
гуру
07.11.25
18:35
(18) Нужно выводить по ОСУ: GTIN + Количество
И марки, в случае продажи на ККТ. Живые, сканированием, не из базы ЧЗ.
23 timurhv
 
07.11.25
18:42
(22) ну это-то само собой, хотя в магазине у дома чет никто так марки и не сканирует...
24 Маленький Вопросик
 
07.11.25
18:44
Поясните что такое количество марок?
25 MWWRuza
 
гуру
07.11.25
18:47
(18) Откройте вкладку "СКЛАД" в ЛК.

Да чего мне вкладка... Я даже по API отчет по складу делал, вот, фрагмент отчета по молочке:

26 MWWRuza
 
гуру
07.11.25
18:53
(24) Поясните что такое количество марок?

Ровно то, что написано. Количество единиц продукции, с нанесенной маркой.
Получили 20 пачек мороженного - количество марок будет 20.
Но, какие конкретно марки - можно только на самой продукции глазами(сканером) прочитать. Ни в документах(ни в бумажных ни в ЭДО), ни в ЛК вы это не увидите.
27 timurhv
 
07.11.25
18:53
(25) Ну вот в (0) пускай делают инвентаризацию и списывают просрочку с соответствующей причиной вывода.
28 MWWRuza
 
гуру
07.11.25
18:59
Да. Но не марки. Просто количества. А вопрос по маркам был... И узнать, какая продукция просрочилась - только глазами... Или сканированием марки живой, и запросом в ЧЗ. Вытащить информацию не сканируя/или не разглядывая напечатанный на этикетке СГ - по продукции ОСУ, к сожалению не получится.
29 Маленький Вопросик
 
07.11.25
19:42
(28) что скажете об этом методе?

api/v4/true-api/cises/search

Метод позволяет получить информацию по КИ / КиЗ, числящихся на участнике оборота товаров
по заданным фильтрам. Максимальный лимит кодов в ответе с учётом пагинации 10 000.
30 Маленький Вопросик
 
07.11.25
19:43
(28) просто "количества" у вас каким методом запрашивается?
31 АгентБезопасной Нацио
 
07.11.25
20:03
(24) То, что учитывается по ОбъемноСортовому Учету (ОСУ). до розницы передается "количество штук по ГТИН", без поштучной (помарочной) детализации.
32 timurhv
 
07.11.25
20:08
(30) Других методов нет, скорее всего:
5.9. Метод получения актуального баланса на складе
33 MWWRuza
 
гуру
08.11.25
20:09
(29) Я все уже сказал выше, именно про этот метод, еще в (15).
Сами смотрите:
Метод позволяет получить информацию по КИ / КиЗ, числящихся на участнике оборота товаров
по заданным фильтрам.
При этом, одно из обязательных полей фильтра - это SGTIN. Смотрите таблицу описания полей запроса там-же, чуть ниже.

PS Не знаю, будет настроение - в выходные(завтра-послезавтра), я постараюсь у себя сваять такой запрос, для получения списка марок, например по воде.
Но, сразу говорю - первый раз буду делать в 7.7. Мне так быстрее и проще. Потом, после отладки и получения приемлемого результата, может и на 8.3 нарисую, как отчет карточки и марки сделал :-)
34 timurhv
 
08.11.25
00:29
(33) чет так себе идея, у нас 1.5 млрд+ марок в год приход уже. АПИ дергать - самоубийство. Я чет в (10) подумал 10тыс х 1000 страниц выдает, а там в итоге только 10к марок раскиданных по всем страницам.
ОСУ марки изначально настроено под списание просрочки, фасовка и тд. Инветаризация была, поэтому в (0) проблем нет.
35 MWWRuza
 
гуру
08.11.25
12:06
(34) Да согласен...

Но, я все-таки набросок запроса сделал... И даже что-то работает :-)
Там требуется SGTIN начальный... х.з. что там указывать...
Взял первую попавшуюся марку из ЛК, вырезал из нее GTIN, а вместо серийного номера добавил строку из 13 нулей :-)))
Дата с - поставил 01.01.2025, 00:00:01.

Возвращает JSON файл, совсем не большой 74 кб всего... В нем куча марок, сколько - пока не понял, разбор JSON пока не делал, сил нет, спать хочу... Завтра.
Но, последняя строка: ""isLastPage": false"... Получается, это не последняя страница. Скорее всего, там 1000 марок. Но, что-то объем маленький для 1000 марок. Учитывая, что там много чего, не только КИЗ марки:


Как-то сомнительно, что 1000 таких блоков текста всего 74 кб будет весить.
Ладно, завтра разберу джейсон, будет видно...
36 Маленький Вопросик
 
08.11.25
07:18
Посмотреть бы все вариантов этих фильтров
37 MWWRuza
 
гуру
08.11.25
12:06
Все варианты фильтров описаны в описании TrueAPI. Там целая большая таблица. Я для пробы пока взял только те, которые обязательные, без них ошибка будет.

PS Я вот сделал, но, честно говоря, не понимаю, какой смысл в инфе, которую этот запрос выдает? Как ее можно использовать на практике?
38 MWWRuza
 
гуру
08.11.25
12:12
Кстати, в ответе есть такая строка:
"expirationDate": "2027-02-14T00:00:00Z",
так, что кому нужен срок годности - он есть прямо тут, отдельно запрашивать не нужно.
Только что это даст? Как в реальном товаре по этой марке найти эту позицию?
39 Маленький Вопросик
 
08.11.25
13:05
(37) можете станицу указать - где эти фильтры?
40 MWWRuza
 
гуру
08.11.25
15:47
(39) Дык параметры тела запроса, страница 354 и дальше:



У меня походу, какой-то косяк с фильтром...
Начал разбирать ответ, там всего 100 КИЗов(почему 100? в параметре пагинации 1000 задал), и там не только по нужному GTIN, а похоже по всем данного клиента.
Разберусь, скорее всего, что-то не верно в фильтре задано :-)

PS Аааа... Понял. Там кроме параметра sgtin, можно передать и параметр gtins, список GTIN, по которым будет инфа. Первый параметр нужен для пагинации, типа с какого номера очередную страницу выводить, и по нему не фильтруется.
41 MWWRuza
 
гуру
08.11.25
15:43
Ну, вот, как-то так:


Пока, без "бантиков" :-) и без пагинации(просто магазинчик маленький, марок мало, отладить не на чем), но, как минимум - работает.

PS Но, еще раз - сделать то я его сделал, но не понимаю - "А ЗАЧЕМ???"
42 Маленький Вопросик
 
08.11.25
16:26
Поздравляю, работает. - покажите листинг функции.

Тогда можно вывести информацио по всем gtin ?
43 MWWRuza
 
гуру
08.11.25
17:16
(42) Вот, только что Вам это даст... Это фрагмент из моей конфы, там куча общих процедур и функций в ГМ...

Листинг
Функция СформироватьТелоЗапроса()
	Фильтр	= СоздатьОбъект("СписокЗначений");
	СзФильтр	= СоздатьОбъект("СписокЗначений");
	СпGTIN		= СоздатьОбъект("СписокЗначений");
	СпGTIN.ДобавитьЗначение(СокрЛП(GTIN));
	СпСтатусов 	= СоздатьОбъект("СписокЗначений");
	Стат		= СоздатьОбъект("СписокЗначений");
	Стат.ДобавитьЗначение(Статус.ПолучитьЗначение(Статус.ТекущаяСтрока()), "status");
	СпСтатусов.ДобавитьЗначение(Стат);
	СпПаг		= СоздатьОбъект("СписокЗначений");
	СзГр		= СоздатьОбъект("СписокЗначений");
	СзГр.ДобавитьЗначение(ТГ.Идентификатор());
	СпПаг.ДобавитьЗначение(1000, "perPage");
	СпПаг.ДобавитьЗначение(ПреобразоватьДатуВСтрХМЛ(ДатаЭМ) + ВернутьВремяСтрокойXML("00:00:01") + ".000Z", "lastEmissionDate");
	СпПаг.ДобавитьЗначение(СокрЛП(GTIN) + "0000000000000", "sgtin");
	СпПаг.ДобавитьЗначение(0, "direction");
	СзФильтр.ДобавитьЗначение(СпGTIN, "gtins");
	Если ПустоеЗначение(СокрЛП(Статус.ПолучитьЗначение(Статус.ТекущаяСтрока()))) = 0 Тогда
	 	СзФильтр.ДобавитьЗначение(СпСтатусов, "states");   
	КонецЕсли;
	СзФильтр.ДобавитьЗначение(СзГр, "productGroups");
	СзФильтр.ДобавитьЗначение(СпПаг, "pagination");
 	Фильтр.ДобавитьЗначение(СзФильтр, "filter");
 	Тело 		= ЗначениеВJSON(Фильтр); 
	Возврат Тело;	
КонецФункции

Процедура Сформировать()
	Перем СЗ;
	СЗ	= СоздатьОбъект("СписокЗначений");
	Если ПроверитьПолучитьТокен() = 0 Тогда
		Если Вопрос("Отсутствует токен авторизации. Если это рабочее место имеет доступ к ЭЦП, нажмите ""Да"", иначе нажмите ""Нет"" и выполните проверку связи с ЦРПТ с рабочего места, имеющего доступ к ЭЦП.", 4, 15) = 6 Тогда
       		СтрОшибка 					= "";
	   		ТекТокен 					= ПолучитьТокенЦРПТ(глПользователь.ЭЦП, ПрефиксВерсии, СтрОшибка);
		Иначе
			СтатусВозврата(0);
			Возврат;
		КонецЕсли;	   		
	КонецЕсли;
	сзЗаголовки 						= СоздатьОбъект("СписокЗначений");
	сзЗаголовки.ДобавитьЗначение("Ansi", 				"Accept-Charset");
	сзЗаголовки.ДобавитьЗначение("application/json", 	"Content-Type"); 
	СтрОшибка							= "";	
	Тело	= СформироватьТелоЗапроса();
	// Отладка
//	Тхт		= СоздатьОбъект("Текст");
//	Тхт.ДобавитьСтроку(Тело);
//	Тхт.Записать("C:\Temp\TeloZapMarok.txt");
	// КонецОтладки 
	Url		= АдресСервераМОТП + "/" + ПрефиксВерсииНов + "/cises/search";
	Ответ = глXmlHttp_ВыполнитьЗапрос("POST", Url, Тело, ТекТокен, сзЗаголовки, СтрОшибка);
	// Отладка 
//	Тхт = СоздатьОбъект("Текст");
//	Тхт.ДобавитьСтроку(Ответ);
//	Тхт.Записать("C:\Temp\OtvMarki.txt");
	// КонецОтладки
	ТзРез	= РазборJSON_SQLLite(Ответ);
	ТЗ 		= СоздатьОбъект("ТаблицаЗначений");
	ТЗ.НоваяКолонка("SGTIN");
	ТЗ.НоваяКолонка("СпРекв");
	ЕстьЕщеСтраницы	= "";
	ТзРез.ВыбратьСтроки();
	Пока ТзРез.ПолучитьСтроку() = 1 Цикл
		Если (ТзРез.Ключ = "sgtin") Или (ТзРез.Ключ = "isLastPage") Тогда
			Если СЗ.РазмерСписка() > 0 Тогда
			    ТЗ.СпРекв = СЗ;
			КонецЕсли;
			
			СЗ	= СоздатьОбъект("СписокЗначений");
			Если ТзРез.Ключ = "sgtin" Тогда
		   		ТЗ.НоваяСтрока();
		   		ТЗ.SGTIN		= ТзРез.Значение;
		   	Иначе
		   		ЕстьЕщеСтраницы	= ТзРез.Значение;	
		   	КонецЕсли;	
		 Иначе
		   	СЗ.ДобавитьЗначение(ТзРез.Значение, ТзРез.Ключ);
		 КонецЕсли;
	КонецЦикла;                              
	Таб = СоздатьОбъект("Таблица");
	Таб.ИсходнаяТаблица("Марки");
	Таб.ВывестиСекцию("Шапка");
	Таб.Опции(0,0,Таб.ВысотаТаблицы(),0);
	ТЗ.ВыбратьСтроки();
	Пока ТЗ.ПолучитьСтроку() = 1 Цикл
		ПечКиз	= СокрЛП(ТЗ.SGTIN);
		СпРекв	= ТЗ.СпРекв;
		Таб.ВывестиСекцию("КИЗ");
	КонецЦикла;
	Таб.ВывестиСекцию("Подвал");
	Таб.ТолькоПросмотр(1);
	Таб.Показать("Список марок по GTIN","");	
КонецПроцедуры

Процедура ОбработкаЯчейкиТаблицы(ЗначЯчейки, Фл)
	Таб = СоздатьОбъект("Таблица");
	Таб.ИсходнаяТаблица("РасшифровкаМарки");
	Таб.ВывестиСекцию("Шапка");
	Таб.Опции(0,0,Таб.ВысотаТаблицы(),0);
	Сч = 0;
	Для Сч = 1 По ЗначЯчейки.РазмерСписка() Цикл
		ИмяПок  	= "";
		ЗначПок 	= ПеревестиОтветыЧЗ_НаЧеловеческийЯзык(ЗначЯчейки.ПолучитьЗначение(Сч, ИмяПок));
		ПозДаты		= Найти(ИмяПок, "Date");
		СГ 			= 0;
		Если ИмяПок = "expirationDate" Тогда
		    СГ		= 1;
		КонецЕсли;
		Если ИмяПок = "expiration" Тогда
		    ПечИмяПок	= ПеревестиОтветыЧЗ_НаЧеловеческийЯзык(ИмяПок, 3);
		Иначе
			ПечИмяПок	= ПеревестиОтветыЧЗ_НаЧеловеческийЯзык(ИмяПок);
		КонецЕсли;
		Если (Лев(ЗначПок, 1) = "[") Или (Лев(ЗначПок, 1) = "{") Тогда
			СзПок	= глРазборJSON(ЗначПок);
			Если СзПок.РазмерСписка() = 0 Тогда
				ЗначПок	= "";
			Иначе
				
			КонецЕсли;
		КонецЕсли;
		Если ПозДаты > 0 Тогда
			Если СГ = 0 Тогда
				ЗначПок	= "Дата, время: " + ВернутьДатуВремяСучЧПстрокой(ЗначПок, Константа.ЧасовойПояс, 1);
			Иначе
				ЗначПок	= "Дата, время: " + ВернутьДатуВремяСучЧПстрокой(ЗначПок, 0, 1);
			КонецЕсли;
		Иначе
			Если ЗначПок = "-1" Тогда
				ЗначПок = "Да";
			ИначеЕсли ЗначПок = "0" Тогда
					ЗначПок	= "Нет";
			КонецЕсли;
		КонецЕсли;
		Таб.ВывестиСекцию("СтрокаПар");
	КонецЦикла;
	Таб.ВывестиСекцию("Подвал");
	Таб.ТолькоПросмотр(1);
	Таб.Показать("Информация по марке","");	
КонецПроцедуры


(42) Тогда можно вывести информацио по всем gtin ?
Да можно конечно... Но, если товарооборот большой, то это ж.. будет, см. (34), там все верно написано...
44 Маленький Вопросик
 
08.11.25
17:57
Много интересной информации. Спасибо
45 Маленький Вопросик
 
08.11.25
20:29
Не подскажите как получить список всех gtin, числящихся на инн?
46 MWWRuza
 
гуру
08.11.25
21:46
(45) 5.5.2. Метод получения списка кодов товаров (GTIN) УОТ по ИНН страница 432 описания TrueAPI.
Но, я сам не пробовал, как-то не вижу смысла в этом.
Попробуйте, нам расскажете :-)
47 MWWRuza
 
гуру
09.11.25
02:22
(46) Сделал я такой запрос... Но, похоже зря потраченное время:
Url = "https://markirovka.crpt.ru/api/v4/true-api/product/gtin?includeSubaccount=true&limit=10&page=0&pg=water"
Ответ = "{"results":[],"total":0}"
СтрОшибка = ""

Пусто. Хотя по воде, GTIN-ы на балансе точно есть, и много.
Похоже он возвращает только те GTIN, которые регистрировал сам участник оборота в "Национальном каталоге", те, что прилетели от поставщиков - не отображаются.

PS Не только по воде. Ни по чем нет.
К сожалению, нет сейчас ключа ни одного из клиентов, кому остатки по тапочкам и шмоткам вводил в оборот, там заводили новые, типа "для остатков" GTIN, начинающиеся на "029***"... Скорее всего, по ним инфа выведется. Ну, может попадет в руки такой токен с КЭП, проверю... Или сформирую у них скриптом "Единый токен в формате UUID", и по нему у себя смогу проверить.