Вопрос

Как сделать фильтрацию поля по Exists фильтру с параметром (значение другого поля)?

Ответ

Пример реализации exists-фильтра с фильтрацией:

var esq = this.Ext.create("Terrasoft.EntitySchemaQuery", {
    "rootSchemaName": "Account"
});
// добавляем колонки запроса
esq.addColumn("Id");
...
// условие фильтрации для использования внутри exists
// searchValue - значение для сравнения с колонкой SearchNumber
var subFilters = Terrasoft.createFilterGroup();
subFilters.addItem(Terrasoft.createColumnFilterWithParameter(
    Terrasoft.ComparisonType.EQUAL, "SearchNumber", searchValue));
// добавляем exists-фильтр с условием в коллекцию фильтров esq
var filters = esq.filters;
filters.add(Terrasoft.createExistsFilter("[AccountCommunication:Account:Id].Id", subFilters));
//получаем значение запроса
esq.getEntityCollection(function(result) {
...
}, this);

В результате на сервер будет отправлен примерно такой запрос:

SELECT Id, ... FROM Account
WHERE EXISTS 
(SELECT
[SubAccountCommunication].[Id] [Id]
FROM
[dbo].[AccountCommunication] [SubAccountCommunication] WITH(NOLOCK)
WHERE
[SubAccountCommunication].[AccountId] = [Account].[Id]
AND [SubAccountCommunication].[SearchNumber] = @P1
)

Параметр @P1 будет хранить значение searchValue, которое мы передавали в условие фильтрации.

Нравится

Поделиться

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

Вопрос

В каких и какие настройки IIS необходимо поменять, что бы изменить продолжительность жизни сессии.

Какие значения установлены сейчас?

Ответ

Выберите пункт «Advanced settings» в правой части окна.

В настройках измените значение «Connection time-out»:

Изображение удалено.

 

Нравится

Поделиться

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

Вопрос

Как добавить поле в "BANT" контейнер (bantcontainer) раздела на карточку продажи

Ответ

добавления поля Вы можете посмотреть пример добавления поля «Бюджет клиента» в схеме «OpportunityPageV2» (пакет «Opportunity») (рис. 1) и сделать аналогично в своей пользовательской схеме «OpportunityPageV2», который находится в Вашем пользовательском пакете.

{
    "operation": "insert",
    "parentName": "BantProfile",
    "propertyName": "items",
    "name": "OpportunityBudget",
    "values": {
        "bindTo": "Budget",
        "layout": {"column": 5, "row": 1, "colSpan": 19}
    },
    "alias": {
        "name": "Budget",
        "excludeProperties": ["layout"],
        "excludeOperations": ["remove", "move"]
    }
},

Изображение удалено.

Стоит учесть следующее:

- в “parentName” необходимо указать «BankProfile»;

- в “bindTo” необходимо указать название желаемой колонки;

- в “layout” указать расположение колонки (необходимо учитывать текущее расположение колонок). 

Нравится

Поделиться

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

Вопрос

При выборе взаимосвязи Account-Account список выбора типов взаимосвязей пустой. Возможно, связано с тем, что у нас несколько типов Account’ов со своими страницами.

Ответ

Судя по всему, система не может определить, для какой сущности ей построить взаимосвязь – контрагента или контакта. Соответственно, нарушается фильтрация и при выборе типа взаимосвязи.

Проверьте, пожалуйста, отладкой метод addRelation() в схеме BaseRelationshipDetailV2. Скорее всего, проблема в строке

var defaultValueColumnName = this.get("CardPageName") === "ContactPageV2" ? "ContactA" : "AccountA";

Возможно, переменная defaultValueColumnName получает некорректное значение.

Если в Вашей конфигурации данный метод (либо другая связанная функциональность) переопределена, необходимо анализировать дополнительно. Убедитесь, что в результате выполнения метода объект openCardConfig получает корректные значения (в особенности это касается defaultValues). Если это не так, необходимо переопределить данный метод в замещающем клиентском модуле для BaseRelationshipDetailV2 или AccountRelationshipDetailV2 и сформировать корректную конфигурацию параметров для карточки редактирования детали.

