Проблема

Есть поле

{
   "operation": "insert",
   "name": "UsrJob",
   "values": {
      "layout": {"column": 0, "row": 0, "colSpan": 12},
      "bindTo": "UsrJob"
   },
   "parentName": "Header",
   "propertyName": "items"
}



В атрибутах идет подписка на событие

"Job": {
   dependencies: [{ 
      columns: ["UsrJob"],
      methodName: "jobChanged"
   }]
}



В метод jobChanged() при изменении поля UsrJob не заходит. Схема карточки наследуется от BasePageV2.

Причина

Пользователь в созданной схеме переопределил метод родительской схемы onEntityInitialized() следующим образом:

onEntityInitialized: function() {
   this.set("IsChanged", true);
   if (this.isAddMode()) {
      this.hideBodyMask();
      return;
   }
   var forecastId = (this.isCopyMode())
   ? this.get("SourceEntityPrimaryColumnValue")
   : this.get("Id");
   if (!Ext.isEmpty(forecastId)) {
      var esq = Ext.create("Terrasoft.EntitySchemaQuery", {
      rootSchemaName: "UsrForecastDimension",
      rowCount: 1
   });
   esq.addColumn("Id");
   esq.addColumn("UsrDimension");
   esq.filters.add("ForecastFilter", Terrasoft.createColumnFilterWithParameter(
      Terrasoft.ComparisonType.EQUAL, "UsrForecast", forecastId));
   esq.getEntityCollection(function(response) {
      if (response && response.success) {
         var collection = response.collection;
         if (collection.getCount() > 0) {
            var collectionItems = collection.getItems();
            var dimensionItem = collectionItems[0];
            var dimension = dimensionItem.get("UsrDimension");
            this.set("UsrDimension", dimension);
         }
      }
      this.hideBodyMask();
      }, this);
   }
},

При этом не был вызван метод onEntityInitialized() базовой схемы.

Решение

Добавить в замещающий метод вызов замещенного метода строкой: 

this.callParent(arguments);

 

Нравится

Поделиться

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

1. В разделе дизайнера системы "Права доступа на операции" создать системную операцию. Например, с кодом CanChangeContractFields

2. В код страницы, на которой мы будем использовать нашу операцию добавляем зависимость страницы от модуля RightUtilities. Пример:

define("ContractPageV2", ["RightUtilities","ProcessModuleUtilities"], function(RightUtilities,ProcessModuleUtilities)

3. В блоке methods{} найти и дополнить функцию init:, а если ее нет - вызвать.

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

Ответ "да" или "нет" система передаст в указанный нами атрибут.

init: function() {
    const operationNames = [
        "CanChangeContactFields" //Здесь через запятую нужно перечислить все системные операции, которые нужно проверить
    ];
    RightUtilities.checkCanExecuteOperations(operationNames, function(result) {
        this.set("FieldsRights", result.CanChangeContactFields); // "FieldsRights" - название атрибута, в который мы передаем результат проверки
    }this);  // CanChangeContactFields - проверку по какой операции мы передаем в атрибут
    this.callParent(arguments);
}

4. Использовать ответ. Например, на поле или кнопке

4.1 ДОСТУП К РЕДАКТИРОВАНИЮ ПОЛЯ

Для этого находим наше поле в блоке diff[] и изменяем значение параметра "enabled"

{
    "operation": "insert",
    "name": "STRING2b088f15-40f9-4bbb-a4bc-dd846be945b2",
    "values": {
        "layout": {
            "colSpan": 12,
            "rowSpan": 1,
            "column": 0,
            "row": 3,
            "layoutName": "Header"
        },
        "bindTo": "UsrField1"//Название нашего поля
        "enabled": {
            "bindTo": "FieldsRights" //возможность редактирования поля зависит от результата проверки, который хранит указанный ранее атрибут
        }
    },
    "parentName": "Header",
    "propertyName": "items",
    "index": 6
}

4.2 ДОСТУП К НАЖАТИЮ КНОПКИ

По аналогии используем параметр "enabled". Например, кнопка в меню "Действия":

 actionMenuItems.addItem(this.getActionsMenuItem({
    "Caption": "Тестовая кнопка",
    "Tag": "runProcess",
    "Enabled": {"bindTo": "FieldsRights"}//активность кнопки зависит от результата проверки, который хранит указанный ранее атрибут
}));

 

Нравится

Поделиться

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

Вопрос

Как сделать фильтрацию поля по 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 комментариев
Показать все комментарии

Симптомы

Ошибка если добавить ленту в новое рабочее место. Текст поста пишется в поле CreatedBy

Решение

В схеме настроек грида раздела «Лента» UsrMobileSocialMessageGridPageSettingsSupervisorworkplace добавляем след.:

{
    "operation": "insert",
    "name": "e0de54d7-b417-42b1-8081-36337aa344a1",
    "values": {
        "row": 0,
        "content": "Created by",
        "columnName": "CreatedBy",
        "dataValueType": 1,
        "operation": "insert"
    },
    "parentName": "settings",
    "propertyName": "items",
    "index": 1
}

2. И в настройке выше, для колонки «Message» меняем ее свойство row на 1:

"row": 1,

 

Нравится

Поделиться

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