Есть потребность простом запросе на проверку данных.
Найти примеров не смог и есть ли они вообще.

if(new Select(userConnection)
                                                .Column("StartDate")
                                                .From("CurrencyRate")
                                                .Where("StartDate").IsEqual(Column.Const(_date)).Execute() > 0)
{
  // код
}

Как я понимаю можно так?

Нравится

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

Если это серверная логика, то так:

if ((new Select(UserConnection).Column(Func.Count("Id")).From("ActivityCorrespondence").Where("ActivityId").IsEqual(Column.Parameter(Entity.ActivityId)) as Select).ExecuteScalar<int>() > 0) {
//...
}

Также учтите, что поле «StartDate» хранит дату-время, поэтому на равенство сравнивать нет смысла, нужно взять интервал двух дат начала и конца периода (то есть дня) и сравнивать при помощи «IsLessOrEqual» и «IsGreaterOrEqual».

Вышла ошибка как только переделал

UserConnection является тип но используется как переменная

if ((new Select(UserConnection)
.Column(Func.Count("Rate"))
.From("CurrencyRate")
.Where("StartDate").IsLessOrEqual(Column.Const(_today))
.And("StartDate").IsGreaterOrEqual(Column.Const(_yesterday))
.ExecuteScalar() > 0))
{
return "That date already exists!";
} else {

Напишите с маленькой буквы.

Нашел ошибку в коде
Но ошибка все равно выходит

Чтобы ошибка не выходила, её нужно исправить.

Мой косяк.
Спасибо, заработало.

DateTime _today = DateTime.Today;
				DateTime _yesterday = DateTime.Today.AddDays(-1);
				var userConnection = (UserConnection)HttpContext.Current.Session["UserConnection"];
 
				var entityRowCount = (new Select(userConnection)
						.Column(Func.Count("Rate"))
						.From("CurrencyRate")
						.Where("StartDate").IsLessOrEqual(Column.Const(_today))
							.And("StartDate").IsGreaterOrEqual(Column.Const(_yesterday))
						as Select).ExecuteScalar<int>();
				if ( entityRowCount > 0) 
				{
					return "That date already exists!";
				} else {

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

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

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

Схема детали указывается при объявлении детали в схеме карточки куда она добавляется, там же указывается и целевой объект БД, мастер-колонки и т.д.
В таблице SysDetails существует запись которая связывает конкретную деталь ее наименование и опять же объект детали.
Где-же связь со страницей редактирования ?

Нравится

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

"Севостьянов Илья Сергеевич" написал:Как устанавливается связь между деталью и ее страницей редактирования ?

sql запросом

Ну в смысле SQL-запросом.
Вот деталь CustomDetail для объекта CustomObject:
1) Создаем схему детали - CustomDetailScheme

define("СustomDetailScheme", [], function() {
	return {
		entitySchemaName: "CustomObject",
		details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
		diff: /**SCHEMA_DIFF*/[]/**SCHEMA_DIFF*/,
		methods: {}
	};
});

2) Создаем страницу редактирования CustomObjectAddPage ([color=red]это я так хотел бы ее назвать[/color], мастер создает CustomObject1Page)

define("CustomObjectAddPage", [], function() {
	return {
		entitySchemaName: "CustomObject",
		details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
		diff: /**SCHEMA_DIFF*/[
			{
				"operation": "insert",
				"name": "SomeField4e5d48ba-e8d3-4e7f-936d-cbf296d05c99",
				"values": {
					"layout": {
						"colSpan": 24,
						"rowSpan": 1,
						"column": 0,
						"row": 0,
						"layoutName": "Header"
					},
					"bindTo": "SomeField"
				},
				"parentName": "Header",
				"propertyName": "items",
				"index": 0
			}
		]/**SCHEMA_DIFF*/,
		methods: {},
		rules: {}
	};
});

3) В некой схеме карточки, например в схеме Контакта - в замещающем объекте объявляем добавление на страницу, в синтаксисе которого определяется объект детали и ее схема, а так же колонки по которым запись текущей карточки объединяется с записью в объекте детали:

define("ContactPageV2", [],
	function() {
		return {
			entitySchemaName: "Contact",
			attributes: {},
			details: {
				"myCustomDetail": {
					"schemaName": "СustomDetailScheme",
					"filter": {
						"detailColumn": "Contact",
						"masterColumn": "Id"
					}
				}
			},
			diff: [
				{
					"operation": "insert",
					"name": "myCustomDetail",
					"values": {
						"itemType": 2,
						"markerValue": "added-detail",
						"visible": true
					},
					"parentName": "GeneralInfoTab",
					"propertyName": "items",
					"index": 3
				}
			],
			methods: {}
		};
	}
);

