diff --git a/CHANGELOG.md b/CHANGELOG.md index e88ce25..3a9eec1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,20 @@ # История изменений crm3-26.rhana -Формат версии: `1.3.0.NNN` (синхронизируется с `VERSION` и `Configuration.xml`). +Формат версии: `1.3.0.NNN` / `1.3.1.NNN` (синхронизируется с `VERSION` и `Configuration.xml`). + +--- + +## 1.3.1.49 (2026-08-10) + +### Обработка РК_ЗагрузкаОстатков — подбор складов и предварительные остатки + +- Общий модуль `РК_ОбменСВнешнейБазой`: HTTP-клиент Transfer API по `РК_НастройкиПодключенияКВнешнейБазе`. +- Подбор складов исходной ИБ (`POST /v1/stock/warehouses`) в отбор на форме. +- Загрузка остатков (`POST /v1/stock/balances`, mode=`combined`) в ТЧ `ВходящиеДанные` с детализацией (кол-во, артикул, код, характеристика, серия/ГТД GUID, вид, политика, организация). +- Шаг «Сопоставить»: поиск НСИ + создание серий-заглушек `Перенос_<склад>_<дата>` по логике BSL-переноса остатков (тест / запись). +- Создание документов ввода остатков — следующий шаг (пока не реализовано). + +Пара: `ws-rhana` 0.0.0.30 (endpoint складов + `nomenclature_article`). --- diff --git a/VERSION b/VERSION index f8edff9..e77903a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.3.1.48 +1.3.1.49 diff --git a/src/CommonModules/РК_ОбменСВнешнейБазой.xml b/src/CommonModules/РК_ОбменСВнешнейБазой.xml new file mode 100644 index 0000000..198163e --- /dev/null +++ b/src/CommonModules/РК_ОбменСВнешнейБазой.xml @@ -0,0 +1,23 @@ + + + + + РК_ОбменСВнешнейБазой + + + ru + Обмен с внешней базой + + + HTTP-клиент Transfer API по настройкам РК_НастройкиПодключенияКВнешнейБазе + false + false + true + false + false + true + false + DontUse + + + diff --git a/src/CommonModules/РК_ОбменСВнешнейБазой/Ext/Module.bsl b/src/CommonModules/РК_ОбменСВнешнейБазой/Ext/Module.bsl new file mode 100644 index 0000000..0065ae1 --- /dev/null +++ b/src/CommonModules/РК_ОбменСВнешнейБазой/Ext/Module.bsl @@ -0,0 +1,190 @@ + +#Область ПрограммныйИнтерфейс + +// Настройки подключения из элемента справочника РК_НастройкиПодключенияКВнешнейБазе. +// +Функция НастройкиПодключения(Подключение) Экспорт + + Если Не ЗначениеЗаполнено(Подключение) Тогда + ВызватьИсключение "Не указано подключение к сторонней базе"; + КонецЕсли; + + Реквизиты = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(Подключение, + "АдресПодключения, Токен, Таймаут, Логин, Пароль, Активно, ИмяТекущейБазы"); + + Если Реквизиты.Активно = Ложь Тогда + ВызватьИсключение "Подключение к сторонней базе отключено (Активно = Ложь)"; + КонецЕсли; + + Адрес = СокрЛП(Строка(Реквизиты.АдресПодключения)); + Если ПустаяСтрока(Адрес) Тогда + ВызватьИсключение "В настройке подключения не заполнен АдресПодключения"; + КонецЕсли; + + Таймаут = 120; + Попытка + Таймаут = Число(Реквизиты.Таймаут); + Исключение + Таймаут = 120; + КонецПопытки; + Если Таймаут <= 0 Тогда + Таймаут = 120; + КонецЕсли; + + Настройки = Новый Структура; + Настройки.Вставить("Адрес", Адрес); + Настройки.Вставить("Токен", СокрЛП(Строка(Реквизиты.Токен))); + Настройки.Вставить("Таймаут", Таймаут); + Настройки.Вставить("Логин", СокрЛП(Строка(Реквизиты.Логин))); + Настройки.Вставить("Пароль", Строка(Реквизиты.Пароль)); + Настройки.Вставить("ИмяТекущейБазы", СокрЛП(Строка(Реквизиты.ИмяТекущейБазы))); + Возврат Настройки; + +КонецФункции + +// POST /v1/stock/warehouses на исходной ИБ. +// +Функция СписокСкладовВнешнейБазы(Подключение, ПараметрыЗапроса = Неопределено) Экспорт + + Если ПараметрыЗапроса = Неопределено Тогда + ПараметрыЗапроса = Новый Структура; + КонецЕсли; + Настройки = НастройкиПодключения(Подключение); + Возврат ВыполнитьPOST(Настройки, "v1/stock/warehouses", ПараметрыЗапроса); + +КонецФункции + +// POST /v1/stock/balances на исходной ИБ. +// +Функция ОстаткиВнешнейБазы(Подключение, ПараметрыЗапроса) Экспорт + + Если ПараметрыЗапроса = Неопределено Тогда + ПараметрыЗапроса = Новый Структура; + КонецЕсли; + Настройки = НастройкиПодключения(Подключение); + Возврат ВыполнитьPOST(Настройки, "v1/stock/balances", ПараметрыЗапроса); + +КонецФункции + +// Универсальный POST к Transfer API. +// +Функция ВыполнитьPOST(НастройкиПодключения, ОтносительныйПуть, Тело) Экспорт + + Возврат ВыполнитьHTTPЗапросЛокально(НастройкиПодключения, ОтносительныйПуть, Тело); + +КонецФункции + +#КонецОбласти + +#Область СлужебныеПроцедурыИФункции + +Функция ВыполнитьHTTPЗапросЛокально(НастройкиПодключения, ОтносительныйПуть, Тело) + + АдресБазы = СокрЛП(Строка(НастройкиПодключения.Адрес)); + Ключ = СокрЛП(Строка(НастройкиПодключения.Токен)); + Таймаут = 120; + Попытка + Таймаут = Число(НастройкиПодключения.Таймаут); + Исключение + Таймаут = 120; + КонецПопытки; + Если Таймаут <= 0 Тогда + Таймаут = 120; + КонецЕсли; + + Логин = ""; + Пароль = ""; + Если НастройкиПодключения.Свойство("Логин") Тогда + Логин = СокрЛП(Строка(НастройкиПодключения.Логин)); + КонецЕсли; + Если НастройкиПодключения.Свойство("Пароль") Тогда + Пароль = Строка(НастройкиПодключения.Пароль); + КонецЕсли; + + Если Тело = Неопределено Тогда + Тело = Новый Структура; + КонецЕсли; + + Запись = Новый ЗаписьJSON; + Запись.УстановитьСтроку(Новый ПараметрыЗаписиJSON(ПереносСтрокJSON.Нет)); + ЗаписатьJSON(Запись, Тело); + ТекстТела = Запись.Закрыть(); + + Разбор = РазобратьURL(АдресБазы); + ПутьЗапроса = Разбор.Путь; + Если Не СтрЗаканчиваетсяНа(ПутьЗапроса, "/") Тогда + ПутьЗапроса = ПутьЗапроса + "/"; + КонецЕсли; + Относительный = СокрЛП(ОтносительныйПуть); + Если СтрНачинаетсяС(Относительный, "/") Тогда + Относительный = Сред(Относительный, 2); + КонецЕсли; + ПутьЗапроса = ПутьЗапроса + Относительный; + + ПользовательHTTP = ?(ПустаяСтрока(Логин), Разбор.Пользователь, Логин); + ПарольHTTP = ?(ПустаяСтрока(Логин), Разбор.Пароль, Пароль); + + Соединение = Новый HTTPСоединение( + Разбор.Хост, + Разбор.Порт, + ПользовательHTTP, + ПарольHTTP, + , + Таймаут, + ?(Разбор.HTTPS, Новый ЗащищенноеСоединениеOpenSSL(), Неопределено)); + + ЗапросHTTP = Новый HTTPЗапрос(ПутьЗапроса); + Если Не ПустаяСтрока(Ключ) Тогда + ЗапросHTTP.Заголовки.Вставить("Authorization", "Bearer " + Ключ); + КонецЕсли; + ЗапросHTTP.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8"); + ЗапросHTTP.УстановитьТелоИзСтроки(ТекстТела, КодировкаТекста.UTF8); + + ОтветHTTP = Соединение.ОтправитьДляОбработки(ЗапросHTTP); + ТекстОтвета = ОтветHTTP.ПолучитьТелоКакСтроку(); + + Если ОтветHTTP.КодСостояния < 200 Или ОтветHTTP.КодСостояния >= 300 Тогда + ЗаписьЖурналаРегистрации("РК_ОбменСВнешнейБазой", УровеньЖурналаРегистрации.Ошибка, , , + "HTTP " + ОтветHTTP.КодСостояния + " " + Относительный + ": " + ТекстОтвета); + ВызватьИсключение "Ошибка HTTP " + ОтветHTTP.КодСостояния + ": " + ТекстОтвета; + КонецЕсли; + + Чтение = Новый ЧтениеJSON; + Чтение.УстановитьСтроку(ТекстОтвета); + Результат = ПрочитатьJSON(Чтение); + Чтение.Закрыть(); + Возврат Результат; + +КонецФункции + +Функция РазобратьURL(Адрес) + + Результат = Новый Структура("Хост, Порт, Путь, HTTPS, Пользователь, Пароль", "", 0, "", Ложь, "", ""); + + СтрокаURL = СокрЛП(Адрес); + HTTPS = СтрНачинаетсяС(НРег(СтрокаURL), "https://"); + Если СтрНачинаетсяС(НРег(СтрокаURL), "http://") Тогда + СтрокаURL = Сред(СтрокаURL, 8); + ИначеЕсли HTTPS Тогда + СтрокаURL = Сред(СтрокаURL, 9); + КонецЕсли; + Результат.HTTPS = HTTPS; + + ПозицияПути = СтрНайти(СтрокаURL, "/"); + ХостПорт = ?(ПозицияПути > 0, Лев(СтрокаURL, ПозицияПути - 1), СтрокаURL); + Результат.Путь = ?(ПозицияПути > 0, Сред(СтрокаURL, ПозицияПути), "/"); + + ПозицияПорта = СтрНайти(ХостПорт, ":"); + Если ПозицияПорта > 0 Тогда + Результат.Хост = Лев(ХостПорт, ПозицияПорта - 1); + Результат.Порт = Число(Сред(ХостПорт, ПозицияПорта + 1)); + Иначе + Результат.Хост = ХостПорт; + Результат.Порт = ?(HTTPS, 443, 80); + КонецЕсли; + + Возврат Результат; + +КонецФункции + +#КонецОбласти diff --git a/src/Configuration.xml b/src/Configuration.xml index f524a20..14c1bb2 100644 --- a/src/Configuration.xml +++ b/src/Configuration.xml @@ -62,7 +62,7 @@ Role.РК_ОсновнаяРоль - 1.3.1.48 + 1.3.1.49 Language.Русский @@ -95,6 +95,7 @@ РК_ОбщегоНазначения РК_ОбщегоНазначенияКлиентСервер РК_ОбщегоНазначенияВызовСервера + РК_ОбменСВнешнейБазой ОбщегоНазначенияКлиентСервер МенеджерОбменаЧерезУниверсальныйФормат ОбменДаннымиXDTOСервер diff --git a/src/DataProcessors/РК_ЗагрузкаОстатков.xml b/src/DataProcessors/РК_ЗагрузкаОстатков.xml index 98be217..bffd6c2 100644 --- a/src/DataProcessors/РК_ЗагрузкаОстатков.xml +++ b/src/DataProcessors/РК_ЗагрузкаОстатков.xml @@ -468,6 +468,867 @@ Auto + + + Количество + + + ru + Количество + + + + + xs:decimal + + 15 + 3 + Any + + + false + + + + false + + false + false + + + false + 0 + DontCheck + Items + + + Auto + Auto + + + Auto + + + + + + КоличествоКОтгрузке + + + ru + К отгрузке + + + + + xs:decimal + + 15 + 3 + Any + + + false + + + + false + + false + false + + + false + 0 + DontCheck + Items + + + Auto + Auto + + + Auto + + + + + + КоличествоОрганизации + + + ru + Кол. организации + + + + + xs:decimal + + 15 + 3 + Any + + + false + + + + false + + false + false + + + false + 0 + DontCheck + Items + + + Auto + Auto + + + Auto + + + + + + Артикул + + + ru + Артикул + + + + + xs:string + + 50 + Variable + + + false + + + + false + + false + false + + + false + + DontCheck + Items + + + Auto + Auto + + + Auto + + + + + + НоменклатураКод + + + ru + Код + + + + + xs:string + + 50 + Variable + + + false + + + + false + + false + false + + + false + + DontCheck + Items + + + Auto + Auto + + + Auto + + + + + + ХарактеристикаНаименование + + + ru + Характеристика + + + + + xs:string + + 150 + Variable + + + false + + + + false + + false + false + + + false + + DontCheck + Items + + + Auto + Auto + + + Auto + + + + + + ХарактеристикаИдентификатор + + + ru + Характеристика идентификатор + + + + + v8:UUID + + false + + + + false + + false + false + + + false + + DontCheck + Items + + + Auto + Auto + + + Auto + + + + + + СерияИдентификатор + + + ru + Серия идентификатор + + + + + v8:UUID + + false + + + + false + + false + false + + + false + + DontCheck + Items + + + Auto + Auto + + + Auto + + + + + + ГТДИдентификатор + + + ru + ГТД идентификатор + + + + + v8:UUID + + false + + + + false + + false + false + + + false + + DontCheck + Items + + + Auto + Auto + + + Auto + + + + + + ВидНоменклатурыНаименование + + + ru + Вид номенклатуры + + + + + xs:string + + 150 + Variable + + + false + + + + false + + false + false + + + false + + DontCheck + Items + + + Auto + Auto + + + Auto + + + + + + ВидНоменклатурыИдентификатор + + + ru + Вид номенклатуры идентификатор + + + + + v8:UUID + + false + + + + false + + false + false + + + false + + DontCheck + Items + + + Auto + Auto + + + Auto + + + + + + ПолитикаСерии + + + ru + Политика серии + + + + + xs:string + + 100 + Variable + + + false + + + + false + + false + false + + + false + + DontCheck + Items + + + Auto + Auto + + + Auto + + + + + + ПолитикаХарактеристик + + + ru + Политика характеристик + + + + + xs:string + + 100 + Variable + + + false + + + + false + + false + false + + + false + + DontCheck + Items + + + Auto + Auto + + + Auto + + + + + + ОрганизацияНаименование + + + ru + Организация + + + + + xs:string + + 150 + Variable + + + false + + + + false + + false + false + + + false + + DontCheck + Items + + + Auto + Auto + + + Auto + + + + + + ОрганизацияИдентификатор + + + ru + Организация идентификатор + + + + + v8:UUID + + false + + + + false + + false + false + + + false + + DontCheck + Items + + + Auto + Auto + + + Auto + + + + + + Номенклатура + + + ru + Номенклатура + + + + + cfg:CatalogRef.Номенклатура + + false + + + + false + + false + false + + + false + + DontCheck + Items + + + Auto + Auto + + + Auto + + + + + + Склад + + + ru + Склад + + + + + cfg:CatalogRef.Склады + + false + + + + false + + false + false + + + false + + DontCheck + Items + + + Auto + Auto + + + Auto + + + + + + Характеристика + + + ru + Характеристика (цель) + + + + + cfg:CatalogRef.ХарактеристикиНоменклатуры + + false + + + + false + + false + false + + + false + + DontCheck + Items + + + Auto + Auto + + + Auto + + + + + + СерияСсылка + + + ru + Серия (цель) + + + + + cfg:CatalogRef.СерииНоменклатуры + + false + + + + false + + false + false + + + false + + DontCheck + Items + + + Auto + Auto + + + Auto + + + + + + НомерГТДСсылка + + + ru + Номер ГТД (цель) + + + + + cfg:CatalogRef.НомераГТД + + false + + + + false + + false + false + + + false + + DontCheck + Items + + + Auto + Auto + + + Auto + + + + + + Сопоставлено + + + ru + Сопоставлено + + + + + xs:boolean + + false + + + + false + + false + false + + + false + false + DontCheck + Items + + + Auto + Auto + + + Auto + + + + + + КомментарийСопоставления + + + ru + Комментарий сопоставления + + + + + xs:string + + 500 + Variable + + + false + + + + false + + false + false + + + false + + DontCheck + Items + + + Auto + Auto + + + Auto + + +
Форма
diff --git a/src/DataProcessors/РК_ЗагрузкаОстатков/Ext/ObjectModule.bsl b/src/DataProcessors/РК_ЗагрузкаОстатков/Ext/ObjectModule.bsl new file mode 100644 index 0000000..cbc5d36 --- /dev/null +++ b/src/DataProcessors/РК_ЗагрузкаОстатков/Ext/ObjectModule.bsl @@ -0,0 +1,439 @@ + +#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда + +#Область ПрограммныйИнтерфейс + +// Заполняет ТЧ ВходящиеДанные строками остатков Transfer API (mode=combined по умолчанию). +// +Процедура ЗаполнитьВходящиеДанныеИзОтветаОстатков(ОтветAPI, ОчищатьПередЗаполнением = Истина) Экспорт + + Если ОчищатьПередЗаполнением Тогда + ВходящиеДанные.Очистить(); + КонецЕсли; + + СтрокиОтвета = Неопределено; + Если ТипЗнч(ОтветAPI) = Тип("Структура") Или ТипЗнч(ОтветAPI) = Тип("Соответствие") Тогда + СтрокиОтвета = ЗначениеСвойства(ОтветAPI, "rows", Неопределено); + КонецЕсли; + Если ТипЗнч(СтрокиОтвета) <> Тип("Массив") Тогда + Возврат; + КонецЕсли; + + Для Каждого СтрокаAPI Из СтрокиОтвета Цикл + НовСтр = ВходящиеДанные.Добавить(); + ЗаполнитьСтрокуВходящихДанныхИзAPI(НовСтр, СтрокаAPI); + КонецЦикла; + +КонецПроцедуры + +// Сопоставление строк ТЧ с НСИ целевой ИБ + создание серий-заглушек при необходимости. +// Алгоритм — по логике scripts/generate_balances_apply_bsl.py (артикул/GUID/код/имя; серии Перенос_*). +// +// Параметры: +// РежимТест - Булево - Истина: только поиск, без создания серий/характеристик +// +// Возвращаемое значение: +// Структура - Сопоставлено, НеСопоставлено, СозданоСерий, СозданоХарактеристик +// +Функция СопоставитьВходящиеДанные(РежимТест = Истина) Экспорт + + Результат = Новый Структура; + Результат.Вставить("Сопоставлено", 0); + Результат.Вставить("НеСопоставлено", 0); + Результат.Вставить("СозданоСерий", 0); + Результат.Вставить("СозданоХарактеристик", 0); + + СуффиксДатыСер = Формат(?(ЗначениеЗаполнено(ДатаДокументовВвода), ДатаДокументовВвода, ДатаОстатков), "ДФ=yyyyMMdd"); + Если ПустаяСтрока(СуффиксДатыСер) Тогда + СуффиксДатыСер = Формат(ТекущаяДатаСеанса(), "ДФ=yyyyMMdd"); + КонецЕсли; + + КэшТребуетсяСерия = Новый Соответствие; + КэшСерий = Новый Соответствие; + + Для Каждого СтрТ Из ВходящиеДанные Цикл + + СтрТ.Сопоставлено = Ложь; + СтрТ.КомментарийСопоставления = ""; + СтрТ.Номенклатура = Справочники.Номенклатура.ПустаяСсылка(); + СтрТ.Склад = Справочники.Склады.ПустаяСсылка(); + СтрТ.Характеристика = Справочники.ХарактеристикиНоменклатуры.ПустаяСсылка(); + СтрТ.СерияСсылка = Справочники.СерииНоменклатуры.ПустаяСсылка(); + СтрТ.НомерГТДСсылка = Справочники.НомераГТД.ПустаяСсылка(); + + Ном = НайтиНоменклатуруСтроки(СтрТ); + Если Не ЗначениеЗаполнено(Ном) Тогда + СтрТ.КомментарийСопоставления = "Номенклатура не найдена"; + Результат.НеСопоставлено = Результат.НеСопоставлено + 1; + Продолжить; + КонецЕсли; + СтрТ.Номенклатура = Ном; + + СкладЦель = НайтиСкладСтроки(СтрТ); + Если Не ЗначениеЗаполнено(СкладЦель) Тогда + СтрТ.КомментарийСопоставления = "Склад не найден"; + Результат.НеСопоставлено = Результат.НеСопоставлено + 1; + Продолжить; + КонецЕсли; + СтрТ.Склад = СкладЦель; + + Хар = НайтиИлиСоздатьХарактеристику(СтрТ, Ном, РежимТест, Результат); + СтрТ.Характеристика = Хар; + + Сер = НайтиИлиСоздатьСерию(СтрТ, Ном, СкладЦель, СуффиксДатыСер, РежимТест, + КэшТребуетсяСерия, КэшСерий, Результат); + СтрТ.СерияСсылка = Сер; + + Если ЗначениеЗаполнено(СтрТ.ГТД) Тогда + КодГТД = СокрЛП(СтрТ.ГТД); + СтрТ.НомерГТДСсылка = Справочники.НомераГТД.НайтиПоКоду(КодГТД); + Если Не ЗначениеЗаполнено(СтрТ.НомерГТДСсылка) Тогда + СтрТ.НомерГТДСсылка = Справочники.НомераГТД.НайтиПоРеквизиту("РегистрационныйНомер", КодГТД); + КонецЕсли; + Если Не ЗначениеЗаполнено(СтрТ.НомерГТДСсылка) Тогда + СтрТ.НомерГТДСсылка = Справочники.НомераГТД.НайтиПоНаименованию(КодГТД, Истина); + КонецЕсли; + Если Не ЗначениеЗаполнено(СтрТ.НомерГТДСсылка) Тогда + СсылкаГТД = СсылкаПоUUID(Справочники.НомераГТД, СтрТ.ГТДИдентификатор); + Если ЗначениеЗаполнено(СсылкаГТД) И ОбщегоНазначения.СсылкаСуществует(СсылкаГТД) Тогда + СтрТ.НомерГТДСсылка = СсылкаГТД; + КонецЕсли; + КонецЕсли; + КонецЕсли; + + СтрТ.Сопоставлено = Истина; + Если ПустаяСтрока(СтрТ.КомментарийСопоставления) Тогда + СтрТ.КомментарийСопоставления = "OK"; + КонецЕсли; + Результат.Сопоставлено = Результат.Сопоставлено + 1; + + КонецЦикла; + + Возврат Результат; + +КонецФункции + +#КонецОбласти + +#Область СлужебныеПроцедурыИФункции + +Процедура ЗаполнитьСтрокуВходящихДанныхИзAPI(НовСтр, СтрокаAPI) + + НовСтр.НоменклатураИдентификатор = UUIDИзСтроки(ЗначениеСвойства(СтрокаAPI, "nomenclature_guid", "")); + НовСтр.НоменклатураНаименование = СокрЛП(Строка(ЗначениеСвойства(СтрокаAPI, "nomenclature_name", ""))); + НовСтр.НоменклатураКод = СокрЛП(Строка(ЗначениеСвойства(СтрокаAPI, "nomenclature_code", ""))); + НовСтр.Артикул = СокрЛП(Строка(ЗначениеСвойства(СтрокаAPI, "nomenclature_article", ""))); + + НовСтр.СкладИдентификатор = UUIDИзСтроки(ЗначениеСвойства(СтрокаAPI, "warehouse_guid", "")); + НовСтр.СкладНаименование = СокрЛП(Строка(ЗначениеСвойства(СтрокаAPI, "warehouse_name", ""))); + + НовСтр.ЕдИзмИдентификатор = UUIDИзСтроки(ЗначениеСвойства(СтрокаAPI, "unit_guid", "")); + НовСтр.ЕдИзм = СокрЛП(Строка(ЗначениеСвойства(СтрокаAPI, "unit_name", ""))); + Если ПустаяСтрока(НовСтр.ЕдИзм) Тогда + НовСтр.ЕдИзм = СокрЛП(Строка(ЗначениеСвойства(СтрокаAPI, "unit_code", ""))); + КонецЕсли; + + НовСтр.ХарактеристикаИдентификатор = UUIDИзСтроки(ЗначениеСвойства(СтрокаAPI, "characteristic_guid", "")); + НовСтр.ХарактеристикаНаименование = СокрЛП(Строка(ЗначениеСвойства(СтрокаAPI, "characteristic_name", ""))); + + НовСтр.СерияИдентификатор = UUIDИзСтроки(ЗначениеСвойства(СтрокаAPI, "series_guid", "")); + НовСтр.Серия = СокрЛП(Строка(ЗначениеСвойства(СтрокаAPI, "series_name", ""))); + + НовСтр.ГТДИдентификатор = UUIDИзСтроки(ЗначениеСвойства(СтрокаAPI, "gtd_guid", "")); + НовСтр.ГТД = СокрЛП(Строка(ЗначениеСвойства(СтрокаAPI, "gtd_name", ""))); + + НовСтр.ОрганизацияИдентификатор = UUIDИзСтроки(ЗначениеСвойства(СтрокаAPI, "organization_guid", "")); + НовСтр.ОрганизацияНаименование = СокрЛП(Строка(ЗначениеСвойства(СтрокаAPI, "organization_name", ""))); + + НовСтр.Количество = ЧислоИзЗначения(ЗначениеСвойства(СтрокаAPI, "qty_warehouse", + ЗначениеСвойства(СтрокаAPI, "qty_org", 0)), 0); + НовСтр.КоличествоКОтгрузке = ЧислоИзЗначения(ЗначениеСвойства(СтрокаAPI, "qty_to_ship", 0), 0); + НовСтр.КоличествоОрганизации = ЧислоИзЗначения(ЗначениеСвойства(СтрокаAPI, "qty_org", 0), 0); + + НовСтр.ВидНоменклатурыИдентификатор = UUIDИзСтроки(ЗначениеСвойства(СтрокаAPI, "policy_kind_guid", "")); + НовСтр.ВидНоменклатурыНаименование = СокрЛП(Строка(ЗначениеСвойства(СтрокаAPI, "policy_kind_name", ""))); + НовСтр.ПолитикаСерии = СокрЛП(Строка(ЗначениеСвойства(СтрокаAPI, "policy_use_series", ""))); + НовСтр.ПолитикаХарактеристик = СокрЛП(Строка(ЗначениеСвойства(СтрокаAPI, "policy_use_characteristics", ""))); + + НовСтр.Сопоставлено = Ложь; + НовСтр.КомментарийСопоставления = ""; + +КонецПроцедуры + +Функция НайтиНоменклатуруСтроки(СтрТ) + + Ном = Справочники.Номенклатура.ПустаяСсылка(); + Арт = СокрЛП(СтрТ.Артикул); + ИмяНом = СокрЛП(СтрТ.НоменклатураНаименование); + КодНом = СокрЛП(СтрТ.НоменклатураКод); + + Если ЗначениеЗаполнено(Арт) Тогда + Ном = Справочники.Номенклатура.НайтиПоРеквизиту("Артикул", Арт); + КонецЕсли; + + Если Не ЗначениеЗаполнено(Ном) Тогда + СсылкаПоГуид = СсылкаПоUUID(Справочники.Номенклатура, СтрТ.НоменклатураИдентификатор); + Если ЗначениеЗаполнено(СсылкаПоГуид) И ОбщегоНазначения.СсылкаСуществует(СсылкаПоГуид) Тогда + Ном = СсылкаПоГуид; + КонецЕсли; + КонецЕсли; + + Если Не ЗначениеЗаполнено(Ном) И ЗначениеЗаполнено(КодНом) Тогда + Ном = Справочники.Номенклатура.НайтиПоКоду(КодНом); + КонецЕсли; + + Если Не ЗначениеЗаполнено(Ном) И ЗначениеЗаполнено(ИмяНом) Тогда + Ном = Справочники.Номенклатура.НайтиПоНаименованию(ИмяНом, Истина); + КонецЕсли; + + Если ЗначениеЗаполнено(Ном) И ЗначениеЗаполнено(ИмяНом) Тогда + Если СокрЛП(Ном.Наименование) <> ИмяНом Тогда + СтрТ.КомментарийСопоставления = "Номенклатура не совпала по имени: " + ИмяНом + " → " + Ном.Наименование; + Возврат Справочники.Номенклатура.ПустаяСсылка(); + КонецЕсли; + КонецЕсли; + + Возврат Ном; + +КонецФункции + +Функция НайтиСкладСтроки(СтрТ) + + СкладЦель = СсылкаПоUUID(Справочники.Склады, СтрТ.СкладИдентификатор); + Если ЗначениеЗаполнено(СкладЦель) И ОбщегоНазначения.СсылкаСуществует(СкладЦель) Тогда + Возврат СкладЦель; + КонецЕсли; + + ИмяСкл = СокрЛП(СтрТ.СкладНаименование); + Если ЗначениеЗаполнено(ИмяСкл) Тогда + Возврат Справочники.Склады.НайтиПоНаименованию(ИмяСкл, Истина); + КонецЕсли; + Возврат Справочники.Склады.ПустаяСсылка(); + +КонецФункции + +Функция НайтиИлиСоздатьХарактеристику(СтрТ, Ном, РежимТест, Результат) + + Хар = Справочники.ХарактеристикиНоменклатуры.ПустаяСсылка(); + ИмяХар = СокрЛП(СтрТ.ХарактеристикаНаименование); + ВидНом = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Ном, "ВидНоменклатуры"); + + ИспХар = Ложь; + Попытка + ИспХар = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Ном, "ВидНоменклатуры.ИспользоватьХарактеристики") = Истина; + Исключение + Попытка + ИспХар = ВидНом.ИспользоватьХарактеристики; + Исключение + КонецПопытки; + КонецПопытки; + + Если ЗначениеЗаполнено(ИмяХар) Тогда + Хар = Справочники.ХарактеристикиНоменклатуры.НайтиПоНаименованию(ИмяХар, Истина, , Ном); + Если Не ЗначениеЗаполнено(Хар) Тогда + Хар = Справочники.ХарактеристикиНоменклатуры.НайтиПоНаименованию(ИмяХар, Истина, , ВидНом); + КонецЕсли; + КонецЕсли; + + Если Не ЗначениеЗаполнено(Хар) Тогда + СсылкаПоГуид = СсылкаПоUUID(Справочники.ХарактеристикиНоменклатуры, СтрТ.ХарактеристикаИдентификатор); + Если ЗначениеЗаполнено(СсылкаПоГуид) И ОбщегоНазначения.СсылкаСуществует(СсылкаПоГуид) Тогда + ВладХар = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(СсылкаПоГуид, "Владелец"); + Если ВладХар = Ном Или ВладХар = ВидНом Тогда + Хар = СсылкаПоГуид; + КонецЕсли; + КонецЕсли; + КонецЕсли; + + Если Не ЗначениеЗаполнено(Хар) И ИспХар И ЗначениеЗаполнено(ИмяХар) И Не РежимТест Тогда + Попытка + НовХар = Справочники.ХарактеристикиНоменклатуры.СоздатьЭлемент(); + НовХар.Владелец = ВидНом; + НовХар.Наименование = ИмяХар; + НовХар.Записать(); + Хар = НовХар.Ссылка; + Результат.СозданоХарактеристик = Результат.СозданоХарактеристик + 1; + Исключение + СтрТ.КомментарийСопоставления = "Ошибка создания характеристики: " + ИмяХар; + КонецПопытки; + КонецЕсли; + + Если Не ИспХар Тогда + Хар = Справочники.ХарактеристикиНоменклатуры.ПустаяСсылка(); + КонецЕсли; + + Возврат Хар; + +КонецФункции + +Функция НайтиИлиСоздатьСерию(СтрТ, Ном, СкладЦель, СуффиксДатыСер, РежимТест, + КэшТребуетсяСерия, КэшСерий, Результат) + + Сер = Справочники.СерииНоменклатуры.ПустаяСсылка(); + ВидНом = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Ном, "ВидНоменклатуры"); + + КлючТребСер = Строка(Ном.УникальныйИдентификатор()); + ТребуетсяСерия = КэшТребуетсяСерия.Получить(КлючТребСер); + Если ТребуетсяСерия = Неопределено Тогда + ТребуетсяСерия = Ложь; + Попытка + ТребуетсяСерия = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Ном, "ВидНоменклатуры.ИспользоватьСерии") = Истина; + Исключение + Попытка + ТребуетсяСерия = ВидНом.ИспользоватьСерии; + Исключение + КонецПопытки; + КонецПопытки; + КэшТребуетсяСерия.Вставить(КлючТребСер, ТребуетсяСерия); + КонецЕсли; + + ИмяСерии = СокрЛП(СтрТ.Серия); + Если Не ЗначениеЗаполнено(ИмяСерии) И ТребуетсяСерия Тогда + КодСклЗагл = ""; + Попытка + КодСклЗагл = СокрЛП(Строка(ОбщегоНазначения.ЗначениеРеквизитаОбъекта(СкладЦель, "Код"))); + Исключение + КодСклЗагл = ""; + КонецПопытки; + Если ПустаяСтрока(КодСклЗагл) Тогда + КодСклЗагл = Лев(СтрЗаменить(Строка(СкладЦель.УникальныйИдентификатор()), "-", ""), 8); + КонецЕсли; + ИмяСерии = "Перенос_" + КодСклЗагл + "_" + СуффиксДатыСер; + СтрТ.Серия = ИмяСерии; + КонецЕсли; + + Если Не ТребуетсяСерия И Не ЗначениеЗаполнено(ИмяСерии) Тогда + Возврат Сер; + КонецЕсли; + + СсылкаПоГуид = СсылкаПоUUID(Справочники.СерииНоменклатуры, СтрТ.СерияИдентификатор); + Если ЗначениеЗаполнено(СсылкаПоГуид) И ОбщегоНазначения.СсылкаСуществует(СсылкаПоГуид) Тогда + Возврат СсылкаПоГуид; + КонецЕсли; + + ВидСер = Неопределено; + ИспНомерСерии = Истина; + Попытка + НастрСер = Справочники.ВидыНоменклатуры.НастройкиИспользованияСерий(ВидНом, СкладЦель); + ВидСер = НастрСер.ВладелецСерий; + ИспНомерСерии = НастрСер.ИспользоватьНомерСерии; + Исключение + ВидСер = ВидНом; + КонецПопытки; + Если Не ЗначениеЗаполнено(ВидСер) Тогда + ВидСер = ВидНом; + КонецЕсли; + + КлючКэшСер = Строка(ВидСер.УникальныйИдентификатор()) + "|" + ИмяСерии; + СерИзКэш = КэшСерий.Получить(КлючКэшСер); + Если СерИзКэш <> Неопределено Тогда + Возврат СерИзКэш; + КонецЕсли; + + Если ИспНомерСерии Тогда + Сер = Справочники.СерииНоменклатуры.НайтиПоРеквизиту("Номер", ИмяСерии, , ВидСер); + КонецЕсли; + Если Не ЗначениеЗаполнено(Сер) Тогда + Сер = Справочники.СерииНоменклатуры.НайтиПоНаименованию(ИмяСерии, Истина, , ВидСер); + КонецЕсли; + + Если Не ЗначениеЗаполнено(Сер) И Не РежимТест И (ТребуетсяСерия Или ЗначениеЗаполнено(ИмяСерии)) Тогда + Попытка + ОбСер = Справочники.СерииНоменклатуры.ПустойОбъект(ВидСер); + Если ИспНомерСерии Тогда + НомерСер = ИмяСерии; + Если СтрНачинаетсяС(ИмяСерии, "Перенос_") Тогда + НомерСер = Сред(ИмяСерии, СтрДлина("Перенос_") + 1); + КонецЕсли; + ОбСер.Номер = НомерСер; + Иначе + Попытка + ОбСер.Наименование = ИмяСерии; + Исключение + КонецПопытки; + КонецЕсли; + ОбСер.Записать(); + Сер = ОбСер.Ссылка; + Результат.СозданоСерий = Результат.СозданоСерий + 1; + Исключение + СтрТ.КомментарийСопоставления = "Ошибка создания серии: " + ИмяСерии; + КонецПопытки; + КонецЕсли; + + Если ЗначениеЗаполнено(Сер) Тогда + КэшСерий.Вставить(КлючКэшСер, Сер); + ИначеЕсли ТребуетсяСерия Тогда + Если ПустаяСтрока(СтрТ.КомментарийСопоставления) Или СтрТ.КомментарийСопоставления = "OK" Тогда + СтрТ.КомментарийСопоставления = "Серия не найдена" + ?(РежимТест, " (тест)", ""); + КонецЕсли; + КонецЕсли; + + Возврат Сер; + +КонецФункции + +Функция СсылкаПоUUID(Менеджер, Идентификатор) + + Если Не ЗначениеЗаполнено(Идентификатор) Тогда + Возврат Менеджер.ПустаяСсылка(); + КонецЕсли; + Попытка + Возврат Менеджер.ПолучитьСсылку(Идентификатор); + Исключение + Возврат Менеджер.ПустаяСсылка(); + КонецПопытки; + +КонецФункции + +Функция UUIDИзСтроки(Значение) + + Текст = НРег(СокрЛП(Строка(Значение))); + Если ПустаяСтрока(Текст) Или Текст = "00000000-0000-0000-0000-000000000000" Тогда + Возврат Новый УникальныйИдентификатор("00000000-0000-0000-0000-000000000000"); + КонецЕсли; + Попытка + Возврат Новый УникальныйИдентификатор(Текст); + Исключение + Возврат Новый УникальныйИдентификатор("00000000-0000-0000-0000-000000000000"); + КонецПопытки; + +КонецФункции + +Функция ЗначениеСвойства(Источник, Имя, ПоУмолчанию) + + Если Источник = Неопределено Тогда + Возврат ПоУмолчанию; + КонецЕсли; + Если ТипЗнч(Источник) = Тип("Структура") Или ТипЗнч(Источник) = Тип("ФиксированнаяСтруктура") Тогда + Если Источник.Свойство(Имя) Тогда + Возврат Источник[Имя]; + КонецЕсли; + Возврат ПоУмолчанию; + КонецЕсли; + Если ТипЗнч(Источник) = Тип("Соответствие") Или ТипЗнч(Источник) = Тип("ФиксированноеСоответствие") Тогда + Значение = Источник.Получить(Имя); + Если Значение = Неопределено Тогда + Возврат ПоУмолчанию; + КонецЕсли; + Возврат Значение; + КонецЕсли; + Возврат ПоУмолчанию; + +КонецФункции + +Функция ЧислоИзЗначения(Значение, ПоУмолчанию) + + Если Значение = Неопределено Или Значение = Null Тогда + Возврат ПоУмолчанию; + КонецЕсли; + Попытка + Возврат Число(Значение); + Исключение + Возврат ПоУмолчанию; + КонецПопытки; + +КонецФункции + +#КонецОбласти + +#КонецЕсли diff --git a/src/DataProcessors/РК_ЗагрузкаОстатков/Forms/ПодборСкладов/Ext/Form.xml b/src/DataProcessors/РК_ЗагрузкаОстатков/Forms/ПодборСкладов/Ext/Form.xml index aae365c..8a35d5b 100644 --- a/src/DataProcessors/РК_ЗагрузкаОстатков/Forms/ПодборСкладов/Ext/Form.xml +++ b/src/DataProcessors/РК_ЗагрузкаОстатков/Forms/ПодборСкладов/Ext/Form.xml @@ -1,6 +1,18 @@ 
- + + + + + + + ПриСозданииНаСервере + Добавление @@ -146,4 +158,21 @@ + + + + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>Перенести в отбор</v8:content> + </v8:item> + + + + ru + Перенести отмеченные склады в отбор + + + ПеренестиВОтбор + + \ No newline at end of file diff --git a/src/DataProcessors/РК_ЗагрузкаОстатков/Forms/ПодборСкладов/Ext/Form/Module.bsl b/src/DataProcessors/РК_ЗагрузкаОстатков/Forms/ПодборСкладов/Ext/Form/Module.bsl new file mode 100644 index 0000000..33ed57c --- /dev/null +++ b/src/DataProcessors/РК_ЗагрузкаОстатков/Forms/ПодборСкладов/Ext/Form/Module.bsl @@ -0,0 +1,78 @@ + +&НаСервере +Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка) + + Добавление = Истина; + Подключение = Неопределено; + Если Параметры.Свойство("ПодключениеКСтороннейБазе", Подключение) Тогда + Объект.ПодключениеКСтороннейБазе = Подключение; + КонецЕсли; + ЗаполнитьСписокСкладовНаСервере(); + +КонецПроцедуры + +&НаКлиенте +Процедура ПеренестиВОтбор(Команда) + + Выбранные = Новый Массив; + Для Каждого Стр Из СписокСкладовВнешнейБазы Цикл + Если Стр.Отметка Тогда + Выбранные.Добавить(Новый Структура("Наименование, Идентификатор, Отметка", + Стр.Наименование, Стр.Идентификатор, Истина)); + КонецЕсли; + КонецЦикла; + Закрыть(Новый Структура("Добавление, Склады", Добавление, Выбранные)); + +КонецПроцедуры + +&НаСервере +Процедура ЗаполнитьСписокСкладовНаСервере() + + Если Не ЗначениеЗаполнено(Объект.ПодключениеКСтороннейБазе) Тогда + Возврат; + КонецЕсли; + + Ответ = РК_ОбменСВнешнейБазой.СписокСкладовВнешнейБазы(Объект.ПодключениеКСтороннейБазе); + Строки = Неопределено; + Если ТипЗнч(Ответ) = Тип("Структура") Или ТипЗнч(Ответ) = Тип("Соответствие") Тогда + Если ТипЗнч(Ответ) = Тип("Структура") Тогда + Если Ответ.Свойство("rows") Тогда + Строки = Ответ.rows; + КонецЕсли; + Иначе + Строки = Ответ.Получить("rows"); + КонецЕсли; + КонецЕсли; + Если ТипЗнч(Строки) <> Тип("Массив") Тогда + Возврат; + КонецЕсли; + + СписокСкладовВнешнейБазы.Очистить(); + Для Каждого СтрокаAPI Из Строки Цикл + ГуидТекст = ""; + Имя = ""; + Если ТипЗнч(СтрокаAPI) = Тип("Структура") Тогда + Если СтрокаAPI.Свойство("guid") Тогда + ГуидТекст = СокрЛП(Строка(СтрокаAPI.guid)); + КонецЕсли; + Если СтрокаAPI.Свойство("name") Тогда + Имя = СокрЛП(Строка(СтрокаAPI.name)); + КонецЕсли; + ИначеЕсли ТипЗнч(СтрокаAPI) = Тип("Соответствие") Тогда + ГуидТекст = СокрЛП(Строка(СтрокаAPI.Получить("guid"))); + Имя = СокрЛП(Строка(СтрокаAPI.Получить("name"))); + КонецЕсли; + Если ПустаяСтрока(ГуидТекст) Тогда + Продолжить; + КонецЕсли; + НовСтр = СписокСкладовВнешнейБазы.Добавить(); + НовСтр.Наименование = Имя; + Попытка + НовСтр.Идентификатор = Новый УникальныйИдентификатор(ГуидТекст); + Исключение + Продолжить; + КонецПопытки; + НовСтр.Отметка = Ложь; + КонецЦикла; + +КонецПроцедуры diff --git a/src/DataProcessors/РК_ЗагрузкаОстатков/Forms/Форма/Ext/Form.xml b/src/DataProcessors/РК_ЗагрузкаОстатков/Forms/Форма/Ext/Form.xml index d8bf30f..d014aef 100644 --- a/src/DataProcessors/РК_ЗагрузкаОстатков/Forms/Форма/Ext/Form.xml +++ b/src/DataProcessors/РК_ЗагрузкаОстатков/Forms/Форма/Ext/Form.xml @@ -6,7 +6,24 @@ Загрузка остатков из внешней базы - + + + + + + + + ПриСозданииНаСервере + Объект.ПодключениеКСтороннейБазе @@ -45,7 +62,7 @@ <v8:item> <v8:lang>ru</v8:lang> - <v8:content>Водящие данные</v8:content> + <v8:content>Входящие данные</v8:content> </v8:item> @@ -143,6 +160,74 @@ + + + Объект.ВходящиеДанные.Количество + EnterOnInput + + + + + Объект.ВходящиеДанные.Артикул + EnterOnInput + + + + + Объект.ВходящиеДанные.НоменклатураКод + EnterOnInput + + + + + Объект.ВходящиеДанные.ХарактеристикаНаименование + EnterOnInput + + + + + Объект.ВходящиеДанные.ВидНоменклатурыНаименование + EnterOnInput + + + + + Объект.ВходящиеДанные.ОрганизацияНаименование + EnterOnInput + + + + + Объект.ВходящиеДанные.Номенклатура + EnterOnInput + + + + + Объект.ВходящиеДанные.Склад + EnterOnInput + + + + + Объект.ВходящиеДанные.СерияСсылка + EnterOnInput + + + + + Объект.ВходящиеДанные.Сопоставлено + EnterOnInput + Auto + + + + + Объект.ВходящиеДанные.КомментарийСопоставления + EnterOnInput + + + @@ -325,5 +410,35 @@ ПодобратьСклады + + + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>Загрузить остатки</v8:content> + </v8:item> + + + + ru + Загрузить остатки из исходной базы + + + ЗагрузитьОстатки + + + + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>Сопоставить</v8:content> + </v8:item> + + + + ru + Сопоставить НСИ и серии + + + Сопоставить + \ No newline at end of file diff --git a/src/DataProcessors/РК_ЗагрузкаОстатков/Forms/Форма/Ext/Form/Module.bsl b/src/DataProcessors/РК_ЗагрузкаОстатков/Forms/Форма/Ext/Form/Module.bsl index 37bd1ef..a59c694 100644 --- a/src/DataProcessors/РК_ЗагрузкаОстатков/Forms/Форма/Ext/Form/Module.bsl +++ b/src/DataProcessors/РК_ЗагрузкаОстатков/Forms/Форма/Ext/Form/Module.bsl @@ -1,10 +1,232 @@  +#Область ОбработчикиСобытийФормы + &НаСервере -Процедура ПодобратьСкладыНаСервере() - // Вставить содержимое обработчика. +Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка) + + Если Не ЗначениеЗаполнено(Объект.ПодключениеКСтороннейБазе) Тогда + Попытка + Объект.ПодключениеКСтороннейБазе = Константы.РК_РабочееПодключениеЧерезАПИ.Получить(); + Исключение + КонецПопытки; + КонецЕсли; + + Если Не ЗначениеЗаполнено(Объект.ДатаОстатков) Тогда + Объект.ДатаОстатков = КонецДня(НачалоМесяца(ТекущаяДатаСеанса()) - 1); + КонецЕсли; + Если Не ЗначениеЗаполнено(Объект.ДатаДокументовВвода) Тогда + Объект.ДатаДокументовВвода = Объект.ДатаОстатков; + КонецЕсли; + КонецПроцедуры +#КонецОбласти + +#Область ОбработчикиКомандФормы + &НаКлиенте Процедура ПодобратьСклады(Команда) + + Если Не ЗначениеЗаполнено(Объект.ПодключениеКСтороннейБазе) Тогда + ПоказатьПредупреждение(, "Укажите подключение к сторонней базе"); + Возврат; + КонецЕсли; + ПодобратьСкладыНаСервере(); + Элементы.ГруппаСтраницы.ТекущаяСтраница = Элементы.ГруппаОтбор; + КонецПроцедуры + +&НаКлиенте +Процедура ЗагрузитьОстатки(Команда) + + Если Не ЗначениеЗаполнено(Объект.ПодключениеКСтороннейБазе) Тогда + ПоказатьПредупреждение(, "Укажите подключение к сторонней базе"); + Возврат; + КонецЕсли; + Если Не ЗначениеЗаполнено(Объект.ДатаОстатков) Тогда + ПоказатьПредупреждение(, "Укажите дату остатков"); + Возврат; + КонецЕсли; + + Количество = ЗагрузитьОстаткиНаСервере(); + Элементы.ГруппаСтраницы.ТекущаяСтраница = Элементы.ГруппаВходящиеДанные; + ПоказатьОповещениеПользователя("Загрузка остатков", , "Загружено строк: " + Формат(Количество, "ЧГ=0")); + +КонецПроцедуры + +&НаКлиенте +Процедура Сопоставить(Команда) + + Если Объект.ВходящиеДанные.Количество() = 0 Тогда + ПоказатьПредупреждение(, "Сначала загрузите остатки"); + Возврат; + КонецЕсли; + + ДопПараметры = Новый Структура("РежимТест", Истина); + Описание = Новый ОписаниеОповещения("СопоставитьПослеВопроса", ЭтотОбъект, ДопПараметры); + ПоказатьВопрос(Описание, + "Создавать отсутствующие серии и характеристики?" + Символы.ПС + + "Да — запись; Нет — только поиск (тест); Отмена — прервать.", + РежимДиалогаВопрос.ДаНетОтмена); + +КонецПроцедуры + +&НаКлиенте +Процедура СопоставитьПослеВопроса(РезультатВопроса, ДопПараметры) Экспорт + + Если РезультатВопроса = КодВозвратаДиалога.Отмена Тогда + Возврат; + КонецЕсли; + РежимТест = (РезультатВопроса <> КодВозвратаДиалога.Да); + Текст = СопоставитьНаСервере(РежимТест); + ПоказатьОповещениеПользователя("Сопоставление", , Текст); + +КонецПроцедуры + +#КонецОбласти + +#Область СлужебныеПроцедурыИФункции + +&НаСервере +Процедура ПодобратьСкладыНаСервере() + + Ответ = РК_ОбменСВнешнейБазой.СписокСкладовВнешнейБазы(Объект.ПодключениеКСтороннейБазе); + Строки = Неопределено; + Если ТипЗнч(Ответ) = Тип("Структура") Или ТипЗнч(Ответ) = Тип("Соответствие") Тогда + Строки = ЗначениеСвойстваОтвета(Ответ, "rows"); + КонецЕсли; + Если ТипЗнч(Строки) <> Тип("Массив") Тогда + ВызватьИсключение "Некорректный ответ /v1/stock/warehouses"; + КонецЕсли; + + БылиОтметки = Новый Соответствие; + Для Каждого Стр Из ОтборСкладовВнешнейБазы Цикл + БылиОтметки.Вставить(Строка(Стр.Идентификатор), Стр.Отметка); + КонецЦикла; + + ОтборСкладовВнешнейБазы.Очистить(); + Для Каждого СтрокаAPI Из Строки Цикл + ГуидТекст = СокрЛП(Строка(ЗначениеСвойстваОтвета(СтрокаAPI, "guid"))); + Если ПустаяСтрока(ГуидТекст) Тогда + Продолжить; + КонецЕсли; + НовСтр = ОтборСкладовВнешнейБазы.Добавить(); + НовСтр.Наименование = СокрЛП(Строка(ЗначениеСвойстваОтвета(СтрокаAPI, "name"))); + Попытка + НовСтр.Идентификатор = Новый УникальныйИдентификатор(ГуидТекст); + Исключение + Продолжить; + КонецПопытки; + СтараяОтметка = БылиОтметки.Получить(Строка(НовСтр.Идентификатор)); + НовСтр.Отметка = ?(СтараяОтметка = Неопределено, Ложь, СтараяОтметка = Истина); + КонецЦикла; + +КонецПроцедуры + +&НаСервере +Функция ЗагрузитьОстаткиНаСервере() + + СкладыGUID = Новый Массив; + Для Каждого Стр Из ОтборСкладовВнешнейБазы Цикл + Если Стр.Отметка Тогда + СкладыGUID.Добавить(Строка(Стр.Идентификатор)); + КонецЕсли; + КонецЦикла; + Если СкладыGUID.Количество() = 0 Тогда + ВызватьИсключение "Отметьте хотя бы один склад на закладке «Отбор»"; + КонецЕсли; + + Фильтры = Новый Структура; + Фильтры.Вставить("warehouses", СкладыGUID); + Фильтры.Вставить("only_nonzero", Истина); + + ВсеСтроки = Новый Массив; + Курсор = ""; + Лимит = 2000; + МаксСтраниц = 200; + + Для НомерСтраницы = 1 По МаксСтраниц Цикл + + ПараметрыЗапроса = Новый Структура; + ПараметрыЗапроса.Вставить("mode", "combined"); + ПараметрыЗапроса.Вставить("as_of", Формат(Объект.ДатаОстатков, "ДФ=yyyy-MM-ddTHH:mm:ss")); + ПараметрыЗапроса.Вставить("limit", Лимит); + ПараметрыЗапроса.Вставить("include_policy", Истина); + ПараметрыЗапроса.Вставить("filters", Фильтры); + Если Не ПустаяСтрока(Курсор) Тогда + ПараметрыЗапроса.Вставить("cursor", Курсор); + КонецЕсли; + + Ответ = РК_ОбменСВнешнейБазой.ОстаткиВнешнейБазы(Объект.ПодключениеКСтороннейБазе, ПараметрыЗапроса); + Строки = ЗначениеСвойстваОтвета(Ответ, "rows"); + Если ТипЗнч(Строки) <> Тип("Массив") Тогда + ВызватьИсключение "Некорректный ответ /v1/stock/balances"; + КонецЕсли; + Для Каждого СтрAPI Из Строки Цикл + ВсеСтроки.Добавить(СтрAPI); + КонецЦикла; + + Мета = ЗначениеСвойстваОтвета(Ответ, "meta"); + ЕстьЕще = Ложь; + Если ТипЗнч(Мета) = Тип("Структура") Или ТипЗнч(Мета) = Тип("Соответствие") Тогда + ЗначениеЕстьЕще = ЗначениеСвойстваОтвета(Мета, "has_more"); + Если ТипЗнч(ЗначениеЕстьЕще) = Тип("Булево") Тогда + ЕстьЕще = ЗначениеЕстьЕще; + ИначеЕсли ЗначениеЕстьЕще <> Неопределено Тогда + ЕстьЕще = (НРег(СокрЛП(Строка(ЗначениеЕстьЕще))) = "true" Или Строка(ЗначениеЕстьЕще) = "1"); + КонецЕсли; + КонецЕсли; + Курсор = СокрЛП(Строка(ЗначениеСвойстваОтвета(Ответ, "cursor"))); + Если Не ЕстьЕще Или ПустаяСтрока(Курсор) Или Строки.Количество() = 0 Тогда + Прервать; + КонецЕсли; + + КонецЦикла; + + Пакет = Новый Структура("rows", ВсеСтроки); + ОбъектОбработки = РеквизитФормыВЗначение("Объект"); + ОбъектОбработки.ЗаполнитьВходящиеДанныеИзОтветаОстатков(Пакет, Истина); + ЗначениеВРеквизитФормы(ОбъектОбработки, "Объект"); + + Возврат Объект.ВходящиеДанные.Количество(); + +КонецФункции + +&НаСервере +Функция СопоставитьНаСервере(РежимТест) + + ОбъектОбработки = РеквизитФормыВЗначение("Объект"); + Результат = ОбъектОбработки.СопоставитьВходящиеДанные(РежимТест); + ЗначениеВРеквизитФормы(ОбъектОбработки, "Объект"); + + Возврат СтрШаблон( + "Сопоставлено: %1; не сопоставлено: %2; создано серий: %3; создано характеристик: %4%5", + Формат(Результат.Сопоставлено, "ЧН=0; ЧГ=0"), + Формат(Результат.НеСопоставлено, "ЧН=0; ЧГ=0"), + Формат(Результат.СозданоСерий, "ЧН=0; ЧГ=0"), + Формат(Результат.СозданоХарактеристик, "ЧН=0; ЧГ=0"), + ?(РежимТест, " (тест)", "")); + +КонецФункции + +&НаСервере +Функция ЗначениеСвойстваОтвета(Источник, Имя) + + Если Источник = Неопределено Тогда + Возврат Неопределено; + КонецЕсли; + Если ТипЗнч(Источник) = Тип("Структура") Или ТипЗнч(Источник) = Тип("ФиксированнаяСтруктура") Тогда + Если Источник.Свойство(Имя) Тогда + Возврат Источник[Имя]; + КонецЕсли; + Возврат Неопределено; + КонецЕсли; + Если ТипЗнч(Источник) = Тип("Соответствие") Или ТипЗнч(Источник) = Тип("ФиксированноеСоответствие") Тогда + Возврат Источник.Получить(Имя); + КонецЕсли; + Возврат Неопределено; + +КонецФункции + +#КонецОбласти diff --git a/src/Subsystems/РК_РАНА/Subsystems/РК_ОбменСВнешнейБазой.xml b/src/Subsystems/РК_РАНА/Subsystems/РК_ОбменСВнешнейБазой.xml index 8f5f021..0d61060 100644 --- a/src/Subsystems/РК_РАНА/Subsystems/РК_ОбменСВнешнейБазой.xml +++ b/src/Subsystems/РК_РАНА/Subsystems/РК_ОбменСВнешнейБазой.xml @@ -18,6 +18,7 @@ Catalog.РК_НастройкиПодключенияКВнешнейБазе Constant.РК_РабочееПодключениеЧерезАПИ + CommonModule.РК_ОбменСВнешнейБазой DataProcessor.РК_ЗагрузкаОстатков DataProcessor.РК_ОбработкаПарнеровКонтрагентов