Нравится

Поделиться

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

Вопрос

В разделе Планирование (Forecast) необходимо расчёт факта выполнять на основе счетов.

Ответ

Необходимо:

1) Внести изменения в схему ForecastBuilder. В методе openForecastPage() код:

var valuePairs = [
 {
  name: "EntitySchemaUId",
  value: "ae46fb87-c02c-4ae8-ad31-a923cdd994cf"
 },
 {
  name: "EntitySchemaName",
  value: "Opportunity"
 }
];

заменить на:

var valuePairs = [
 {
  name: "EntitySchemaUId",
  value: "bfb313dd-bb55-4e1b-8e42-3d346e0da7c5"
 },
 {
  name: "EntitySchemaName",
  value: "Invoice"
 }
];

2) Внести изменения в хранимую процедуру tsp_RecalculateForecastFact

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

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[tsp_RecalculateForecastFact]
@ForecastId UNIQUEIDENTIFIER = NULL,
@CurrentUserContactId UNIQUEIDENTIFIER = NULL
AS
IF @ForecastId IS NULL
BEGIN
	RETURN;
END
DECLARE @PlanIndicatorId UNIQUEIDENTIFIER
DECLARE @FactIndicatorId UNIQUEIDENTIFIER
DECLARE @FactPercentIndicatorId UNIQUEIDENTIFIER
DECLARE @PotentialIndicatorId UNIQUEIDENTIFIER
DECLARE @CompletedId UNIQUEIDENTIFIER
DECLARE @ForecastItemId UNIQUEIDENTIFIER
DECLARE @DimensionId UNIQUEIDENTIFIER
DECLARE @DimensionValueId UNIQUEIDENTIFIER
DECLARE @PeriodId UNIQUEIDENTIFIER
DECLARE @StartDate DATE
DECLARE @DueDate DATE
DECLARE @MaxDueDate DATE
DECLARE @ColumnName NVARCHAR(100)
DECLARE @SQLText NVARCHAR(MAX)
DECLARE @PlanAmount DECIMAL(18,2)
DECLARE @FactAmount DECIMAL(18,2)
DECLARE @PotentialAmount DECIMAL(18,2)
DECLARE @FactPotentialAmountTable TABLE (PlanAmount DECIMAL(18,2), FactAmount DECIMAL(18,2), PotentialAmount DECIMAL(18,2))
SET @PlanIndicatorId = '{CBD311C7-6E1B-4324-BF21-192681349DDF}'
SET @FactIndicatorId = '{52CAE26F-84F6-42A0-AAEF-97790AF3B8D9}'
SET @FactPercentIndicatorId = '{E0D66FFB-A3E3-4DA9-BCB7-95D27033286E}'
SET @PotentialIndicatorId = '{A004FC7A-D63D-4E3C-9356-0AD77B2600F3}'
--SET @CompletedId = '{60D5310C-5BE6-DF11-971B-001D60E938C6}'
SET @CompletedId = '{698D39FD-52E6-DF11-971B-001D60E938C6}' --Paid PaymentStatusId from InvoicePaymentStatus
DELETE FROM ForecastItemValue 
WHERE ForecastIndicatorId IN (@FactIndicatorId, @FactPercentIndicatorId, @PotentialIndicatorId)
AND EXISTS (SELECT 1 
			FROM ForecastItem fi 
			WHERE ForecastItemValue.ForecastItemId = fi.Id
				AND fi.ForecastId = @ForecastId 
			) 
SET @MaxDueDate = (SELECT Convert(Date, MAX(StartDate), 104) FROM Invoice o WHERE o.PaymentStatusId = @CompletedId)
DECLARE Cur CURSOR STATIC LOCAL FOR
SELECT
fi.Id ForecastItemId,
d.Id DimensionId, 
fi.DimensionValueId DimensionValueId,
p.Id PeriodId,
p.StartDate StartDate,
p.DueDate DueDate,
d.[Path] + 'Id'
FROM ForecastItem fi
INNER JOIN Forecast f ON f.Id = fi.ForecastId
INNER JOIN ForecastDimension fd ON fd.Id = fi.ForecastDimensionId
INNER JOIN Dimension d ON d.Id = fd.DimensionId
INNER JOIN Period p ON p.PeriodTypeId = f.PeriodTypeId
WHERE f.Id = @ForecastId
AND ISNULL(d.[Path],'') <> ''
AND p.StartDate <= @MaxDueDate
 