Саму же деталь, называем "КастомнаяДеталь" и регистрируем
запись в SysDetail в которой собственно и сопоставляются:
"Заголовок" (Caption) к UId записям в таблице SysSchema - схемы детали (DetailSchemaUId) и схемы объекта детали (EntitySchemaUId)

Связи схемы детали и объекта детали - аш в 3-х местах, и ни единого упоминания страницы редактирования для объекта детали ни в коде ни в БД.
Каким же образом созданная мастером CustomObject1Page работает, а стоит создать схему мне самостоятельно и назвать ее CustomObjectAddPage то каким образом мне установить ее как странице редактирования для детали - ни в коде ни в БД я не нашел упоминаний, мысль только одна - что схема карточки редактирования объекта детали выбирается по имени, т.е. для детали с объектом CustomObject бедт осуществляться поиск схемы CustomObject[цифра]Page .
Так что ли получается ?

"Севостьянов Илья Сергеевич" написал:Так что ли получается ?

Нет, связь происходит через таблицу SysModuleEdit через развязочный объект SysModuleEntity. К примеру:

Вот объект:
SELECT * FROM SysSchema WHERE Name = 'Opportunity' AND ExtendParent = 0
запоминаем его UId --ae46fb87-c02c-4ae8-ad31-a923cdd994cf

Вот его развязочная запись:
SELECT * FROM SysModuleEntity WHERE SysEntitySchemaUId = 'ae46fb87-c02c-4ae8-ad31-a923cdd994cf'
Запоминаем Id --a4e7bf65-7380-e011-afbc-00155d04320c

Ну и вот страница(цы) редактирования:
SELECT * FROM SysModuleEdit WHERE SysModuleEntityId = 'a4e7bf65-7380-e011-afbc-00155d04320c'

Вот собственно в SysModuleEdit и можно подменить страницу.

Спасибо, вот теперь ситуация немного прояснилась, там же и UId миникарточки и еще мног овсего интересного :)

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

define("ActivitySectionV2", ["BaseFiltersGenerateModule", "ConfigurationConstants", "ConfigurationEnums",
"ProcessModuleUtilities", "GoogleIntegrationUtilitiesV2",
"ActivitySectionGridRowViewModel", "css!ActivitySectionCSS"],
function (BaseFiltersGenerateModule, ConfigurationConstants, ConfigurationEnums,
ProcessModuleUtilities) {
return {
entitySchemaName: "Activity",
mixins: {},
attributes: {},
messages: {},
methods: {
// Переопределение базового метода, который модифицирует строку данных перед загрузкой в реестр.
prepareResponseCollectionItem: function (item) {
// Вызов базового метода.
this.callParent(arguments);
item.customStyle = null;
// Определение категории активности.
var category = item.get("ActivityCategory");
if (category) {
switch (category.value) {
// Выполнить
case "f51c4643-58e6-df11-971b-001d60e938c6":
item.customStyle = {
// Цвет текста
"color": "black",
// Цвет фона — зеленый.
"background": "#dbfbe1"
}; break;

// Встреча
case "42c74c49-58e6-df11-971b-001d60e938c6":
item.customStyle = {
// Цвет текста
"color": "black",
// Цвет фона — красный.
"background": "#fbdbdc"
}; break;

case "8b16d130-313e-4b12-a12e-73a2dd8d33cf":
item.customStyle = {
// Цвет текста
"color": "black",
// Цвет фона — красный.
"background": "#fbdbdc"
}; break;

// Звонок
case "03df85bf-6b19-4dea-8463-d5d49b80bb28":
item.customStyle = {
// Цвет текста
"color": "black",
// Цвет фона — синий.
"background": "#dbe0fb"
}; break;
// Звонок
case "e52bd583-7825-e011-8165-00155d043204":
item.customStyle = {
// Цвет текста
"color": "black",
// Цвет фона — синий.
"background": "#dbe0fb"
}; break;
//Чат
case "2365ae4f-58e6-df11-971b-001d60e938c6": item.customStyle = {
// Цвет текста
"color": "black",
// Цвет фона — желтый.
"background": "#fbfbdb"
}; break;

}
}
}
},
diff: /**SCHEMA_DIFF*/[]/**SCHEMA_DIFF*/
};
}
);

Нравится

