Добрый день! В разделе продажи есть вкладка продукты, где размещена деталь продукты/услуги в продаже. Здесь каждый продукт имеет стоимость. Также есть вкладка данные о продаже и там есть поле сумма продажи в которое необходимо просуммировать стоимость для всех продуктов из предыдущей вкладке. Подскажите метод как это можно реализовать.



 

Нравится

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

Добрый день, Вадим!

В базовой конфигурации системы и так сумма продуктов из базовой детали "Продукт в продаже" пересчитывается в указанном Вами поле "Сумма продажи". Если на Вашем сайте данный пересчет не происходит, то с данным вопросом следует обратиться в техническую поддержку для анализа проблемы конкретно на Вашем сайте.

Если вопрос в том, как реализована логика пересчета поля "Сумма продажи" на основании суммы всех продуктов в детали "Продукт в продаже", то данная логика записана на объекте [OpportunityProductIneterst] в методе "CalckOpportunityAmmount" :

var oppotrunityAmountSelect = new Select(UserConnection)

    .Column("Amount")

    .From("OpportunityProductInterest")

    .Where("OpportunityId").IsEqual(Column.Parameter(opportunityId)) as Select;

double opportunityAmount = 0.0;

using (var dbExecutor = UserConnection.EnsureDBConnection()) {

    using (IDataReader dr = oppotrunityAmountSelect.ExecuteReader(dbExecutor)) {

        while (dr.Read()) {

            if(!dr.IsDBNull(0)){

                opportunityAmount += (double)UserConnection.DBTypeConverter.DBValueToDecimal(dr[0]);

            }

        }

    }

}

//далее идет код обновления продажи после пересчета (здесь же в объекте): 



var update = new Update(UserConnection, "Opportunity")

        .Set("Amount", Column.Parameter(opportunityAmount))

        .Where("Id").IsEqual(Column.Parameter(opportunityId));

    update.Execute();

Также, на всякий случай прикрепляю код пересчтеа суммы и цены именно в детали "Продукт в продаже" для каждого отдельного продукта:

* Recalculates products amount in opportunity.

                     * @private

                     */

                    recalculateAmount: function() {

                        var price = this.get("Price");

                        var quantity = this.get("Quantity");

                        if (price && quantity) {

                            this.set("Amount", price * quantity);

                        }

                    },

                    /**

                     * Recalculates product price.

                     * @private

                     */

                    calculatePrice: function() {

                        var product = this.get("Product");

                        if (this.Ext.isEmpty(product) || this.Ext.isEmpty(product.Currency)) {

                            return;

                        }

                        MoneyModule.onLoadCurrencyRate.call(this, product.Currency.value, null, function(item) {

                            var price = (product.Price * item.Division) / (item.Rate);

                            this.set("Price", price);

                        });

                    },

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

Генкал Вадим,

Если вам не нужно это поле оперативно отображать в карточке, то можно сделать в простом БП по событиям добавления/редактирования/удаления записей в объекте продукты/услуги

Владимир Соколов,

Реализовал для даного обьекта событие 

ProductInOpportunitySaving в таком виде: добавил процес(скрин), а в элемент script task такой код: var opportunityId = Entity.GetTypedColumnValue<Guid>("OpportunityId");

var oppotrunityAmountSelect = new Select(UserConnection)

    .Column("Amount")

    .From("CHProductsAndServicesInOpp")

    .Where("OpportunityId").IsEqual(Column.Parameter(opportunityId)) as Select;

double opportunityAmount = 0.0;

using (var dbExecutor = UserConnection.EnsureDBConnection()) {

    using (IDataReader dr = oppotrunityAmountSelect.ExecuteReader(dbExecutor)) {

        while (dr.Read()) {

            if(!dr.IsDBNull(0)){

                opportunityAmount += (double)UserConnection.DBTypeConverter.DBValueToDecimal(dr[0]);

            }

        }

    }

}

var update = new Update(UserConnection, "Opportunity")

        .Set("Amount", Column.Parameter(opportunityAmount))

        .Where("Id").IsEqual(Column.Parameter(opportunityId));

    update.Execute();

return true;

После публикации поле не считается. Cистема выдает ошибку: Значение с именем "OpportunityId" не найдено

Saving срабатывает до записи в базу. Соответственно, запрос select выберет ещё старое значение. После сохранения срабатывает событие Saved, лучше на нём.

Ну и перебор в цикле — не лучший вариант, если на детали много записей. Можно сразу написать запрос с sum.

