Здравствуйте.
Добавляю кнопку в LeftContainer, аналогично добавлению в BasePageV2:

{
        "operation": "insert",
        "parentName": "LeftContainer",
        "propertyName": "items",
        "name": "SentManufacturerButton",
        "values": {
                "itemType": Terrasoft.ViewItemType.BUTTON,
                "caption": "SentManufacturerButtonCaption",
                "classes": {"textClass": "actions-button-margin-right"},
                "click": {"bindTo": "sentManufacturerButtonClick"},
                "style": Terrasoft.controls.ButtonEnums.style.GREY,
                "visible": true,
                "tag": "sentManufacturerButtonClick",
                "markerValue": "SentManufacturerButton"
        }
}

Но она странно себя ведет, при редактировании(открытии из раздела) записи она не отображается, если обновить открытую страницу редактирования кнопка появляется, также отображается при добавлении записи.
Подскажите пожалуйста в чем проблема?

Версия 7.7.0.2325

Нравится

2 комментария
Технические вопросы
7.x

В мене є питання по видаленню колонок в обєкті.
Чи можливо видалити колонку в самій базі даних після того як вона була видалена у конфігураторі?
Які будуть наслідки таких дій?

Нравится

1 комментарий

Проблема может быть, если на это поле была завязана логика в хранимках, триггерах и других подобных объектах на уровне БД. После удаления поля обращения к нему будут завершаться ошибками.

Показать все комментарии

Я создал новый раздел, куда нужно будет вносить данные с процентами. Там есть поле для чисел с плавающей запятой, где можно выставить округление до 0.01. А где настроить минимальное/максимальное значение? Так как в поле будут заноситься исключительно проценты, то ограничение на ввод составляет от 0.01 до 100.

Нравится

1 комментарий

Все, решил. К примеру, есть поле "Percent", то в "Схему редактирования раздела" надо внести следующее:

methods: {
    /**
     * Добавляет валидаторы
     * @inheritdoc Terrasoft.BasePageV2ViewModel#setValidationConfig
     * @overridden
     */
    setValidationConfig: function() {
        this.callParent(arguments);
	this.addColumnValidator("Percent", this.validatePercent);
    },
    /**
     * Валидация процентов.
     * от 0.01 до 100
     */
    validatePercent: function(){
        var _invalidMessage = "";
	var _percent = Terrasoft.deepClone(this.get("Percent"));
	if(_percent < 0.01){
	    _invalidMessage = "Значение меньше 0.01%";
	}else if(_percent > 100){
	    _invalidMessage = "Значение больше 100%";	
	}
	return {
	    fullInvalidMessage: _invalidMessage,
	    invalidMessage: _invalidMessage
	};
    }
}

Поле, в моем случае обязательное, потому определение заполнено/незаполнено сюда не вносил.

Показать все комментарии
Технические вопросы
7.x

Доброго дня!
В мене є карточка рахунків(Invoice), вона має поле "Номер", як текстове поле, але в це поле записуються номера. Виникла проблема в тому, що тепер сортування працює не так як б хотілося, тобто сортується текст а не цифри.
Чи можливо змінити базову логіку сортування для своє сторінки(схеми)

Нравится

3 комментария

Здравствуйте!

Как вариант Вы можете создать пользовательское поле "Номер" с типом "Целое число" и перенести данные из базового поля в созданное.

Единственная проблема - у пользовательского поля не будет автоинкрементирования.

"Демьяник Алексей" написал:

Единственная проблема - у пользовательского поля не будет автоинкрементирования.

Олексій, змушений не погодитись. Його неважко самому реалізувати.

"Саварин Володимир" написал:
Демьяник Алексей пишет:

Единственная проблема - у пользовательского поля не будет автоинкрементирования.

Олексій, змушений не погодитись. Його неважко самому реалізувати.

Я на всякий случай предупредил:smile:

Показать все комментарии
Технические вопросы
7.x

Задача:
есть два справочника, список Физ.лиц и список Юр.лиц. (справочники простые), как настроить поле со списком, чтобы в нем можно было выбирать Наименования из обоих справочников?

Нравится

21 комментарий

чтобы отобразить такой составной справочник надо будет создать представление (объект со свойством "представление") и SQL-скрипт а ля

