Для переноса настроек колонок создайте привязку данных на вкладке Данные в разделе Конфигурация. При создании привязки нужно настроить фильтрацию записей таблицы SysProfileData. Нажатием на кнопку Показать данные вы сможете увидеть какие именно данные будут привязаны. Обязательным условием фильтрации является условие по полю Ключ.
при вызове карточки через openCardInChain не удается передать значения для справочных полей. Значения простых типов: строки, числа, булева - переносятся
справочные - нет
this.openCardInChain({
id:"Id",
schemaName:"Tender1Page",
operation:"add",
moduleId:this.sandbox.id+"_AddTenderSuccessAction", //Автоматически устанавливаем значения в открываемой карточке
defaultValues:[ //Справочное поле полученное из модели - не переносится {name:"KmProjects", value:this.get("Project")}, //Компонуемый объект для заполнения справочного поля - не переносится {name:"Request", value:{
value:this.get("Id"),
id:this.get("Id"),
displayValue:this.get("RequestNumber") }}, //Число - переносится корректно {name:"CostPriceFromONIC", value:this.get("CostPriceFromOnicExcludingVat")}, //Устанавливаем значение поля "Стоимость" из запроса в поле //Строка - переносится нормально {name:"AmountKPwithoutVAT", value:this.get("Cost")} ] });
попробовал передавать ай-дишники... тоже не выходит
...
defaultValues:[//Справочное поле полученное из модели - не переносится{name:"KmProjects", value:this.get("Project").value},
//Компонуемый объект для заполнения справочного поля - не переносится{name:"Request", value:this.get("Id"),
//Число - переносится корректно{name:"CostPriceFromONIC", value:this.get("CostPriceFromOnicExcludingVat")},
//Устанавливаем значение поля "Стоимость" из запроса в поле //Строка - переносится нормально{name:"AmountKPwithoutVAT", value:this.get("Cost")}]
...
Добрый день, у нас в црм есть раздел “сделки”, куда попадают анкеты с формы на сайте, также вся эта форма преобразовывается в pdf и с помощью odata прикрепляется к той же сделке в црм в "файлы и примечания". Подскажите, пожалуйста, можно ли как-то реализовать, чтобы в случае изменения полей сделки менеджером в црм полностью пересоздавался/изменялся фал pdf с новыми параметрами или же можно как-то из бизнес-процессов вызвать php скрипт для создания pdf, передавая необходимый id?
В bpm'online можно реализовать процесс, который будет запускаться по изменению записи. Однако логику изменения/создания *.pdf файла необходимо будет реализовать на C#.
Вы можете реализовать веб-сервис, который генерирует этот отчет, а с помощью ODATA обратно прикрепляете его к сделке. А в бизнес-процессе вызвать этот веб-сервис.
спасибо за ответ :smile:, а реально ли сделать, чтобы все файлы из детали автоматически упаковывались в zip архив и при добавлении новых архив обновлялся, чтобы пользователь мог скачать по нажатию кнопки архив со всеми pdf?
В системе напрямую такой возможности нет, можно попробовать переопределить эту логику и добавить модулю архиватора на Javascript или С#, например https://habrahabr.ru/post/133129/
Коллеги, подскажите, пожалуйста, как можно перенести настройки отчётов раздела через svn? Подозреваю, что это некие данные, которые надо привязать к пакету. Но какие?
Подскажите как корректно загрузить пользовательский модуль с параметрами для конструктора объекта модуля. Или иным образом передать в контекст загружаемого модуля данные ?
Пример модуля
Для передачи параметров в загружаемы модуль, необходимо воспользоваться свойством instanceConfig. Скорей всего проблема связана с тем, что в конструктор модуля можно передавать только литералы объектов. this же является уже созданным экземпляром класса.
В вашем варианте это модуль элемента граф.интерфейса, со вьюхой и т.д.
наследник "Terrasoft.BaseSchemaModule"
В моем же случае нет вьюх, у Вас не описан метод init, работа в котором требуется мне.
Да и в любом случае - я воспроизвел свой юзкейс наследуясь от Terrasoft.BaseSchemaModule
В init модуля все равно нет ничего ни через instanceConfig ни через parameters
loadModule должен по определению эти объекты транслировать в конструктор.
Но по какой-то причине этого не происходит в моем кейсе...
И вопрос здесь - почему ?
На вопрос "как?" примеров и в исходниках много... но не ясно почему там работает а в моем модуле, содранном структурно под копирку - не работает.
Скорей всего это архитектурное решение, ведь даже инстанс sandbox в загружаемом модуле инциализируется отдельно. Также можно кешировать scope в свойствах глобального объекта браузера.
Так же в самом модуле, добавлена подписка на событие:
в схеме некоей карточки я добавляю модуль в зависимости, объявляю его экземпляр,
но когда дело доходит
Код внутри модуля исполняется успешно, во всех случаях кроме непосредственной подписки на события
В конечном итоге имеем ошибку "Cannot read property 'messages' of null "
внутри bootstrap.js
... getEventDescriptor:function(eventName){ var moduleDynamicMessages =this.getCurrentModuleDynamicMessages(); if(moduleDynamicMessages[eventName]){ return moduleDynamicMessages[eventName]; } var moduleDescriptor = core.getModuleDescriptor(this.moduleName); return(moduleDescriptor.messages)? moduleDescriptor.messages[eventName]||null:null; },
...
this.moduleName - оказывается в состоянии undefined
Если кто-то понимает причины, где я допустил просчет, пожалуйста подскажите.
Хотелось бы наконец разобраться как использовать функционал "своих модулей" и применять их в разработке собственной логики.
Делал модальное окно с общением между ним и карточкой из которой оно открывается через песочницу. Возможно будет полезно, вот здесь код и описание: http://www.community.terrasoft.ru/forum/topic/17970#comment-63544
Т.к. модальное окно по сути тоже модуль и песочница там работала.
"Андросов Дмитрий" написал:Ext.create(sandbox) - это что?
Эксперимент после которого, собственно подписка уже двинулась дальше, изначального фейла в котором this.sandbox = undefined
Подглядел где-то в исходниках.
...
Переработал модуль, переосмыслив, почитав статью.
да, а вот создавать экземпляр вашего модуля на LeadPage не надо
На правах, связанного вопроса...
Если я не могу/не надо создавать, как же я смогу передать контекст, при Ext.create(
я планировал передавать его - перегружая динамическое свойство, в объекте (2-ой аргумент конструктора)
Я так понимаю во время загрузки модуля, такой возможности уже не предоставляется
Или есть ?
PS: В двух словах, если можно, а в каких юзкейсах потребуется явное объявление экземпляра через Ext.create(?
"Terrasoft.CardModuleResponseInterceptor" использовать невозможно.
Вызов кода модуля, и его метода init происходит через его имя "модуля" а не класса, Вы второпях ошиблись.
т.е.
Но по неизвестной причине - мне не удается получить значения в контексте init метода.
При этом инициируя через Ext.create и явный вызов init метода у экземпляра
как раз аргументы конструктора передаются корректно, но зато не функционирует sandbox
С этого собственно все и началось.
Проблема стоит следующая: создать иерархическую(или скорее графоподобную) сущность, каждый элемент которой мог бы иметь как несколько детей, так и несколько предков и потому стандартная реализация через колонку ParentId не подходит. Вопрос следующий: как правильно(если вообще возможно) создать такую структуру данных, чтобы потом можно было выбрать всех предков скажем так:
Select accountSelect = GetAccountSelectQuery(accountId, additionalColumnNames);
var hierarhicalOptions = new HierarchicalSelectOptions {
PrimaryColumnName = "AccountId",
ParentColumnName = "ParentAccountId",
SelectType = HierarchicalSelectType.Parents,
MaxDepthParameter = select.Parameters.GetByName("MaxDepth"),
IncludeLevelColumn = true
};
QueryCondition startingCondition = hierarhicalOptions.StartingPrimaryColumnCondition;
startingCondition.LeftExpression = new QueryColumnExpression("AccountId");
startingCondition.IsEqual(select.Parameters.GetByName("RootAccountId"));
string sqlText = UserConnection.DBEngine.GetQuerySqlText(accountSelect, hierarhicalOptions);
using (DBExecutor dbExecutor = UserConnection.EnsureDBConnection()) {
using (IDataReader reader = dbExecutor.ExecuteReader(sqlText, accountSelect.Parameters)) {
while (reader.Read()) {
ancestors.Add(reader.GetColumnValue("AccountId"););
}
Идея Ваша ясна, но реализовать вот прямо как код написан вряд ли удастся, только если писать какие-то костыли. Допустим, а) если количество предков или наследников или наследников будет строго меньше N, можно сделать N полей, но это плохо с той стороны, что большое количество полей будет просто излишним, б) сделать какое-то поле, в котором будут сконкатенированы, допустим, через запятую id`шники предков, и потом его парсить, но это нарушение реляционности, да и в принципе очень проблематично. Рекомендую все же пересмотреть иерархию и подобрать другое решение.
С "наскоку" не получается в исходниках найти ту часть кода, который отвечает за реализацию поведения (часто встречающегося в типовых конфигурациях): Когда при выборе справочного значения в типовом окне справочника, происходит добавление с открытием карточки, или из какого-то пункта меню открывается карточка создания, а по завершению ее редактирования ("Сохранить") карточка закрывается, пользователь возвращается на карточку из которой он инициировал создание, где уже заполняется вновь созданным значением связанное справочное поле.
Подскажите куда копать ?
Я предполагаю что для этого поведения существует "стройный" механизм, выраженный в использовании каких-то специальных методов и т.д.
За функционал открытия новой карточки при добавлении записи в справочное поле отвечает метод actionButtonClick из LookupPageViewModelGenerator. Также Вам стоит посмотреть в метод defaultModeActionButtonClick из того же модуля.
Основная "магия" происходит в момент публикации сообщения PushHistoryState.
А можете помочь, поточнее определить/разобрать "магию".
Каким-то образом ведь должно быть определено что в открываемой карточке, во-первых надо ее закрывать при сохранении (если открыть карточку просто через OpenCardInChain такого не происходит),
во-вторых указать в какое поле искомой карточки - устанавливать значением - вновь созданную запись.
Мне необходимо добиться аналогичного поведения, только не из окна справочника, а по пункту меню "Действия"... например для карточки объекта "У" - пункт меню "Создать X"
Должна открываться карточка "X" и после ее сохранения, необходимо вернуть пользователя "на исходную карточку "Y", где специализированное поле для связи "Связанный объект Х" (Являясь справочным полем для "X") будет заполнено значением только что созданного "X".
"килочасы" отладки, позволили определить наилучшего кандидата, это событие "CardModuleResponse"
(Прямо то что нужно в атрибуты события передаются данные по уже успешно сохраненному объекту)
При условии помещения в "PushHistoryState" текущей карточки с признаком "isInChain: true"
И дальнейшим открытием карточки нового объекта через openCardInChain, "Сохранить" или "Отмена" в открываемой карточке, естественным образом вернут пользователя на страницу помещенную в PushHistoryState. При сохранении карточки обязательно произойдет публикация CardModuleResponse в который будет переданы данные о созданной записи
Казалось бы - проблем нет, подписываемся на событие и счастливы...
но нет....
На событие "CardModuleResponse" подписаться в карточке нельзя, так как в ее контексте на уровне BasePageV2 это событие уже объявлено в направлении "PUBLISH"
Как же можно обойти такое ограничение и все таки подписаться на это событие ?
(В случае с выбором из справочника, подписка происходит в рамках схемы LookupPageViewModelGenerator).
Может быть можно как-то выкрутиться через модуль, в который передавать контекст карточки, а в нем произвести подписку, т.к. там не будет зависимости от BasePageV2 ?
Здравствуйте,
Рекомендую вам написать БП в котором открывать карточку создания нужной вам сущности, после чего, из скрипт-таска послать веб сокет сообщение с id созданной записи в карточку, из которой через действия вы запустите данный процесс: http://www.community.terrasoft.ru/forum/topic/11784#comment-56699
В карточке услышав данное веб-сокет сообщение вы просто нужное поле, заполните значением по id полученным из процесса.
Информация о том, как запустить из JS процесс есть на академии.
Ну есть же механизм который используется в LookupPageViewModelGenerator
событие CardModuleResponse которое встроено в штатное платформенное поведение.
Неужели его никак нельзя использовать в собственных сценариях ?
"Севостьянов Илья Сергеевич" написал:Неужели его никак нельзя использовать в собственных сценариях ?
если вы хотите его использовать на наследниках BaseEntityPage, то не выйдет - нельзя на одного и то же сообщение подписаться в обе стороны. Вам придется реализовывать собственную пару для передачи сообщения между карточкой и карточкой. В случае со справочником [если я ничего не путаю] - LookupPage служит передатчиком между одной карточкой и другой
"Андросов Дмитрий" написал:В случае со справочником [если я ничего не путаю] - LookupPage служит передатчиком между одной карточкой и другой
Да и вот идея у меня была, забацать модуль посредник. В другой теме уже по нему выспрашиваю, пока что не очень получается :(
Мне кажется это более архитектурно-верный способ, нежели "обмазываться" событиями каждый раз.
Вам стоит смотреть в сторону использования метода openCardInChain для открытия карточки, а также для передачи в открываемую карточку имени атрибута, в который в итоге необходимо записать значение сохраняемой записи.
Передать значение можно через свойство defaultValues. Свойство defaultValues должно содержать массив объектов вида {name: "", value: ""}. В открывшейся карточке переданные значения можно считать с атрибута DefaultValues.
Возвращать Id сохраняемой записи уже через sandbox заместив BasePageV2.
Подскажите, пожалуйста, как можно перенести набор системных настроек через svn?
Во вкладке Данные переносимого пакета я создал новую схему для всех созданных системных настроек с фильтром "Код начинается на ...", схема показала 3 нужные записи.
Попробовал создать схему привязки Значений системной настройки (с фильтром Системная настройка.Код начинается на ... - т.е. зеркально предыдущему фильтру), при показе данных отображает 3 корректных значения, но при сохранении выдаётся ошибка для всех трёх значений: "Не привязаны данные для связанного объекта "SysSettings" по колонке "SysSettings"" и дальше Id системных настроек.
Но если я пытаюсь добавить ещё одну схему привязки системной настройки с другим фильтром мне выдаётся сообщение, что эта запись уже привязана в другой схеме.
Подскажите, пожалуйста, корректный способ переноса настроек.
Что интересно. Сейчас (в процессе тестирования) попробовал изменить в настройке фильтров ограничение с И на ИЛИ для единственного фильтра и все записи корректно привязались, вторая схема также увидела привязанные данные.
Правда до этого я указал один раз в фильтре конкретное значение записи в режиме фильтра "равно".
Теперь изменения фильтров на И или ИЛИ не отменяют успешность привязки данных к пакету.
"Севостьянов Илья Сергеевич" написал:
Наиболее гарантированный, а так же с наиболее ожидаемым поведением - это SQL-скрипт.
Это всё-таки хардкор без поддержки логики приложения...
Если есть штатные рабочие инструменты, хочется сначала пользоваться ими, пока не будет доказано, что они неработоспособны.
Пока получилось, что надо как минимум одно условие прописать в качестве прямого "равно", тогда данные привязываются, а дальше можно ставить любые условия. Буду ещё дальше смотреть как оно работает.
"Фёдоров Александр. Афлекс" написал:Если есть штатные рабочие инструменты, хочется сначала пользоваться ими, пока не будет доказано, что они неработоспособны.
Они не предназначаются для переноса:
1) Системных настроек и их значений
2) Настройки колонок и их значений
3) Организационной структуры
4) Пользовательских прав.
Об этом, не однократно заявляли специалисты тех.поддрежки.
Если Вы хотите "надежно" переносить Ваши системные настройки - Вам необходимо написать SQL-сценарий, при этом желательно с логикой проверки предварительного существования, а так же проверкой - возможно, связанных данных.
ИМХО самый подходящий вариант (для TSQL) это MERGE скрипт, я о нем писал.
PS: Через данные, нормально переносятся группы системных настроект, включение настроек в группы, но самими значениями настроек - иногда бывают проблемы.
Об этом неоднократно заявляли специалисты тех.поддержки.
...
Это утверждение входит в противоречие с рекомендацией (которые звучали в том числе и на форуме Террасофт): при разработке новых объектов для задания значений по умолчанию использовать системные переменные.
Объективно есть потребность в переносе системных настроек между окружениями, да и оргструктуру с настройкой прав было бы удобнее сначала тестировать, а затем переносить пакетом.
При этом SQL-скрипт - это слишком низкоуровневый инструмент, для которого требуется разработчик с неплохим знанием SQL.
да нормально они переносятся - привяжите нужные данные для таблиц
SysSettings (обязательно)
SysSettingsFolder (группы настроек)
SysSettingsFolderLcz (локализация групп настроек)
SysSettingsGrantor (вхождение пользователей, если настройка "персональная")
SysSettingsInFolder (вхождение настройки в группу настроек)
SysSettingsLcz (локализация настроек)
SysSettingsReferenceSchema (не знаю, что это, вроде не нужно)
SysSettingsValue (обязательно)
они даже установятся в правильном порядке.
после установки только надо бы редис очистить и перезайти на клиенте
и еще момент, если настройка уже была, то, чтобы значение поменялось, надо ставить признак "Обязательно для обновления" на соответствующую колонку
"Мотков Илья" написал:
1. Создать привязку на системную настройку
2. Создать привязку на само значение System settings value
Илья, да, я так и сделал. В первоначальном моём сообщении я писал про то, что не сработала привязка данных из-за группового фильтра. После указания прямого фильтра всё заработало.
Дмитрий, спасибо за столь развёрнуты ответ. За "Обязательно для обновления" - отдельное спасибо.