1 комментарий
define("OrderSectionV2", ["OrderConfigurationConstants"],
    function (OrderConfigurationConstants) {
        return {
            // Название схемы раздела.
            entitySchemaName: "Order",
            // Коллекция методов модели представления раздела.
            methods: {
                // Переопределение базового метода, который модифицирует строку данных перед загрузкой в реестр.
                prepareResponseCollectionItem: function (item) {
                    this.callParent(arguments);
                    item.customStyle = null;
                    var running = item.get("Status");
                    //Если условие подходит, меняем цвет записи на темно-серый, а фон на светло-зеленый.
                    if (running.value === OrderConfigurationConstants.Order.OrderStatus.Running) {
                        item.customStyle = {
                            'color': "darkgrey",
                            'background': "#D8FBC2"
                        }
                    }
                }
            }
        };
    });
Показать все комментарии

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

Нравится

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

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

"Варфоломеев Данила" написал:

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


Добрый день Данила, а как вызывать модуль?

Вот пример работы модуля модального окна:

Модуль:

 define("UsrMyModalModule", ["ModalBox", "BaseSchemaModuleV2"],
        function(ModalBox) {
    Ext.define("Terrasoft.configuration.UsrMyModalModule", {
        extend: "Terrasoft.BaseSchemaModule",
        alternateClassName: "Terrasoft.UsrMyModalModule",
        /**
         * @inheritDoc Terrasoft.BaseSchemaModule#generateViewContainerId
         * @overridden
         */
        generateViewContainerId: false,
        /**
         * @inheritDoc Terrasoft.BaseSchemaModule#initSchemaName
         * @overridden
         */
        initSchemaName: function() {
            this.schemaName = "UsrMyModalPage";
        },
        /**
         * @inheritDoc Terrasoft.BaseSchemaModule#initHistoryState
         * @overridden
         */
        initHistoryState: Terrasoft.emptyFn,
    });
    return Terrasoft.UsrMyModalModule;
});

Страница модального окна:

define("UsrMyModalPage", ["ModalBox"], function(ModalBox) {
    return {
        attributes: {
            "TestText": {
                dataValueType: Terrasoft.DataValueType.TEXT,
                type: Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN
            }
        },
        messages: {
            "DataFromModal": {
                mode: Terrasoft.MessageMode.PTP,
                direction: Terrasoft.MessageDirectionType.PUBLISH
            }
        },
        methods: {
            init: function(callback, scope) {
                this.callParent(arguments);
            },
            onRender: function() {
            },
            onCloseButtonClick: function() {
                this.sandbox.publish("DataFromModal", { test: this.get("TestText") }, [this.sandbox.id]);
                ModalBox.close();
            }
        },
        diff: [
            {
                "operation": "insert",
                "name": "MyContainer",
                "propertyName": "items",
                "values": {
                    "itemType": Terrasoft.ViewItemType.CONTAINER,
                    "items": []
                }
            },
            {
                "operation": "insert",
                "parentName": "MyContainer",
                "propertyName": "items",
                "name": "MyGridContainer",
                "values": {
                    "itemType": Terrasoft.ViewItemType.GRID_LAYOUT,
                    "items": []
                }
            },
            {
                "operation": "insert",
                "parentName": "MyGridContainer",
                "propertyName": "items",
                "name": "TestText",
                "values": {
                    "bindTo": "TestText",
                    "caption": "Test text",
                    "layout": {"column": 0, "row": 0, "colSpan": 10}
                }
            },
            {
                "operation": "insert",
                "parentName": "MyGridContainer",
                "name": "CloseButton",
                "propertyName": "items",
                "values": {
                    "itemType": Terrasoft.ViewItemType.BUTTON,
                    "style": Terrasoft.controls.ButtonEnums.style.BLUE,
                    "click": {bindTo: "onCloseButtonClick"},
                    "markerValue": "CloseButton",
                    "caption": "OK",
                    "layout": { "column": 0, "row": 1, "colSpan": 3 }
                }
            }
        ]
    };
});

Вызов из карточки:

define("ContactPageV2", ["ContactPageV2Resources", "GeneralDetails", "ModalBox"],
function(resources, GeneralDetails, ModalBox) {
    return {
        entitySchemaName: "Contact",
        messages: {
            "DataFromModal": {
                mode: Terrasoft.MessageMode.PTP,
                direction: Terrasoft.MessageDirectionType.SUBSCRIBE
            }
        },
        details: /**SCHEMA_DETAILS*/{
        }/**SCHEMA_DETAILS*/,
        methods: {
            subscribeSandboxEvents: function() {
                this.callParent(arguments);
                this.sandbox.subscribe("DataFromModal", function(arg) {
                    console.log("msg from modal: " + arg.test);
                }, this, [this.sandbox.id + "_" + "UsrMyModalModule"]);
            },
            loadMyModal: function() {
                var sandbox = this.sandbox;
                var config = {
                    heightPixels: 420,
                    widthPixels: 750
                };
                var moduleName = "UsrMyModalModule";
                var moduleId = sandbox.id + "_" + moduleName;
                var renderTo = ModalBox.show(config, function() {
                    sandbox.unloadModule(moduleId, renderTo);
                });
                sandbox.loadModule(moduleName, {
                    id: moduleId,
                    renderTo: renderTo
                });
            },
            onMyClick: function() {
                this.loadMyModal();
            },
            onEntityInitialized: function() {
                this.callParent(arguments);
            }
        },
        diff: /**SCHEMA_DIFF*/[
            {
                "operation": "insert",
                "parentName": "CombinedModeActionButtonsCardContainer",
                "propertyName": "items",
                "name": "MainContactButton",
                "values": {
                    "itemType": Terrasoft.ViewItemType.BUTTON,
                    "caption": "пыщь-пыщь",
                    "click": {"bindTo": "onMyClick"}
                }
            }
        ]/**SCHEMA_DIFF*/
    };
});

В примере, страница модального окна это «Схема модели представления карточки», без указания родительской схемы.
Модуль модального окна это «Модуль», с одной единственной зависимостью на вышесозданную страницу.

"Максим Шевченко" написал:
Спасибо Максим

Максим а как вывести реестр в модальное окно? пробовал указывать родительский объект и схему ничего не вышло

в событие "DataFromModal" - передайте ваш this целиком, в таком случае в последствии получив его сможете получить доступ и к его модели и к "GridData"

"Севостьянов Илья Сергеевич" написал:

в событие "DataFromModal" - передайте ваш this целиком, в таком случае в последствии получив его сможете получить доступ и к его модели и к "GridData"


Илья Вы немного не правильно поняли, я хочу в модальном окне отобразить реестр без возможности редактирования, сделал через esq, а результат пытаюсь записать в gridata но возникает ошибка "message: Cannot read property 'each' of null "
код js

define("UsrMyModalPage", ["ModalBox"], function (ModalBox) {
    return {
        attributes: {
            "GridDataTest": { dataValueType: Terrasoft.DataValueType.COLLECTION },
        },
        messages: {
            "DataFromModal": {
                mode: Terrasoft.MessageMode.PTP,
                direction: Terrasoft.MessageDirectionType.PUBLISH
            }
        },
        methods: {
            init: function (callback, scope) {
                this.callParent(arguments);
 
                var esq = this.Ext.create("Terrasoft.EntitySchemaQuery", {
                    rootSchemaName: "UsrPLP"
                });
                esq.addColumn("Name");
                esq.addColumn("UsrPoints");
 
                esq.getEntityCollection(function (result) {
                    if (!result.success) {
                        this.showInformationDialog("Ошибка запроса данных");
                        return;
                    }
                    this.set("GridDataTest", result.collection);
                }, this);
            },
            onCloseButtonClick: function () {
                ModalBox.close();
            }
        },
        diff: [
            {
                "operation": "insert",
                "name": "MyContainer",
                "propertyName": "items",
                "values": {
                    "itemType": Terrasoft.ViewItemType.CONTAINER,
                    "items": []
                }
            },
            {
                "operation": "insert",
                "parentName": "MyContainer",
                "propertyName": "items",
                "name": "MyGridContainer",
                "values": {
                    "itemType": Terrasoft.ViewItemType.GRID_LAYOUT,
                    "items": []
                }
            },
             {
                 "operation": "insert",
                 "name": "DataGrid",
                 "parentName": "MyContainer",
                 "propertyName": "items",
                 "values": {
                     "itemType": Terrasoft.ViewItemType.GRID,
                     "listedZebra": true,
                     "collection": { "bindTo": "GridDataTest" },
                 }
 
             },
            {
                "operation": "insert",
                "parentName": "MyGridContainer",
                "name": "CloseButton",
                "propertyName": "items",
                "values": {
                    "itemType": Terrasoft.ViewItemType.BUTTON,
                    "style": Terrasoft.controls.ButtonEnums.style.BLUE,
                    "click": { bindTo: "onCloseButtonClick" },
                    "markerValue": "CloseButton",
                    "caption": "Close",
                    "layout": { "column": 0, "row": 1, "colSpan": 3 }
                }
            }
        ]
    };
});

"Головачев Дмитрий Александрович" написал:Cannot read property 'each' of null "

Вероятно не хватает миксина или какого-то метода, посмотрите в сторону: BaseLookupPageV2
которая тоже является модальным окном и не наследуется ни от кого, весь её код для работы грида прописан в ней же.

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