create view [dbo].[FizUrLic]
as
	select 
		[Id]
		,[Name]
	from FizLic
	union all
	select 
		[Id]
		,[Name]
	from UrLic
GO

. Это будет так сказать виртуальная таблица, объединяющая два ваших справочника в один. Но возникнут большие сложности с сохранением значения поля. Т.к. поле должно быть справочным и одновременно иметь возможность ссылаться на два разных справочника. Задача уровня разработчика.

другой вариант - объединить физически два справочника в один, добавив поле типа (Физическое/Юридическое), по которому фильтровать там, где это вам надо

Видел вот такой вариант решения совмещения из двух справочников:

да, это продажи в 7.7. Но сделать это не так-то просто

Вот в том то и вопрос. От этого задача не изменяется.) Где-то же есть код, который организовывает подобный диалог? Если да, то подскажите - где искать.
Я догадываюсь, что такое вполне организовали на С#.

похоже, все уже сделано Террасофтом)
версия 7.7 пакет Opportunity схема OpportunityPageV2
не проверял, но вроде достаточно добавить аналогичный код

attributes : {
	"Client" : {
		"caption" : {
			"bindTo" : "Resources.Strings.Client"
		},
		"dataValueType" : this.Terrasoft.DataValueType.LOOKUP,
		"multiLookupColumns" : ["Contact", "Account"],
		"isRequired" : true
	}
},
diff[{
		"operation" : "insert",
		"parentName" : "Header",
		"propertyName" : "items",
		"name" : "Client",
		"values" : {
			"layout" : {
				"column" : 2,
				"row" : 1,
				"colSpan" : 10
			},
			"tip" : {
				"content" : {
					"bindTo" : "Resources.Strings.ClientTip"
				}
			},
			"controlConfig" : {
				"enableLeftIcon" : true,
				"leftIconConfig" : {
					"bindTo" : "getMultiLookupIconConfig"
				}
			}
		}
	}
]

Я видел нечто похожее, в Order 7.7, "OrderPageV2". Я так понимаю, что еще надо лепить проверку.

define("OrderPageV2", 
["ProductSalesUtils", "OrderConfigurationConstants", "BusinessRuleModule", "MoneyModule", "VisaHelper", "ConfigurationConstants", "ProductEntryPageUtils", "css!VisaHelper", "MultiCurrencyEdit","MultiCurrencyEditUtilities"],
function(ProductSalesUtils, OrderConfigurationConstants, BusinessRuleModule, MoneyModule, VisaHelper,     ConfigurationConstants) {
    return {
        entitySchemaName: "Order",
        messages: { ... },
        attributes: {
            ...                     
            "Client": {
                "caption": {"bindTo": "Resources.Strings.Client"},
                "dataValueType": this.Terrasoft.DataValueType.LOOKUP,
                "multiLookupColumns": ["Contact", "Account"],
                "isRequired": true
            }
        },
        details: /**SCHEMA_DETAILS*/{ ... },
        mixins: { ... },
        methods: { 
            ...
            /**
             * Выполняет проверку значения модели представления.
             * Если присутствуют некорректные значения, выводит сообщение о необходимости заполнения первого.
             * @protected
             * @overridden
             * @param {Function} callback callback-функция
             * @param {Terrasoft.BaseSchemaViewModel} scope Контекст выполнения callback-функции
             */
            asyncValidate: function(callback, scope) {
                this.callParent([function(response) {
                    var checkResponse = function(context) {
                        if (!context.response.success) {
                            context.callback.call(context.scope, context.response);
                        } else {
                            context.next();
                        }
                    };
                    var validationChain = [
                        checkResponse,
                        function(context) {
                            context.scope.validateAccountOrContactFilling(function(response) {
                                context.response = response;
                                context.next();
                                }, context.scope);
                        },
                        function(context) {
                            context.callback.call(context.scope, context.response);
                        }
                    ];
                    Terrasoft.chain({
                        scope: scope || this,
                        response: response,
                        callback: callback
                        }, validationChain);
                }, this]);
            },                    
            ...                    
            /**
             * Проверяет заполненость полей "Контакт" или "Контрагент" значениями
             * @param {Function} callback Функция обратного вызова
             * @param {Object} scope Контекст
             */
            validateAccountOrContactFilling: function(callback, scope) {
                var account = this.get("Account");
                var contact = this.get("Contact");
                var result = {
                    success: true
                };
                if (this.Ext.isEmpty(account) && this.Ext.isEmpty(contact)) {
                    result.message = this.get("Resources.Strings.RequiredFieldsMessage");
                    result.success = false;
                }
                callback.call(scope || this, result);
            },                    
            ...            
        },
        diff: /**SCHEMA_DIFF*/[ 
            ...            
            {
                "operation": "insert",
                "parentName": "Header",
                "propertyName": "items",
                "name": "Client",
                "values": {
                    "layout": {"column": 0, "row": 0, "colSpan": 12},
                    "tip": {
                        "content": {"bindTo": "Resources.Strings.ClientTip"}
                    },
                    "controlConfig": {
                        "enableLeftIcon": true,
                        "leftIconConfig": {"bindTo": "getMultiLookupIconConfig"}
                    }
                }
            }
            ...
        ]
    }
});            
 