SET NOCOUNT ON;
 
OPEN Cur
FETCH NEXT FROM Cur INTO @ForecastItemId, @DimensionId, @DimensionValueId, @PeriodId, @StartDate, @DueDate, @ColumnName
WHILE @@FETCH_STATUS = 0
BEGIN
	SET @DueDate = DATEADD(DAY, 1, @DueDate)
	DELETE FROM @FactPotentialAmountTable
	SET @SQLText = N'
		SELECT
		(SELECT SUM(ISNULL(fiv.[Value], 0))
		FROM [ForecastItemValue] fiv
		WHERE fiv.[ForecastItemId] = @P5
		AND fiv.[PeriodId] = @P6
		AND fiv.[ForecastIndicatorId] = @P7
		) PlanAmount,
		(SELECT SUM(ISNULL(o.[Amount], 0)) 
		FROM [Invoice] o
		WHERE o.[PaymentStatusId] = @P1
		AND o.[StartDate] >= @P2 
		AND o.[StartDate] < @P3
		AND o.' + @ColumnName + N' = @P4
		) FactAmount,
		(SELECT SUM(ISNULL(o.[Amount], 0)) 
		FROM [Invoice] o
		INNER JOIN [InvoicePaymentStatus] os ON os.[Id] = o.[PaymentStatusId]
		WHERE os.[FinalStatus] = 0
		AND o.[StartDate] >= @P2 
		AND o.[StartDate] < @P3
		AND o.' + @ColumnName + N' = @P4
		) PotentialAmount'
	INSERT INTO @FactPotentialAmountTable exec sp_executesql @SQLText,
	N'@P1 UNIQUEIDENTIFIER, @P2 DATE, @P3 DATE, @P4 UNIQUEIDENTIFIER, @P5 UNIQUEIDENTIFIER, @P6 UNIQUEIDENTIFIER, @P7 UNIQUEIDENTIFIER',
	@P1 = @CompletedId, @P2 = @StartDate, @P3 = @DueDate, @P4 = @DimensionValueId, @P5 = @ForecastItemId,
	@P6 = @PeriodId, @P7 =  @PlanIndicatorId
	SELECT @PlanAmount = PlanAmount, @FactAmount = FactAmount, @PotentialAmount = PotentialAmount 
	FROM @FactPotentialAmountTable
	IF (@FactAmount <> 0)
	BEGIN
		INSERT INTO ForecastItemValue
		(
			Id,
			CreatedOn,
			CreatedById,
			ModifiedOn,
			ModifiedById,
			ProcessListeners,
			ForecastIndicatorId,
			[Value],
			PeriodId,
			ForecastItemId
		)
		VALUES
		(
			NEWID(),
			GETUTCDATE(),
			@CurrentUserContactId,
			GETUTCDATE(),
			@CurrentUserContactId,
			0,
			@FactIndicatorId,
			@FactAmount,
			@PeriodId,
			@ForecastItemId
		)
		IF (@PlanAmount <> 0)
		BEGIN
			INSERT INTO ForecastItemValue
			(
				Id,
				CreatedOn,
				CreatedById,
				ModifiedOn,
				ModifiedById,
				ProcessListeners,
				ForecastIndicatorId,
				[Value],
				PeriodId,
				ForecastItemId
			)
			VALUES
			(
				NEWID(),
				GETUTCDATE(),
				@CurrentUserContactId,
				GETUTCDATE(),
				@CurrentUserContactId,
				0,
				@FactPercentIndicatorId,
				CAST((@FactAmount * 100 / @PlanAmount) AS DECIMAL(18, 2)),
				@PeriodId,
				@ForecastItemId
			)
		END
	END
 
	IF (@PotentialAmount <> 0)
	BEGIN
		INSERT  INTO ForecastItemValue
		(
			Id,
			CreatedOn,
			CreatedById,
			ModifiedOn,
			ModifiedById,
			ProcessListeners,
			ForecastIndicatorId,
			[Value],
			PeriodId,
			ForecastItemId
		)
		VALUES
		(
			NEWID(),
			GETUTCDATE(),
			@CurrentUserContactId,
			GETUTCDATE(),
			@CurrentUserContactId,
			0,
			@PotentialIndicatorId,
			@PotentialAmount ,
			@PeriodId,
			@ForecastItemId
		)
	END