Коллеги, добрый день!
Ситуация следующая, для реализации доработки, связанной с загрузкой файлов на деталь (FileDetailV2)
нужно было обновить библиотеку FileApi до более новой версии. Соответсвенно для этого я подменил файлы FileApi.js и FileApi.min.js в папке ..\ui\FileApi
Но, после изменения значения ключа "SeparatedJsFiles" из внутреннего web.config на false, приложение будет подгружать файл all-combined.js, в котором собрана старая версия FileApi и соотв. новый функционал работать не будет.
Вопрос, как можно пересобрать all-combined включая новые версии файлов, или может быть есть более правильный путь решения в такой ситуации?
Спасибо!

Нравится

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

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

Пересобрать файл all-combined.js нет возможности, т.к. он собирается в момент создания сборки и живет все время без изменений. В этом файле находятся ядровый функционал.

Можете вырезать и вставить новый функционал в all-combined.js, но при обновлении сайта на новую версию, также обновится и файл all-combined.js, затерев Ваши изменения.

Правильнее было бы подключить новую версию в Ext.define.

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

Коллеги, добрый день!

У нас в системе реализовано кастомное модальное окно, на котором расположен ряд фильтров. Подскажите, пожалуйста, как реализовать поле типом "Выбор из справочника" в модальном окне. Именно не список, а справочник.

Спасибо!

Нравится

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

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

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

Скриншот расположения окна - https://db.tt/gOBNhNzPCI.

Выбор из справочника необходим, например, для таких полей, как ОКВЭД.

Добрый день, Сергей.

Отображение модального окна в модальном окне является извечной проблемой не только в рамках bpb'online. Рекомендую Вам смотреть в сторону использования выпадающих списков и свойства prepareList для наполнения их в рантайме.

Коллеги, спасибо!

У кого-нибудь есть примеры реализации выпадающих список в модальных окнах с использованием этого свойства?

Вот пример для OrderPageV2. Для модального окна отличий быть не должно.

define("OrderPageV2", [], function() {
	return {
		entitySchemaName: "Order",
		details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
		diff: /**SCHEMA_DIFF*/[
	{
		"operation": "insert",
		"name": "myEnum",
		"values": {
			"caption": "myEnum",
			"layout": {
				"colSpan": 12,
				"rowSpan": 1,
				"column": 0,
				"row": 2,
				"layoutName": "Header"
			},
			"controlConfig": {
				"className": "Terrasoft.ComboBoxEdit",
				"list": {
					"bindTo": "myList"
				},
				"change": {
					"bindTo": "onMyValueChange"
				},
				"prepareList": {
					"bindTo": "prepareMyList"
				}
			},
			"labelConfig": {},
			"enabled": true,
			"bindTo": "myEnum"
		},
		"parentName": "Header",
		"propertyName": "items",
		"index": 4
	}]/**SCHEMA_DIFF*/,
		methods: {
			onPageInitialized: function(callback, scope) {
				if (!this.get("myList")) {
					this.set("myList", this.Ext.create("Terrasoft.Collection"));
				}
				if (callback) {
					callback.call(scope || this);
				}
			},
			prepareMyList: function(filter, list) {
				if (list === null) {
					return;
				}
				list.clear();
				var columns = {};
				var value1 = {
					displayValue: "a123",
					value: "1"
				};
				var value2 = {
					displayValue: "b234",
					value: "2"
				};
				var value3 = {
					displayValue: "c345",
					value: "3"
				};
				columns[1] = value1;
				columns[2] = value2;
				columns[3] = value3;
				list.loadAll(columns);
			},
			 onMyValueChange: function(val) {
				if (val && val.displayValue) {
					console.log("you pick: ", val.displayValue);
				}
			}
		},
		attributes: {
			"myEnum": {
				"dataValueType": Terrasoft.DataValueType.ENUM,
				"type": Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
				"caption": "myEnum"
			},
			"myList": {
				"dataValueType": Terrasoft.DataValueType.ENUM,
				"type": Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
				"isCollection": true
			}
		},
		rules: {}
	};
});

Не знаю что у вас там не работает... Написал свой контрол (да, немного кривой:smile:), все сохраняется.
1
2
3
4

Можете поделиться примером кода?)

Сергей, Выше уже есть наглядный пример кода OrderPageV2. У Вас что-то не получается?

Получилось. Всем большое спасибо!

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

Проблема с созданием такого правила.
За основу взял пример из Академии: https://academy.terrasoft.ru/documents/technic-sdk/7-9/dobavlenie-pravil....
Валятся ошибки response status: 400 (Bad Request) (смотрите прикрепленный файл).
Прошу ввести в тему как это действие реализовать, если кто знает.