Зверев Александр,

Спасибо за ответ. Но почему выдает ошибку: 

"Значение с именем "OpportunityId" не найдено" когда я изменяю записи в детали. Судя по вашему ответу у меня должно было просто остаться старое значение. Но по факту система не находит OpportunityId. Подскажите, с чем это может быть связано?

Возможно, там ещё пусто. Или поле не так называется. Нужно отлаживаться.

Разобрался. Проблема была в именовании поля.

Показать все комментарии
Фильтрация поддетали
7.11
sales

Задание: В карточке в вкладке есть 2 детали(А и Б)

Нужно что бы при выборе записи из детали А обновлялся реестр на детали Б.

Пытался Делать через "filterMethod": "OnLotPeriodInTendersFilter"

и по событию обновлять реестр Б, но OnLotPeriodInTendersFilter Запускается только раз, и при reloadGridData() в детали Б Новы й фильтр не подтягиватся... Подскажите как решить данное бизнес-задание

Нравится

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

Добрый день

Вам нужно при выделении записи делать publish сообщения для другой детали. А в детали "А" сделать subscribe и обновлять все, что вам нужно

Добрый день Виталий.

Советую найти и разобраться как работают детали "BaseOneToManyGridDetail", "BaseManyToManyGridDetail". Именно взяв за основу одну из них можно решить вашу задачу. Поискать примеры можно в конфигурации BPMOnline Service Enterprise. Там есть готовые и реализованные примеры. 

Артем Гура,

Это понятно, не могу найти где именно можно применить новый фильтр

Власов Михаил Викторович,

буду искать

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

Всем доброго времени суток. Версия 7.11.

В бизнес-процессе в рамках задания-сценария создаётся запись в разделе. После чего необходимо создать ещё ряд записей на детали внутри карточки этой записи.

Привязка на деталь осуществляется по id основной записи. Обычно в таких случаях на клиенте создаётся свой guid через функцию Terrasoft.generateGUID();, который затем в insert прописывается в колонку Id также, как и любая другая колонка.

Есть ли аналог этого в сценариях БП?

Нравится

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

Денис, здравствуйте.

Для этих целей есть метод Guid.NewGuid(), подробнее можно найти по ссылке.

Пример использования : 

var contactId = Guid.NewGuid();

Андрей, спасибо! Частично помогло.

Частично - потому что записать сгенерированный таким образом newGiud в другой объект в колонку-справочника невозможно. Возникает ошибка: System.ArgumentException: Отсутствует сопоставление типа объекта Terrasoft.Core.DB.QueryColumnExpression с известным собственным типом управляемого поставщика.

Соответственно вопрос: есть ли callback у insert.Execute(); ? Чтобы можно было гарантированно вызвать продолжение функции уже после того, как запись с id newGiud создана в базе.

Денис

Скорее всего вам не надо создавать новый guid. После создания записи вам надо прочитать в процессе ее id и уже затем использовать его в записях детали.

например

var Id = item.GetTypedColumnValue<Guid>("Id");

Пример можно глянуть здесь https://academy.terrasoft.ru/documents/technic-sdk/7-11/kak-zapuskat-pr…

 

Денис,

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

Показать все комментарии
7.11
sales
Есть задача вычислить сколько рабочего времени (в минутах) было затрачено на решение заявки.
При реализации необходимо учитывать начальную и конечную дату и время, а также календарь, который указан в сервисном договоре.
Вопрос: готов ли метод который вернет значение в минутах или других величинах при описанных входных данных? Или необходимо писать свой метод?

Нравится

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

Добрый день!



К сожалению, в базовой версии такого метода нет. 

Это связано с тем, что обращение может переоткрываться несколько раз. 



Потому в данной ситуации, необходимо реализовать свой метод.

 

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

Добрый день.

Переименовал раздел Контрагенты в Компании, и название кнопки "Добавить контрагента" теперь выглядит неуместно. Подскажите пожалуйста, где необходимо внести изменения (в схеме AccountSectionV2 эта кнопка не фигурирует)

Прикрепленные файлы

Нравится

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

Здравствуйте, Иван!

Переименовать кнопку "Добавить контрагента" можно в разделе "Переводы". Больше информации о функциональности переводов в нашем приложении Вы сможете найти на Академии: https://academy.terrasoft.ru/documents/sales-enterprise/7-11/multiyazychie.

Примечание. после применения переводов необходимо перезайти в систему - тогда изменения вступят в силу.