FETCH NEXT FROM Cur INTO @ForecastItemId, @DimensionId, @DimensionValueId, @PeriodId, @StartDate, @DueDate, @ColumnName
END
CLOSE Cur
DEALLOCATE Cur

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

SELECT * FROM Dimension

По умолчанию в ней указаны: Account, ResponsibleDepartment, Owner, LeadType

Нравится

Поделиться

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

Вопрос

Необходимо вывести на деталь "Файлы" дату добавления файла

Ответ

Создайте замещающую схему детали:

define("FileDetailV2", ["ViewUtilities", "ConfigurationConstants", "ConfigurationEnums", "ImageListViewModel",
        "css!FileDetailCssModule"], function(ViewUtilities, ConfigurationConstants, ConfigurationEnums) {
    return {
        attributes: {
        },
        messages: {
        },
        methods: {
            getGridDataColumns: function() {
                var baseGridDataColumns = this.callParent(arguments);
                var gridDataColumns = {
                    "Type": {
                        path: "Type"
                    },
                    "Version": {
                        path: "Version"
                    }
                };
                return this.Ext.apply(baseGridDataColumns, gridDataColumns);
            }
        },
        diff: /**SCHEMA_DIFF*/[
            {
                "operation": "remove",
                "name": "DataGrid"
            },
            {
                "operation": "insert",
                "name": "DataGrid1",
                "parentName": "Detail",
                "propertyName": "items",
                "values": {
                    "itemType": Terrasoft.ViewItemType.GRID,
                    "listedZebra": true,
                    "collection": {"bindTo": "Collection"},
                    "activeRow": {"bindTo": "ActiveRow"},
                    "primaryColumnName": "Id",
                    "isEmpty": {"bindTo": "IsGridEmpty"},
                    "isLoading": {"bindTo": "IsGridLoading"},
                    "multiSelect": {"bindTo": "MultiSelect"},
                    "selectedRows": {"bindTo": "SelectedRows"},
                    "sortColumn": {"bindTo": "sortColumn"},
                    "sortColumnDirection": {"bindTo": "GridSortDirection"},
                    "sortColumnIndex": {"bindTo": "SortColumnIndex"},
                    "linkClick": {"bindTo": "linkClicked"},
                    "type": "listed",
                    "visible": {
                        "bindTo": "isImageManagerDetailView",
                        "bindConfig": {"converter": "getDataGridVisible"}
                    },
                    "listedConfig": {
                        "name": "DataGridListedConfig",
                        "items": [
                            {
                                "name": "NameListedGridColumn",
                                "bindTo": "Name",
                                "position": {
                                    "column": 1,
                                    "colSpan": 14
                                },
                                "type": Terrasoft.GridCellType.LINK
                            },
                            {
                                "name": "VersionListedGridColumn",
                                "bindTo": "Version",
                                "position": {
                                    "column": 15,
                                    "colSpan": 3
                                }
                            },
                            {
                                "name": "CreatedOnListedGridColumn",
                                "bindTo": "CreatedOn",
                                "position": {
                                    "column": 22,
                                    "colSpan": 2
                                }
                            }
                        ]
                    },
                    "tiledConfig": {
                        "name": "DataGridTiledConfig",
                        "grid": {
                            "columns": 24,
                            "rows": 3
                        },
                        "items": [
                            {
                                "name": "NameTiledGridColumn",
                                "bindTo": "Name",
                                "position": {
                                    "row": 1,
                                    "column": 1,
                                    "colSpan": 24
                                },
                                "type": Terrasoft.GridCellType.LINK
                            },
                            {
                                "name": "ModifiedByTiledGridColumn",
                                "bindTo": "ModifiedBy",
                                "position": {
                                    "row": 1,
                                    "column": 25,
                                    "colSpan": 12
                                }
                            },
                            {
                                "name": "VersionTiledGridColumn",
                                "bindTo": "Version",
                                "position": {
                                    "row": 1,
                                    "column": 27,
                                    "colSpan": 12
                                }
                            },
                            {
                                "name": "ModifiedOnTiledGridColumn",
                                "bindTo": "ModifiedOn",
                                "position": {
                                    "row": 1,
                                    "column": 39,
                                    "colSpan": 12
                                }
                            },
                            {
                                "name": "SizeTiledGridColumn",
                                "bindTo": "Size",
                                "position": {
                                    "row": 1,
                                    "column": 51,
                                    "colSpan": 12
                                }
                            }
                        ]
                    },
                    "linkClick": {"bindTo": "linkClicked"}
                }
            }
        ]   /**SCHEMA_DIFF*/
    };
});

 