-- Проверка наличия хранимой процедуры с именем tsp_FindContactDuplicateByInn.
IF NOT OBJECT_ID('[dbo].[tsp_FindAccountDuplicateByMyString]') IS NULL
BEGIN
    -- Удаление хранимой процедуры.
    DROP PROCEDURE [dbo].[tsp_FindAccountDuplicateByMyString];
END;
GO
-- Создание хранимой процедуры.
CREATE PROCEDURE [dbo].[tsp_FindAccountDuplicateByMyString] (
    -- Этот табличный параметр передается только в случае сохранения нового контакта.
    -- Содержит данные нового контакта.
    -- В случае запуска процесса глобального поиска дублей переданный параметр не содержит данных.
    @parsedConfig CreatingObjectInfo READONLY,
    -- Уникальный идентификатор пользователя, который запустил поиск дублей.
    @sysAdminUnit UNIQUEIDENTIFIER,
    -- Идентификатор текущего правила из таблицы [ContactDuplicateSearchResult].
    -- Этот идентификатор создается после регистрации правила в системе.
    @ruleId UNIQUEIDENTIFIER
)
AS
BEGIN
    -- Получение количества записей из принимаемой таблицы для определения запуска глобального поиска дублей.
    DECLARE @parsedConfigRowsCount INT = (SELECT COUNT(*) FROM @parsedConfig);
    -- Создание временной таблицы с данными контактов для поиска.
    CREATE TABLE #searchAccount (
        [MyString] INT,
        [SortDate] DATETIME
    );
    -- В случае глобального поиска выполняется заполнение временной таблицы данными.
    IF @parsedConfigRowsCount = 0
    BEGIN
        -- Добавление во временную таблицу данных для поиска дублей.
        INSERT INTO #searchAccount ([MyString], [SortDate])
        -- Запрос на выборку данных контактов.
        SELECT
            -- Выбираются колонки ИНН даты модификации контакта.
            [MyString],
            MAX([ModifiedOn])
        FROM [Account]
        -- Добавляется группировка по полям для возможности использовать проверку на количество.
        GROUP BY [MyString]
        -- Таблица заполняется только в случае наличия более одного контакта.
        HAVING COUNT(*) > 1;
    END;
   
    -- Заполнение таблицы результатов.
    INSERT INTO [AccountDuplicateSearchResult] ([AccountId], [GroupId], [RuleId], [SysAdminUnitId])
    SELECT
        -- Идентификатор дубля контакта.
        [vr].[Id],
        -- Формирование номера группы.
        DENSE_RANK() OVER (ORDER BY [vr].[SortDate] DESC, [vr].[MyString]),
        -- Идентификатор правила.
        @ruleId RuleId,
        -- Идентификатор пользователя, под которым запущен процесс поиска дублей.
        @sysAdminUnit
    FROM (
        -- Подзапрос, из которого заполняется таблица дублей.
        SELECT
            -- Идентификатор контакта.
            [v].[Id],
            --ИНН контакта.
            [v].[MyString],
            -- Дата сортировки.
            [r].[SortDate]
        -- Таблицы, из которых берутся данные.
        FROM [Account] [v], #searchAccount r
        -- Правило, по которому определяется, что контакты — дубли.
        WHERE [v].[MyString] = [r].[MyString]
        -- Группировка результата поиска.
        GROUP BY [v].[MyString], [r].[SortDate], [v].[Id]
    ) [vr];
END;
GO

Нравится

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

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

Поля AlternativeName не существует во вьюхе VwAccountCleanDataValues. Там есть только Id, ModifiedOn и Name, которые берутся из Account.
Вы можете брать поле AlternativeName сразу из Account.

"Demchenko Olha" написал:

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

Поля AlternativeName не существует во вьюхе VwAccountCleanDataValues. Там есть только Id, ModifiedOn и Name, которые берутся из Account.

Вы можете брать поле AlternativeName сразу из Account.


Я поменял описание. Теперь совсем другая проблема.

Уточните какая возникла проблема.

Проблема в том, что теперь поиск дублей в контрагент не работает.

Вы можете посмотреть какая возникает ошибка в таблице DeduplicateExecLog. Еще можно проверить в журнале процессов запускается ли процесс "Процесс дедепликации", есть ли в нём ошибки.

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

Добрый день, коллеги.

В системе можно подключить почтовый ящик и на коммуникационной панели в "конвертике" отображаются все входящие\исходящие письма этого ящика.
Подскажите, а нет ли раздела, где отображаются все эти письма? Либо же может есть возможно вынести все письма в какой-либо раздел?

Нравится

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

"Гольфельд Елена Андреевна" написал:где отображаются все эти письма?