Дарина, здравствуйте!

Мы реализовывали Ваш кейс следующим образом:

- нашли соответствующую запись в Переводах - https://prnt.sc/hyys9e

- применили переводы

- перезашли в приложение

В результате название кнопки изменилось - http://prntscr.com/hyyvkq

Если Вы действовали по описанному алгоритму, и название кнопки не изменилось, напишите нам в службу поддержки на support@terrasoft.ru для более детального рассмотрения Вашего кейса.

Показать все комментарии
Вычисляемая колонка в реестре
7.11
sales

Нужно сделать самую обычную колонку в реестре в которой бы отображалось 2 значения в зависимости от того что есть на детале. Можно ли сделать виртуальную колонку? или делать колонку в объекте и ее пересчитывать при изменении записей на детале?

Нравится

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

Виталий, добрый день!

Не совсем понял вопроса, можно описать кейс поподробнее?

И что вы подразумеваете под "виртуальной колонкой" и как вы собираетесь её показывать в реестре?

Тёскин Дмитрий Валерьевич,

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

Можно сделать реальную колонку и бизнес-процесс, которые при изменении записей на детали пересчитывает значение колонки.

Так вы сможете не только отобразить колонку в реестре, но и фильтровать по ней в фильтрах

Владимир Соколов,

Так и будет, че это я прицепился вычисляемой колонке... Че только не взбредет в 12 ночи...

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

Коллеги, доброго времени суток. Версия 7.11.

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



Для теста, впрочем, был сделан простой процесс, который просто логирует текущую дату и параметр в справочник. Процесс называется, допустим UsrStartTestProcess, у него есть параметр UsrTestParameter.



Нашёл вот такую тему: https://community.terrasoft.ru/questions/zapusk-bp-iz-elementa-zadanie-…



Внутри другого процесса в скрипт таске вызываю следующий код:



var userConnection = Get("UserConnection");

/* тут всякие манипуляции */



Dictionary parameters = new Dictionary();

parameters["UsrTestParameter"] = UsrCaseId.ToString();

processExecutor = userConnection.ProcessEngine.ProcessExecutor;

processExecutor.Execute("UsrStartTestProcess", parameters);



При компиляции процесс выдаёт ошибку: The name 'processExecutor' does not exist in the current context на строчке processExecutor = userConnection.ProcessEngine.ProcessExecutor;



Что я делаю не так? Что ещё должно быть подключено?

Нравится

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

Денис, привет!

Я использую вот такой код для запуска подпроцессов в задании-сценарии. Попробуйте его, только сделайте ваш вызываемый подпроцесс тоже компилируемым.

var user = UserConnection;
var processSchemaManager = (ProcessSchemaManager)user.GetSchemaManager(@"ProcessSchemaManager");
var processSchema = processSchemaManager.GetInstanceByName(@"ProcessName");
var process = processSchema.CreateProcess(user);
process.SetPropertyValue(@"ContactId", ContactId);
process.Execute(user);

 

Приветствую, Денис!

Запустить бизнес-процесс с элемента задания-сценария можно написав в текст сценария следующий код:

UserConnection userConnection = Get<UserConnection>("UserConnection");
var manager = userConnection.ProcessSchemaManager;
var processSchema = manager.GetInstanceByName(@"UsrStartTestProcess");
var process = processSchema.CreateProcess(userConnection);
if (processSchema.Parameters.ExistsByName(@"UsrTestParameter"))
{
    //здесь выполняется передача параметров в БП, где parameters - коллекция в текущем БП, UsrTestParameter - коллекция в запускаемом БП
    process.SetPropertyValue(@"UsrTestParameter", parameters);
}
process.Execute(userConnection);

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

Кормильцев Андрей,

Андрей, спасибо! Похоже, работает.

Если ещё будут вопросы, я задам в Техподдержке.

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

Всем доброго времени суток.

Версия 7.11.

В сценариях бизнес-процессов можно писать запросы к базе, и задавать при этом фильтры, например:

var esqAgentFilter = esqClient.CreateFilterWithParameters(FilterComparisonType.Equal, "UsrAgent", UsrAgentId);

Существует ли в БП аналог createColumnInFilterWithParameters? К примеру, мне нужен запрос двух уровней: сначала я ищу записи в одном объекте, и нахожу несколько записей, соответствующих запросу, после чего мне нужно в другом объекте найти все записи, которые соответствовали всем найденным в первом запросе.