Помимо этого, я так понимаю, что в самой сущности необходимо начилие также соответствующих справочных полей "Contact" и "Account", а поле "Client" - это как виртуальное поле.

Я эти шаги проделал на тестовом разделе: сделал 2 поля и запилил эти добавки, но страница тупо зависла. Может еще что-то нужно? Или где посмотреть причину, логи какие-нибудь..

Если убрать валидаторы, то идея - работоспособна.

Дмитрий, спасибо большое. )

Продолжаем разговор.)
С сохранением данных - определились, а вот теперь обратная задача: отобразить общее значение из этих двух полей - в одном поле реестра (по сути, там будет или данные из одного поля или из другого).

Здравствуйте, Евгений.

Как вариант решения, можно создать в объекте скрытое поле, в которое подтягивать необходимое значения, после чего выводить его в реестре стандартными средствами.

Здравствуйте, Павел.
Идея хорошая, сходная с идеей в Карточке редактирования. А есть пример какой-нибудь по реализации этого процесса? Или где создавать эту вирт.колонку и как этот реестр определит, что ее нужно выводить?

Эта колонка может быть просто текстовым полем с проставленным свойством "visible": false. При изменении значения мультилукапного аттрибута, Вы можете получать значение этого аттрибута используя this.get и устанавливать в скрытое поле через this.set. Вывести данное поле в реестр не составит проблем.

"Мотков Илья" написал:

Эта колонка может быть просто текстовым полем с проставленным свойством "visible": false. При изменении значения мультилукапного аттрибута, Вы можете получать значение этого аттрибута используя this.get и устанавливать в скрытое поле через this.set. Вывести данное поле в реестр не составит проблем.

Я думал об этом, только как поведет себя это поле, если данные (например ФИО) в справочние - изменятся? Значение которое сохранено - уже не поменяется же..
Или можно его как-то при выборке динамически обновлять?

Текстовое поле действительно не изменится, в этом случае можно создать процесс актуализации, который будет, к примеру, раз в день запускаться, проходить по всем записям в разделе и сравнивать поле справочника с текстовым. Если отличаются, менять значение текстового поля на значение справочника.

Возникла идея модифицировать данные на лету, в процессе загрузки, например в методе GridUtilitiesV2.onGridDataLoaded. Насколько это возможно?

Очень странно, что не дает модифицировать данные в JavaScript, которые загружены с сервера. Т.е. стили модернизировать можно, а данные нельзя? А если мне надо сохранять данные в сжатом формате, а потом их распаковывать для удобства отображения?

А разве не будет самым простым решением - создать новый справочник в объекте. Значения в котором будут заполняться, изменяться и удаляться при помощи триггеров в таблицах на основании которых он строится или при помощи бизнес процессов.

"Мотков Илья" написал:А разве не будет самым простым решением - создать новый справочник в объекте. Значения в котором будут заполняться, изменяться и удаляться при помощи триггеров в таблицах на основании которых он строится или при помощи бизнес процессов.

самое простое не есть самое лучшее
;)

"Фролов Евгений" написал:Я думал об этом, только как поведет себя это поле, если данные (например ФИО) в справочние - изменятся? Значение которое сохранено - уже не поменяется же..