По-сути коммуникационная панель и есть раздел для писем. Все письма хранятся как активности с типом "email". Так что можно в теории можно:
а) убрать/подредактировать фильтр в активностях, чтобы выводились письма
б) создать доп раздел, забиндить его на "Activity", установить фильтры: активности с типом email и для, допустим, текущего контакта

"Варфоломеев Данила" написал:По-сути коммуникационная панель и есть раздел для писем.

Согласна с вами, но хотелось бы иметь именно раздел в панели слева.

"Варфоломеев Данила" написал:а) убрать/подредактировать фильтр в активностях, чтобы выводились письма

Пробовала делать фильтр в активностях, в котором указывала Тип = Email, система ничего не находит по данному фильтру. Хотя письма в системе есть.

"Варфоломеев Данила" написал:б) создать доп раздел, забиндить его на "Activity", установить фильтры: активности с типом email и для, допустим, текущего контакта

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

"Варфоломеев Данила" написал:забиндить его на "Activity"

Не подскажите, как это сделать?

"Гольфельд Елена Андреевна" написал:Пробовала делать фильтр в активностях, в котором указывала Тип = Email

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

getFilters: function() {
	//гора кода
	filters.add("NotEmailFilter", Terrasoft.createColumnFilterWithParameter(
		Terrasoft.ComparisonType.NOT_EQUAL, 
		"Type", 
		ConfigurationConstants.Activity.Type.Email));
	//...еще хуже
},

"Гольфельд Елена Андреевна" написал:как-то стандартными средствами.

Сомневаюсь, что можно как-то без программирования реализовать. Сейчас попробую, посмотрим что получится...

Ну вот как-то так. На скорую руку, получилось на удивление быстро. Однако всё равно требуется полазить по конфигурации, написать совсем немного кода)
scr

"Варфоломеев Данила" написал:Ну вот как-то так. На скорую руку, получилось на удивление быстро. Однако всё равно требуется полазить по конфигурации, написать совсем немного кода)

Вы молодец! Это новый раздел? Не поделитесь как вы реализовали данный функционал?

"Гольфельд Елена Андреевна" написал:Не поделитесь как вы реализовали данный функционал?

1) Создать через мастер разделов новый раздел (заполняете заголовок, код, рабочее место, сохраняете). Вкладку "страница" трогать не нужно
2) Зайти в конфигурацию, найти 2 только что созданных схемы. У меня раздел назывался Emails, соответственно и названия у схем похожие
pic
3) Поменять код схемы раздела на

define("TmEmails1Section" /*вместо TmEmails1Section название схемы раздела*/, ["ConfigurationConstants"], function(ConfigurationConstants) {
	return {
		entitySchemaName: "Activity",
		details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
		diff: /**SCHEMA_DIFF*/[]/**SCHEMA_DIFF*/,
		methods: {
			getFilters: function() {
				var filters = this.callParent(arguments);
				filters.add("NotEmailFilter", this.Terrasoft.createColumnFilterWithParameter(
						this.Terrasoft.ComparisonType.EQUAL, "Type", ConfigurationConstants.Activity.Type.Email
					));
				return filters;
			}
		}
	};
});

4) Поменять код схемы страницы на

define("TmEmails1Page" /*вместо TmEmails1Page название схемы страницы*/, [], function() {
	return {
		entitySchemaName: "Activity",
		details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
		diff: /**SCHEMA_DIFF*/[]/**SCHEMA_DIFF*/,
		methods: {},
		rules: {}
	};
});

Важный момент: справа внизу в свойствах надо указать родительский объект "Страница редактирования активности ( UIv2 )"
5) все. почистить кеш, перезайти, появится развел в указанном ранее рабочем месте. Осталось только настроить колонки

Вроде получилось быстро. Но при этом находясь в новом разделе, все равно выделение слева происходит на раздел Activity.
И фильтры у разделов получаются общие.

"Владимир Соколов" написал:Вроде получилось быстро. Но при этом находясь в новом разделе, все равно выделение слева происходит на раздел Activity.

Ну можно создать представление VwActivity и на основании представления сделать уже раздел. Если в разделе нужно создавать/редактировать/удалять записи - повесьте на представление триггеры.

"Владимир Соколов" написал:И фильтры у разделов получаются общие.

Вполне логично - группы объекта Activity хранятся в объекте ActivityFolder.

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

Добрый день, стоит задача убрть поле “Название контрагента” из мини-карточки лида во время добавления
!
Создали замещающую схему:

define("LeadMiniPage", ["MiniPageResourceUtilities", "EmailHelper", "BaseProgressBarModule",
        "css!BaseProgressBarModule", "css!LeadMiniPageCSS"
    ],
    function(miniPageResources, EmailHelper) {
        return {
            entitySchemaName: "Lead",
            details: /**SCHEMA_DETAILS*/ {} /**SCHEMA_DETAILS*/ ,
            attributes: {

            },
            methods: {},
            diff: /**SCHEMA_DIFF*/ [{
                    "operation": "insert",
                    "name": "Account",
                    "parentName": "MiniPage",
                    "propertyName": "items",
                    "values": {
                        "layout": {
                            "column": 0,
                            "row": 4,
                            "colSpan": 24
                        },
                        "isMiniPageModelItem": true,
                        "visible": false
                    }
                },

            ] /**SCHEMA_DIFF*/
        };
    }
);

но не срабатывает, также переопределяли метод getContactAccountVisibility, но тогда пропадают также и ФИО контакта.
Пробовали также такой вариант:
methods: {
        getContactAccountVisibility: function(columnNames) {
            return false;
        },
        getContactVisibility: function(columnNames) {
            if (this.get("IsFromSection") || this.get("IsFromQuickAddMenu")) {
                return true;
            }
            return !this.get("IsQualifiedLookupVisible") && this.isViewMode(columnNames);
        },
    },
    diff: /**SCHEMA_DIFF*/ [{
            "operation": "insert",
            "name": "Account",
            "parentName": "MiniPage",
            "propertyName": "items",
            "values": {
                "layout": {
                    "column": 0,
                    "row": 4,
                    "colSpan": 24
                },
                "isMiniPageModelItem": true,
                "visible": {
                    "bindTo": "getContactAccountVisibility"
                }
            }
        },
        {
            "operation": "insert",
            "name": "Contact",
            "parentName": "MiniPage",
            "propertyName": "items",
            "values": {
                "layout": {
                    "column": 0,
                    "row": 5,
                    "colSpan": 24
                },
                "isMiniPageModelItem": true,
                "visible": {
                    "bindTo": "getContactVisibility"
                }
            }
        },
    ] /**SCHEMA_DIFF*/

Но ничего не срабатывает, подскажите пожалуйста, как правильно реализовать сокрытие поля.

Нравится

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

вариант 1:

diff: /**SCHEMA_DIFF*/ [
{
     "operation": "remove",
     "name": "Account"
}
] /**SCHEMA_DIFF*/

В этом случе вы удаляете элемент (ну и он скрывается соответственно)

вариант 2:

diff: /**SCHEMA_DIFF*/ [
{
    "operation": "merge",
     "name": "Account",
     "values": {
            "visible": false
      }
}
] /**SCHEMA_DIFF*/

Тут вы его просто скрываете

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

При помощи

this.getHistoryStateInfo();

Возможно получить объект который описывает в каком "режиме отображения" (Combined/Combined+Grid/Separated) и "операционном режиме" (add/edit) открыта текущая карточка.
Но есть одно обстоятельство которое заставляет задуматься:
свойство "operation" вышеописанного объекта содержит немного непредсказуемые значения:
//document.CasePageScope = this (схемы CasePage)

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

Такое же поведение свойственно и при открытии карточки при помощи openCardInChain

Вопрос: Можно сделать допущение что если

this.getHistoryStateInfo().operation === "" || this.getHistoryStateInfo().operation === "add"

Это однозначно "Добавление новой записи" ?
Или может случиться и так что this.getHistoryStateInfo().operation будет содержать пустую строку ("") и в режиме редактирования, и в каком ни будь еще режиме (если они есть) ?

Нравится

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

"Севостьянов Илья Сергеевич" написал:Или может случиться и так что this.getHistoryStateInfo().operation будет содержать пустую строку

Скорее всего будет при режиме копирования записи. Обычно в строке ничего нет, если открывается запись, которой ещё нет в бд. А зачем так всё усложнять? Можно же взять

this.isAddMode()/this.isCopyMode()/this.isEditMode()

Спасибо, я про эти методы не знал.
https://academy.terrasoft.ru/jscoresdk/#!/api
В SDK о них ни слова, впрочем как обычно.

"Севостьянов Илья Сергеевич" написал:
https://academy.terrasoft.ru/jscoresdk/#!/api

В SDK о них ни слова, впрочем как обычно.

Здравствуйте.
Там о них и не может ничего быть. :)
По ссылке выше опубликована справка по API ядра.
Методы

this.isAddMode()/this.isCopyMode()/this.isEditMode()

объявлены в схеме BasePageV2, которая размещена в пакете NUI, который относится к конфигурации, а не ядру.
К сожалению, на текущий момент справка по API конфигурации не опубликована из-за определенных технических проблем. Однако, она планируется к публикации в ближайшее время.

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