Обычно с этим справляется как раз createColumnInFilterWithParameters, но есть ли он в БП?

Нравится

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

Денис, добрый день!

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

Денис, добрый день

Аналогичного элемента нет. Есть 2 варианта:

1. Использовать сценарий

2. Реализовать свой собственный элемент, который будет делать то что вам нужно

 

Показать все комментарии
клиентский ESQ
Filter
7.11
sales

Доброго времени суток,

Я бы хотел попросить помощи в реализации подобного SQL запроса через entitySchemaQuery на фронт енде

Select id,
       name
from TableA 
where 
    accountId = '777' 
    and (name <> 'Igor' 
         OR name <> 'Alex') 

Из того что я пробовал

var esQuery = this.Ext.create("Terrasoft.EntitySchemaQuery", { rootSchemaName: "TableA" });
				esQuery.addColumn("Id");
				esQuery.addColumn("Name");
				
var esqMainFilter = esQuery.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, "account", "777");
				
var esqFirstFilter = esQuery.createColumnFilterWithParameter(Terrasoft.ComparisonType.NOT_EQUAL, "Name", "Igor");
var esqSecondFilter = esQuery.createColumnFilterWithParameter(Terrasoft.ComparisonType.NOT_EQUAL, "Name", "Alex");
				
				
var secondaryFilter = Terrasoft.createFilterGroup();
secondaryFilter.logicalOperation = Terrasoft.LogicalOperatorType.OR;
secondaryFilter.add("esqFirstFilter", esqFirstFilter);
secondaryFilter.add("esqSecondFilter", esqSecondFilter);
				
				
esQuery.filters.logicalOperation = Terrasoft.LogicalOperatorType.AND;
esQuery.filters.add("esqMainFilter", esqMainFilter);
esQuery.filters.add("esqSecondaryFilter", secondaryFilter);

Спасибо!

Нравится

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

Добрый день, 

Вот пример похожего запроса через entitySchemaQuery на клиенте

esQuery = Ext.create("Terrasoft.EntitySchemaQuery", { rootSchemaName: "Contact" });
esQuery.addColumn("Name");
 
var esqMainFilter = this.Terrasoft.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, "Account", "b3f737a4-d95b-4c87-9082-8d0deb421882");
esQuery.filters.logicalOperation = Terrasoft.LogicalOperatorType.AND;
esQuery.filters.addItem(esqMainFilter);

var esqFirstFilter = this.Terrasoft.createColumnFilterWithParameter(Terrasoft.ComparisonType.NOT_EQUAL, "Name", "test2");
var esqSecondaryFilter = this.Terrasoft.createColumnFilterWithParameter(Terrasoft.ComparisonType.NOT_EQUAL, "Name", "test3");

var filterCollection = this.Terrasoft.createFilterGroup();
filterCollection.logicalOperation = Terrasoft.LogicalOperatorType.OR;
filterCollection.addItem(esqFirstFilter);
filterCollection.addItem(esqSecondaryFilter);

esQuery.filters.addItem(filterCollection);
esQuery.getEntityCollection();

используем this.Terrasoft.createFilterGroup() для того что бы добавить группу фильтров с OR.

выполнив этот запрос в консоли браузера профайлером отловила запрос который пришел в БД, выглядит он следующим образом:

Показать все комментарии
email
регистрация раздела
7.11
sales

Нужно создать раздел писем.

В теории нужно создать только схему реестра и ее зарегистрировать с активностями и подтянуть существующую карточку редактирования, потом по убирать все лишнее.

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

Нравится

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

Здравствуйте, Виталий

Може более подробно описать что Вы имеете ввиду и какая стоит перед Вами бизнес задача?

Denys Diachenko, решил. 

Что бы не выделяло раздел активностей при переходе в новый раздел писем нужно преопределить функцию, вот так:

changeSelectedSideBarMenu: function() {

                    var moduleConfig = this.getModuleStructure();

                    if (moduleConfig) {

                        var config = "SectionModuleV2/UsrCorrespondenceSectionV2/";

                        this.sandbox.publish("SelectedSideBarItemChanged", config, ["sectionMenuModule"]);

                    }

                }

Радчук Виталий Владимирович,

Попробуйте создать раздел на основе объекта представления, наследующего структуру объекта Активности.

Сам сейчас работаю над этой задачей.

Можем решить совместными усилиями.

Радчук Виталий Владимирович пишет:

так:changeSelectedSideBarMenu

А в какой схеме вы переопределяете этот метод?

 

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