Нравится

Поделиться

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

Симптомы

При подключении к серверу происходит ошибка:

Сообщение: В процессе получения текущего времени произошла ошибка 

Дополнительная информация: 

{"request":{"id":6,"headers":{"X-Terrasoft-Mobile":"true","Accept":"application/json","Content-Type":"application/json","Authorization":"Cookie","X-Requested-With":"XMLHttpRequest"},"options":{"url":"http://xxx.xxx.xxx.xxx/0/Mobile/Services/MobileDataService.ashx?functio…","scope":{"initialConfig":{"url":"http://xxx.xxx.xxx.xxx/0/Mobile/Services/MobileDataService.ashx?functio…","scope":{},"headers":{"X-Terrasoft-Mobile":"true","Accept":"application/json","Content-Type":"application/json","Authorization":"Cookie"},"method":"GET","disableCaching":false},"performanceCounterKey":"d0bdde84-6a5e-4855-bdd0-e7dafea8f9a1"},"headers":{"X-Terrasoft-Mobile":"true","Accept":"application/json","Content-Type":"application/json","Authorization":"Cookie"},"method":"GET","disableCaching":false},"async":true},"requestId":6,"status":500,"statusText":"Internal Server Error","responseText":"{\r\n  \"Code\": -1,\r\n  \"Exception\": \"System.Net.Sockets.SocketException (0x80004005): Обычно разрешается только одно использование адреса сокета (протокол/сетевой адрес/порт) 127.0.0.1:6379\\r\\n  в System.Net.Sockets.Socket.Connect(IPAddress[] addresses, Int32 port)\\r\\n  в System.Net.Sockets.Socket.Connect(String host, Int32 port)\\r\\n  в ServiceStack.Redis.RedisNativeClient.Connect()\"\r\n}","responseXML":null,"responseBytes":null}

Причина

Порт, на который происходит редирект занят другим приложением

Решение

Использовать для мобильного подключения порты, которые не используются другим ПО

Необходимые условия и возможные ограничения

Подключение на внешний адрес и редирект данного подключения на внутренний адрес с использованием занятого порта.

Нравится

Поделиться

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

Вопрос:

Имеется задача поздравлять по Email сотрудников и клиентов с днем рождения. Подскажите пожалуйста, как через бизнес процесс решить? 

Ответ:

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

Для таких целей в БП целесообразней использовать элемент Задание - сценарий. Примеры работы с объектами в скрипте можно найти на Академии, нужный в данной задаче объект - ContactAnniversary .

В рамках же скрипта можно выполнять и отправку письма для коллекции контактов, пример отправки по созданному id активности письма можно найти в базовом процессе "Отправка email сообщения контакту обращения" пакета Case.

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

Нравится

Поделиться

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

Вопрос

При автоматической отправке email по процессу выдает ошибку "Сбой установки соединения из-за неожиданного формата пакета". При отправке письма из этого ящика вручную все работает.