БП, который стартует при изменении поля ФИО в Контакте. И этот БП меняет текстовую колонку во всех нужных объектах, где клиент является физ-лицом.
То же самое с объектом Контрагент

Всем спасибо, пока принято решение не совмещать вывод данных.

Показать все комментарии
case в бизнесс процессе
Технические вопросы
7.x

Здравствуйте.
Помогите пожалуйста с ответом на вопрос.
У меня есть бизнесс процесс, который запускается при лобавлении нового лида, который пришел из Лендинга. Таких лендингов у меня 15 штук. В одной из веток процесса мне нужно создавать счет, номер которого должен иметь вид "12_17032016" где число до подчеркивания - это число, которое соответствует одному из Лендингов. Как мне описать условия присвоения такого названия Счету если у Лендинг1 число 1, Лендинг2 число 2, и так до Лендинг15 число 15? Я так понимаю мне для этого нужно создать параметр в Parameters бизнесс-процесса и в Задании-сценарии зделать Switch Case.
Но я не знаю как мне это сделать.
Можете помочь? Спасибо.

Нравится

1 комментарий

Добрый день!

Для решения задачи используйте условные потоки. Читать данные объекта, в условном потоке проверять значение поля со значением из справочника. Например:
[#Читать данные 1.Первый элемент результирующей коллекции.Тип#] == [#Справочник.Тип контакта.Клиент#]
В зависимости от результата указывать номер счета с помощью конкатенации строк. Например:
"11_" + [#Читать данные 1.Первый элемент результирующей коллекции.ФИО#]

Показать все комментарии

За двоение функциональных ролей.
При создании функциональной роли "Менеджер Х". Была добавлена одна запись.

Но при раздаче прав на "Доступ к операциям" их оказалось 2.

Почему так?
Уже не первый раз.
Что надо делать чтобы такого не было?
Спасибо.

Нравится

3 комментария

Разработчик бизнес решений
и
Разрабочики бизнес решений
отличаются наличием буквы "и" и отсутствием буквы "т" во второй роли :smile:

Ок.
Т.е. в этом списке выводиться как функциональная так и орган-е роли ?
А еще момент почему нет иконки пользователи системы?

Н

"ЮМРавильевич" написал:
Т.е. в этом списке выводиться как функциональная так и орган-е роли ?


Не совсем так. В этом списке выводятся организационные роли, которые Вы можете связать с создаваемой функциональной ролью. Насколько я понял Вы уже создали две организационных роли (Разработчик бизнес решений и Разрабочики бизнес решений) в разделе Организационная структура в Дизайнере системы.
Более подробно об организационных и функциональных ролях Вы можете узнать:

Показать все комментарии
необязательная колонка null int int64 long
Технические вопросы
7.x

Здравствуйте!

Необходимо добавить свойство в объект с типом int64 (long) и еще нужно, чтобы оно могло принимать значение NULL (не задано).
Каким образом это можно сделать в bpmonline 7.2 ?

Спасибо.

Нравится

7 комментариев

Юрий, как удачно вы создали тему!
Тоже очень интересует эта проблема, так как по логике должно быть в поле null, что означает - поле не заполняли, а получается оно автоматически ставится в 0! Что по бизнес-логике неверно.
Скрины поля в бпм и бд во вложении.
Очень жду рецепта - что нужно сделать, чтобы работало так, как предполагается.

Да, очень часто бывает так, что приходится ставить дополнительный CheckBox, чтобы понять, что это NULL, а не 0

Здравствуйте!

Изменить на NULL нельзя, т.к. в нашей реализации этот тип данных должен иметь значение по умолчанию на уровне БД.
Его значение можно изменить из дизайнера на любое числовое значение:
[IMG]http://s019.radikal.ru/i626/1603/b1/e41826716a8a.jpg[/IMG]

Очень жаль. Показывать вместо возраста -1 (к примеру) совсем не хочется.
А переписывать загрузку и сохранение объекта, чтобы руками менять значения полей - это как-то слишком трудоемко.

А что можете сказать по поводу типа long ?

Юрий, такого типа нет. Для числовых типов значение NULL - недопустимо.

ЭХ, явная недоработка на мой взгляд.

"Владимир Соколов" написал:

Да, очень часто бывает так, что приходится ставить дополнительный CheckBox, чтобы понять, что это NULL, а не 0


Владимир, а как вы это делаете? Т.е. заставляете пользователя чекбокс ставить перед заполнением поля? Или сами как-то заполняете скрытое поле при изменении значения?

Показать все комментарии

Здравствуйте.
Интересует вопрос как в бизнес-процесе в элементе формула присвоить текстовому полю ProductId значение вида "72_16032016" где 72 это код продукта а 16032016 - текущая дата. Мне нужно чтобы был именно такой формат (без точек). Как это мне написать.

Вот такой вариант "72_"+[#Системная переменная.Текущее значение даты#].ToString() не работает. И еще не понятно как мне убрать точки в 16.03.2016.
Ошибка - cannot convert string to DataTime.
Подскажите пожалуйста. Спасибо!

Нравится

6 комментариев

Поле ProductId имеет тип данных GUID (глобальный уникальный идентификатор). Это идентификатор записи в базе данных. Поэтому вы не сможете присвоить ему пользовательское значение. Вы можете присвоить какой-то уникальный код вашему продукту, несколько модифицировав пример, предлагаемый в Документации разработчика-Примеры решения типовых задач-Разработка бизнес-логики-
Как добавить автонумерацию к полю страницы редактирования

Здравствуйте Роман. Я не использую поле ProductId которое заложено в системе. Я создал в бизнесс процессе строковый параметр ProductId и в Формуле хочу ему присвоить значение вида "72_16032016" где 72 это код продукта а 16032016 - текущая дата. Мне нужно чтобы был именно такой формат (без точек).
Как мне модифицировать эту формулу "72_"+[#Системная переменная.Текущее значение даты#].ToString() чтобы не выдавало ошибки cannot convert string to DataTime и записывало значение именно в таком формате(без точек) "72_16032016".
Автонумерация мне не нужна, ибо это будет поле номер счета (и оно не обязательно будет уникальным)
Спасибо.

Здравствуйте!

Вариант DateTime.Today.ToString не пробовали? (https://msdn.microsoft.com/en-us/library/system.datetime.today(v=vs.110… - получение строки с датой).
Замена символов в строке - https://msdn.microsoft.com/en-us/library/kxbw3kwc(v=vs.110).aspx (для того, чтобы убрать разделитель)

Здравствуйте Алексей.
Видимо я не понимаю где я могу писать э С# код.
Ибо если в Формуле написать "72_"+DateTime.Today.ToString то система ругается и выдает Operator '+' canot be applied to operands of type 'string' and 'metod group'.
Подскажите, пожалуйста, как это полностью прописать и где.

Вот я сделал так

и получил такой результат

Остается убрать точки и нули, которые зашли от времени.

Это пробую сделать в задании-сценарии.
Беру OrderId и пробую уубрать точки.

И получаю ошибку.

OrderId лежит в параметрах бизнесс процесса.

Здравствуйте Алексей!
Прошу вас помочь мне в одном вопросе.
Вот у меня на скрине, что у предыдущем посте название 72_17.03.2016 10:22:32.
Подскажите, как мне убрать пробел. У меня это строковое поле. Функции С# для этого я знаю. Я не знаю где и как я могу их задействовать. Можете сделать скрин в каком месте и как мне это сделать (в бизнес процессе). Благодарен вам очень!

Здравствуйте, Сергей!

В версии 770 немного изменилось обращение к параметрам процесса.

Пример:
Для получение значения параметра процесса OrderId:
var orderId= Get("OrderId");
Для того, чтобы задать параметру процесса значение:
Set("OrderId", "Some value");

Показать все комментарии

Доброго времени суток! Интересует вопрос приема системой Террасофт массива данных для определенных полей, например у мне нужно скинуть список продуктов пользователя. Я кидаю массив данных (JSON, обычный массив через cURL) и сможет ли система парсить его разбив его на нужную информацию?

Спасибо.

Нравится

1 комментарий

Здравствуйте!

Вы можете создать свой вебсервис в bpmonline и обращаться к нему. Как вариант, Вы можете сделать процесс, который будет декодировать строку JSON, а саму строку передавать в бизнес процесс в качестве параметра.

Более подробно читайте здесь.

Показать все комментарии