Ответ

Данная проблема возникает из-за прав на почтовый ящик.

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

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

Нравится

Поделиться

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

Вопрос

Как передать идентификатор контрагента, из карточки заказа, на страницу редактирования детали "Продукт в заказе" через сообщения sandbox?

Ответ

Код замещающей схемы страницы Заказа:

define("OrderPageV2", ["OrderPageV2Resources", "GeneralDetails"],
function(resources, GeneralDetails) {
    return {
        entitySchemaName: "Order",
        details: /**SCHEMA_DETAILS*/{
        }/**SCHEMA_DETAILS*/,
        diff: /**SCHEMA_DIFF*/[
        ]/**SCHEMA_DIFF*/,
        attributes: {},
        methods: {
            onEntityInitialized: function() {
                this.callParent(arguments);
                this.sandbox.subscribe("OrderProductPageAsksForData", function(arg) {
                    console.log("OrderProductPageV2 запрашивает данные прямо сейчас,");
                    console.log("по Id песочницы: " + arg.sandboxId);
                    // Высылаем данные.
                    this.sendDataToOrderProductPage(arg.sandboxId);
                }, this, [this.sandbox.id]);
                console.log("Мы(OrderPageV2) подписались на сообщение: OrderProductPageAsksForData.");
                console.log("Id песочницы в этой карточке(OrderPageV2) следующий:");
                console.log(this.sandbox.id);
            },
            sendDataToOrderProductPage: function(sandboxId) {
                this.sandbox.publish("DataToOrderProductPage", { accountId: this.get("Account").value }, [sandboxId]);
                console.log("AccountId отправлен сообщением для OrderProductPageV2 по Id: " + sandboxId);
            }
        },
        rules: {},
        messages: {
            "DataToOrderProductPage": {
                mode: Terrasoft.MessageMode.PTP,
                direction: Terrasoft.MessageDirectionType.PUBLISH
            },
            "OrderProductPageAsksForData": {
                mode: Terrasoft.MessageMode.PTP,
                direction: Terrasoft.MessageDirectionType.SUBSCRIBE
            }
        },
        userCode: {}
    };
});

Код замещающей схемы страницы детали Продукт в заказе:

define("OrderProductPageV2", ["BusinessRuleModule", "OrderUtilities"],
    function(BusinessRuleModule) {
        return {
            entitySchemaName: "OrderProduct",
            mixins: {},
            attributes: {},
            methods: {
                onEntityInitialized: function() {
                    this.callParent(arguments);
                    this.sandbox.subscribe("DataToOrderProductPage", function(arg) {
                        console.log("OrderPageV2 передает нам данные!");
                        alert("accountId: " + arg.accountId);
                    }, this, [this.sandbox.id]);
                    console.log("Мы(OrderProductPageV2) подписались на сообщение: DataToOrderProductPage.");
                    console.log("По нашему(OrderProductPageV2) Id песочницы:");
                    console.log(this.sandbox.id);
                    this.sandbox.publish("OrderProductPageAsksForData", {
                        sandboxId: this.sandbox.id
                    }, [this.getOrderPageSandboxId()]);
                    console.log("Запросили данные у OrderPageV2, по её Id песочницы: " + this.getOrderPageSandboxId());
                },
                getOrderPageSandboxId: function() {
                    var index = this.sandbox.id.indexOf("_detail_ProductInProducts");
                    return this.sandbox.id.substring(0, index);
                }
            },
            messages: {
                "DataToOrderProductPage": {
                    mode: Terrasoft.MessageMode.PTP,
                    direction: Terrasoft.MessageDirectionType.SUBSCRIBE
                },
                "OrderProductPageAsksForData": {
                    mode: Terrasoft.MessageMode.PTP,
                    direction: Terrasoft.MessageDirectionType.PUBLISH
                }
            },
            diff: /**SCHEMA_DIFF*/[
            ]/**SCHEMA_DIFF*/,
            rules: {
            }
        };
    }
);

 

Нравится

Поделиться

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