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

У нас 1с через Odata передает данные о заказе, включая поле Дата (Date)

На сервере часовой пояс киевский, у супервизора тоже киевский, в bpm в системной настройке киевский.

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

Знаю, что время в bpm хранится в UTC и когда из 1с приходит дата она записывается в это поле и пользователь видет + 3 часа.

Например создал заказ в бпм. Дата 9 утра. (если sql запрос сделать в базу) там 6 утра. Все ок, пользователь видит 9. Ушло в 1с, там заказ провели и возвращают в бпм. Уходит из 1с тоже 9 утра. Пришел в бпм, смотрим запросом в базу, там стало 9 утра, а пользователь видит 12 часов уже, т.е + 3 часа.

Как правильно передать запрос. Пробовали так:

{

    "AccountId": "590eb789-2b6d-4257-838f-917003ffce43",

    "CHOurCompanyId": "3d5d64dd-450f-4d70-a722-ee95caa2a5b3",

    "StatusId": "40de86ee-274d-4098-9b92-9ebdcf83d4fc",

    "CHVATTop": "false",

    "Date": "2019-06-04T12:05:12+TZ",

    "Number": "УТХ00013754",

    "Amount": "391",

    "OpId1C": "41d319dd-86a4-11e9-8102-e36315b16de3"

выдает ошибку - Cannot convert a primitive value to the expected type 'Edm.DateTime'. See the inner exception for more details.



Подскажите, как правильно сделать, может код на поле навешать в бпм

Нравится

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

«+TZ» — это не прямо так нужно писать, а указать нужный пояс. Например,«2018-01-31T08:24:49+03:00». Подробнее по работе с датой см. в этой теме.

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

Википедия гласит:

Следует помнить, что время по UTC не переводится ни зимой, ни летом. Поэтому для тех мест, где есть переход на летнее время, меняется смещение относительно UTC.

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

т.е в запрос при переходе на зимнее надо менять с +03:00 на +02:00?

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

Можно на стороне 1С перед передачей даты вычислять текущее значение смещения.

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

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

Нравится

2 комментария
Лучший ответ

Думаю что вам может помочь это бесплатное приложение.

Думаю что вам может помочь это бесплатное приложение.

Григорий Чех, спасибо Вам большое.

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

Добрый субботний вечер!))

Есть у нас пакет, который сделан на Enterprise. Хотим его поставить на commerce.

В зависимости пакета  убираем SalesEnterprise пакет.

Добавляем зависимость от базовых пакетов Base, NUI, UIv2.

Но при удалении SalesEnterprise ошибка...  скрины

Что делаем ни так? 

Заранее спасибо!

Нравится

6 комментариев
Лучший ответ

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

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

delete from SysPackageDependency 

where SysPackageId = (select Id from SysPackage where Name = 'qrtHMS')

    and DependOnPackageId = (select Id from SysPackage where Name = 'SalesEnterpriseSoftkey_ENU')

А потом зайти в конфигурацию и перекомпилировать все схемы.

Также на существующем сайте (там, где Вы пытаетесь через интерфейс убрать связь с пакетом) попробуйте выполнить это действие ещё раз, а потом после свала посмотреть логи приложения bpm'online.

Ошибка возникает именно при удалении?

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

Алла Савельева,

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

 

Алла Савельева,

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

Как можно узнать есть ли эти ссылки на пакет SalesEnterprise и если есть, то на какие объекты?

 

Елена К,

Определить схемы, в которых есть зависимость можно, выполнив такой запрос:

select SS.*
from SysSchema SS
   join SysSchema Parent on Parent.Id = SS.ParentId
where SS.SysPackageId = (select Id from SysPackage where Name = '<название Вашего пакета>')
    and Parent.SysPackageId = (select Id from SysPackage where Name = '<название пакета, на который могут ссылаться схемы>')

 

Алла Савельева,

Алла, запрос 

select SS.*

from SysSchema SS

   join SysSchema Parent on Parent.Id = SS.ParentId

where SS.SysPackageId = (select Id from SysPackage where Name = 'qrtHMS')

    and Parent.SysPackageId = (select Id from SysPackage where Name = 'SalesEnterpriseSoftkey_ENU')

Запрос вернул 0 записей. Т.е. в нашем пакете нет ни одной схемы которая ссылается на SalesEnterpriseSoftkey_ENU.

Что думаете еще может быть?)

 

 

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

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

delete from SysPackageDependency 

where SysPackageId = (select Id from SysPackage where Name = 'qrtHMS')

    and DependOnPackageId = (select Id from SysPackage where Name = 'SalesEnterpriseSoftkey_ENU')

А потом зайти в конфигурацию и перекомпилировать все схемы.

Также на существующем сайте (там, где Вы пытаетесь через интерфейс убрать связь с пакетом) попробуйте выполнить это действие ещё раз, а потом после свала посмотреть логи приложения bpm'online.

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

Здравствуйте, уважаемое сообщество!

В базе имеется много Контрагентов внесённых вручную, сделали интеграцию Контрагентов из 1С при помощи 1С Коннектора, естественно появились дубли

Но заметил, что при объединении дублей остаётся идентификатор старого объекта, а не нового который я выбираю... всё бы ничего но мне нужен новый идентификатор, который был присвоен после интеграции так как по нему идёт связь с Коннектором в таблице SmrSyncHistory для дальнешей синхронизации

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

Проверяю следующим запросом к базе:

select * from Account where name = 'Высший Вкус ООО (ВВ)';
select * from SmrSyncHistory where localid in (select id from Account where name = 'Высший Вкус ООО (ВВ)');

 

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

До объединения:

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

 

После объединения:

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

 

Нравится

5 комментариев
Лучший ответ

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

Пока в стандартном механизме платформы нет выбора золотой записи.

В случае использования 1C Connector вы можете сразу настроить признак [Использовать для дедупликации] по полю Название, чтобы дубли вообще не создавались. Подробнее -https://samarasoft.com/docs/1c-connector/integration-setting-bpmonline/fields-mapping/

В стандартном механизме в качестве золотой берётся первое значение в коллекции. В схеме DeduplicationMergeHandler функция MergeEntityDublicates начинается так:

public void MergeEntityDublicates(string schemaName, int groupId, List<Guid> duplicateRecordIds, Dictionary<string, string> resolvedConflicts) {
	EntitySchema entitySchema = _userConnection.EntitySchemaManager.GetInstanceByName(schemaName);
	EntityCollection duplicates = GetEntityDublicates(schemaName, duplicateRecordIds);
	Entity goldenEntity = duplicates.FirstOrDefault();
	if (goldenEntity == null) {
		return;
	}
	duplicates.RemoveFirst();
	duplicateRecordIds.Remove(goldenEntity.PrimaryColumnValue);
	if (duplicates.Count == 0) {
		return;
	}

А коллекция отсортирована по дате создания, старые вначале:

public EntityCollection GetEntityDublicates(string schemaName, List<Guid> ids, List<string> columns = null) {
	EntitySchema schema = _userConnection.EntitySchemaManager
		.GetInstanceByName(schemaName);
	var esq = new EntitySchemaQuery(schema);
	if (columns == null) {
		esq.AddAllSchemaColumns();
	} else {
		esq.PrimaryQueryColumn.IsAlwaysSelect = true;
		if (!columns.Contains("CreatedOn")) {
			esq.AddColumn("CreatedOn");
		}
		foreach (string columnName in columns) {
			esq.AddColumn(columnName);
		}
	}
	esq.Filters.Add(esq.CreateFilterWithParameters(FilterComparisonType.Equal,
		esq.RootSchema.PrimaryColumn.Name, ids.Cast<object>()));
	EntityCollection entityCollection = esq.GetEntityCollection(_userConnection);
	entityCollection.Order("CreatedOn", OrderDirection.Ascending);
	return entityCollection;
}

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

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

Спасибо за советы, только сейчас пролучилось вернуться к этому кейсу

Я так понимаю что включать признак дедупликации в Коннекторе уже поздно, ну или чистить записи и проводить интеграцию заново

Хочу попробовать сделать по совету Зверева Александра, но не могу найти статью или ответы на комьюнити как правильно замещать "Исходный код", я так понял надо просто поменять Ascending на Descending.

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

Трефилов Павел Сергеевич,

ОМАЙГАДБЛ... всё гениальное просто, спасибо, попробую ))))))))

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

Создал иерархическую деталь с редактируемым реестром. Но появилась проблема при количестве дочерних элементов больше 8. Они почему не отображаются, выдается ошибка Cannot read property 'getAttribute' of null. В БД всё верно. 

Вот код детали

define("IDSBRefrigeratorInTMADetail",
    ["ConfigurationGrid", "ConfigurationGridGenerator", "ConfigurationGridUtilities"],
    function () {
        return {
            messages: {
                "ReloadRefrigeratorsInTMAGrid": {
                    "mode": Terrasoft.MessageMode.BROADCAST,
                    "direction": Terrasoft.MessageDirectionType.SUBSCRIBE
                }
            },
            entitySchemaName: "IDSBRefrigeratorInTMA",
            attributes: {
                "IsEditable": {
                    dataValueType: Terrasoft.DataValueType.BOOLEAN,
                    type: Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
                    value: true
                }
            },
            mixins: {
                ConfigurationGridUtilities: "Terrasoft.ConfigurationGridUtilities"
            },
            details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
            diff: /**SCHEMA_DIFF*/[
                {
                    "operation": "merge",
                    "name": "DataGrid",
                    "values": {
                        "hierarchical": true,
                        "hierarchicalColumnName": "IDSBParent",
                        "maxColumns": 48,
                        "maxRowsCount": 10000,
                        "className": "Terrasoft.ConfigurationGrid",
                        "generator": "ConfigurationGridGenerator.generatePartial",
                        "generateControlsConfig": { "bindTo": "generateActiveRowControlsConfig" },
                        "changeRow": { "bindTo": "changeRow" },
                        "unSelectRow": { "bindTo": "unSelectRow" },
                        "onGridClick": { "bindTo": "onGridClick" },
                        "activeRowAction": { "bindTo": "onActiveRowAction" },
                        "initActiveRowKeyMap": { "bindTo": "initActiveRowKeyMap" },
                        "multiSelect": false
                    }
                },
                {
                    "operation": "remove",
                    "name": "AddRecordButton"
                }]/**SCHEMA_DIFF*/,
            methods: {
                generateActiveRowControlsConfig: function (id, columnsConfig, rowConfig) {
                    this.columnsConfig = columnsConfig;
                    var gridData = this.getGridData();
                    var activeRow = gridData.get(id);
                    var isEditableColumn;
                    if (activeRow.values.IDSBParent === "") {
                        isEditableColumn = this.isEditableParentColumn;
                    }
                    else {
                        isEditableColumn = this.isEditableColumn;
                    }
                    var gridLayoutItems = [];
                    var currentColumnIndex = 0;
                    Terrasoft.each(columnsConfig, function (columnConfig) {
                        var cellConfig = this.getActiveRowCellConfig(columnConfig, currentColumnIndex);
                        cellConfig.enabled = isEditableColumn(cellConfig.name);
                        if (!cellConfig.hasOwnProperty("isNotFound")) {
                            gridLayoutItems.push(cellConfig);
                        }
                        currentColumnIndex += cellConfig.layout.colSpan;
                    }, this);
                    this.applyBusinessRulesForActiveRow(id, gridLayoutItems);
                    var viewGenerator = Ext.create(this.getRowViewGeneratorClassName());
                    viewGenerator.viewModelClass = this;
                    var gridLayoutConfig = viewGenerator.generateGridLayout({
                        name: this.name,
                        items: gridLayoutItems
                    });
                    rowConfig.push(gridLayoutConfig);
                },
                isEditableParentColumn: function (columnName) {
                    return false;
                },
                isEditableColumn: function (columnName) {
                    return (columnName === "IDSBBottlePlan");
                }/*,
                init: function () {
                    this.callParent(arguments);
                    this.sandbox.subscribe("ReloadRefrigeratorsInTMAGrid", this.onReloadRefrigeratorsInTMAGrid, this);
                },
                onReloadRefrigeratorsInTMAGrid: function (args) {
                    this.reloadGridData();
                }*/
            }
	};
});

 

Нравится

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

Для упрощения отладки посмотрите SQL профайлером запросы которые отправляются в БД.

Григорий Чех, думаете нужно заместить метод addGridDataColumns?

Григорий имел в виду использование профайлера. Естественно, только для случаев, когда есть доступ к серверу БД.

посмотрел профайлер. Выполняется следующий запрос. Забил его сам в SQL Management. Выдал недостающие элементы, которые как раз невыведены на экран. Ошибка возникает когда нажимаю "Показать больше"

SELECT
	[IDSBRefrigeratorInTMA].[Id] [Id],
	[IDSBRefrigeratorInTMA].[IDSBStreet] [IDSBStreet],
	[IDSBRefrigeratorInTMA].[IDSBCustomerInTMAId] [IDSBCustomerInTMAId],
	[IDSBRefrigeratorInTMA].[ITTradeMarketId] [ITTradeMarketId],
	[ITTradeMarket].[ITName] [ITTradeMarket.ITName],
	[IDSBRefrigeratorInTMA].[MonthId] [MonthId],
	[Month].[Name] [Month.Name],
	[IDSBRefrigeratorInTMA].[IDSBBottlePlan] [IDSBBottlePlan],
	[IDSBRefrigeratorInTMA].[IDSBParentId] [IDSBParentId],
	[IDSBParent].[IDSBStreet] [IDSBParent.IDSBStreet],
	[ITTradeMarket].[ITTypeId] [ITTradeMarket.ITTypeId],
	[ITType].[Name] [ITType.Name],
	(
SELECT
	COUNT([SubEntryPoint].[Id]) [Count]
FROM
	[dbo].[EntryPoint] [SubEntryPoint] WITH(NOLOCK)
WHERE
	[SubEntryPoint].[EntityId] = [IDSBRefrigeratorInTMA].[Id]
	AND [SubEntryPoint].[IsActive] = 1) [SubEntryPoint],
	[IDSBRefrigeratorInTMA].[CreatedOn] [CreatedOn],
	[IDSBRefrigeratorInTMA].[CreatedById] [CreatedById],
	[CreatedBy].[Name] [CreatedBy.Name],
	[CreatedBy].[PhotoId] [CreatedBy.PhotoId],
	[IDSBRefrigeratorInTMA].[ModifiedOn] [ModifiedOn],
	[IDSBRefrigeratorInTMA].[ModifiedById] [ModifiedById],
	[ModifiedBy].[Name] [ModifiedBy.Name],
	[ModifiedBy].[PhotoId] [ModifiedBy.PhotoId],
	[IDSBRefrigeratorInTMA].[ProcessListeners] [ProcessListeners]
FROM
	[dbo].[IDSBRefrigeratorInTMA] [IDSBRefrigeratorInTMA] WITH(NOLOCK)
	LEFT OUTER JOIN [dbo].[ITTradeMarket] [ITTradeMarket] WITH(NOLOCK) ON ([ITTradeMarket].[Id] = [IDSBRefrigeratorInTMA].[ITTradeMarketId])
	LEFT OUTER JOIN [dbo].[Month] [Month] WITH(NOLOCK) ON ([Month].[Id] = [IDSBRefrigeratorInTMA].[MonthId])
	LEFT OUTER JOIN [dbo].[IDSBRefrigeratorInTMA] [IDSBParent] WITH(NOLOCK) ON ([IDSBParent].[Id] = [IDSBRefrigeratorInTMA].[IDSBParentId])
	LEFT OUTER JOIN [dbo].[ITITTradeMarketType1] [ITType] WITH(NOLOCK) ON ([ITType].[Id] = [ITTradeMarket].[ITTypeId])
	LEFT OUTER JOIN [dbo].[Contact] [CreatedBy] WITH(NOLOCK) ON ([CreatedBy].[Id] = [IDSBRefrigeratorInTMA].[CreatedById])
	LEFT OUTER JOIN [dbo].[Contact] [ModifiedBy] WITH(NOLOCK) ON ([ModifiedBy].[Id] = [IDSBRefrigeratorInTMA].[ModifiedById])
WHERE
	[IDSBRefrigeratorInTMA].[ITTradeMarketId] = '54368FDE-6D00-4BDE-BAAE-EDEA56EBAA33'
ORDER BY
	[Id] ASC OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY

 

Может, 8 элементов видно как раз из-за выборки порциями по 10? Судя по окончанию SQL-запроса, это как раз вторая десятка, первая пропущена.

А где именно вылетает «Cannot read property 'getAttribute' of null», полный стек не видно?

Вылетает на этом методе. В строке var n = this.getDomRow(i) в n кладется undefined и далее соответственно вылетает ошибка. В i в этот момент родительская колонка

onCollectionDataLoaded: function(e, t, a) {
        if (this.theoreticallyActiveRows = null,
        !this.rows.length)
            return this.collection = this.collection || e,
            this.prepareCollectionData(),
            void this.safeRerender();
        if (!Ext.Object.isEmpty(t) && this.rendered) {
            var r = []
              , s = {
                rows: r
            };
            if (t.each(function(e) {
                this.prepareCollectionItem(e);
                var t = this.getRow(e);
                r.push(t),
                a && ("top" !== a.mode ? this.rows.push(t) : this.rows.splice(0, 0, t))
            }, this),
            this.hierarchical && !t.isEmpty()) {
                var i = t.getByIndex(0).get(this.hierarchicalColumnName);
                if (s[this.hierarchicalColumnName] = i,
                "listed" === this.type && i) {
                    var n = this.getDomRow(i)
                      , o = parseInt(n.getAttribute("level"), 10);
                    s.rowLevel = o + 1
                }
            }
            var l = [];
            this.renderGrid(l, s);
            for (var c = "", h = 0, u = l.length; h < u; h += 1)
                c += Ext.DomHelper.createHtml(l[h]);
            Ext.Object.isEmpty(a) && (a = {
                mode: "bottom"
            }),
            this.addRows(c, a),
            this.checkNeedLoadData()
        }
    },

 

Что-то не могу найти такой функции в «коробке».

А иерархичность и редактируемость сами по себе совместимы? На других таких деталях ограничения в 8 нет?

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

Это логично, если сбой при превышении 8 потомков. В плоской детали никаких потомков нет. Сравните с другими иерархическими деталями, есть там такое ограничение или нет?

Решил проблему. Добавил значения атрибутов, чтобы всё грузилось сразу. В моем случае такое решение вполне подходит

init: function () {
                    this.callParent(arguments);
                    this.set("IsPageable", false);
                    this.set("RowCount", 28000);
                    this.sandbox.subscribe("ReloadRefrigeratorsInTMAGrid", this.onReloadRefrigeratorsInTMAGrid, this);
                },

 

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

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

Пытаюсь обновить запись из внешнего приложения через сабж (0/dataservice/json/reply/UpdateQuery).

Формирую JSON

{
  "rootSchemaName": "UsrPrintTemplates",
  "operationType": 2,
  "filters": {
    "RootSchemaName": "UsrPrintTemplates",
    "logicalOperation": 0,
    "isEnabled": true,
    "filterType": 1,
    "ComparisonType": 3,
    "leftExpression": {
      "expressionType": 0,
      "columnPath": "UsrBitrixId"
    },
    "rightExpression": {
      "expressionType": 2,
      "parameter": {
        "dataValueType": 4,
        "value": 2098527
      }
    }
  },
  "columnValues": {
    "items": {
      "Name": {
        "expressionType": 2,
        "parameter": {
          "dataValueType": 1,
          "value": "Акт"
        }
      },
      "UsrFileType": {
        "expressionType": 2,
        "parameter": {
          "dataValueType": 0,
          "value": "dce4c8c1-4784-475e-8fac-7c244053095c"
        }
      }
    }
  },
  "isForceUpdate": false
}

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

но у меня почему-то обновляются все записи в таблице, т.е. фильтр не отрабатывает.

Как мне его записать, чтобы обновилась 1 запись, в которой поле UsrBitrixId = 2098527 ?

Нравится

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

Если есть доступ к базе, посмотрите в SQL-профайлере, что за запрос получается, с каким фильтром. Возможно, дело в неверно указанном типе для колонки UsrBitrixId.

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

Здравствуйте! Нужно добавить одна текстовое поля на странице генерация отчета.

Задача состоит в добавление фильтраций по текстовое значение, но когда я пробовал добавить новое поле, оно не появляется. Я попробовал добавить: "Text", "SHORT_TEXT", "LONG_TEXT", все из данный link: https://academy.terrasoft.ru/api/jscoreapi/7.12.0/#!/api/Terrasoft.core…, добавляются только "INTEGER","LOOKUP","ENUM", и "DATE". Как я могу добавить это поле что бы оно было видно? Может для этого поле мне нужно указать другие параметры.

P.S: Отчет создан через "BPMonlineReportDesigner"

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

Нравится

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

Добрый день!

1) Проверьте, что в локализируемых строках есть строка "Name".

2) Попробуйте тип "TEXT" (заглавными буквами).

3) Что VBName - есть такая колонка.

4) Может есть ошибки в консоли. И они могут подсказать вам

Добрый день Александр, я проверил все эти пункты, все колонки есть и локализированная строка тоже есть.  Сделал debugg, и нашёл что он использует модуль ReportFilterModule, и в коде, в switch  нет такой тип TEXT, но когда я пробовал замещать, вышло ошибка, что запрещено замещение модулей.  Может подсказать если есть другие способы, что бы добавить там это поле

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

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

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

Нравится

5 комментариев
Лучший ответ

Добрый день!

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

Добрый день!

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

Если доступа к серверу нет, то можно и без хранимок, используя в C#-скрипте БП классы Select и Update. С ними тоже сигналы не генерируются. А если нужно, чтобы по каждой записи отрабатывала логика встроенных и отдельных БП на изменение ответственного, то только с использованием класса EntitySchemaQuery.

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

Да забыл уточнить доступа к серверу действительно нет.

 

Пробовал реализовать через esq: 

          var isOwnerInChange = true;

           while (isOwnerInChange) {

                var subQuery = new EntitySchemaQuery(_uc.EntitySchemaManager,"UsrChangeOwnerHelperLog");

                    subQuery.AddColumn("UsrEntityId");

    

                var entitySchemaManager = _uc.EntitySchemaManager;

                var esq = new EntitySchemaQuery(entitySchemaManager, "Название схемы");

                esq.UseAdminRights = false;

                esq.AddAllSchemaColumns();



              //  какие то фильтры

                

                var mainFilter = new EntitySchemaQueryFilter(FilterComparisonType.NotExists);

                    mainFilter.LeftExpression = esq.CreateSchemaColumnExpression("Id");

                    mainFilter.RightExpressions.Add(new EntitySchemaQueryExpression(subQuery));

                    esq.Filters.Add(mainFilter);

                

                esq.RowCount=1000;

                    

                var entities = esq.GetEntityCollection(_uc);

                

                if (entities.Count > 0)

                    {

                        foreach (Entity entity in entities)

                        {

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

                            var newOwnerId = SearchOwner(accountId, "Account");



                            //Какая то логика

                        }

                } else {

                    isOwnerInChange = false;

                }

            }

В конце не забудьте каждой entity.Save();

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

Добрый день !

Есть ли возможность без программирования направлять пользователю на электронную почту уведомление (допустим по пятницам или по понедельникам)  - чтобы в теле письма была таблица со всеми лидами, созданными за прошедшую неделю (желательно кликабельные ссылки)? Как можно это реализовать ?

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

Нравится

3 комментария
Лучший ответ

Добрый день!

Выполнять в бизнес процессе, который по вашему расписанию будет отсылать Email сообщение (пример).

А вот сформировать тело сообщения с таблицей без программирования уже сложно.

Добрый день!

Выполнять в бизнес процессе, который по вашему расписанию будет отсылать Email сообщение (пример).

А вот сформировать тело сообщения с таблицей без программирования уже сложно.

Сидоров Александр В.,

Спасибо. Сложно= невозможно, я правильно понимаю ? А если исключить таблицу, и представить просто список ?

LilyG,

Ну да. Считать список можно стандартными блоками БП. А вот из списка сформировать текст, который потом пойдет в сообщение - уже нужен блок "Задание сценарий", а это уже программирование

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

Добрый день!

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

actionMenuItems.addItem(this.getButtonMenuItem({

                    "Caption": {"bindTo": "Resources.Strings.EditRightsCaption"},

                    "Tag": "editRights",

                    "Visible": {"bindTo": "getSchemaAdministratedByRecords"}

                }));

метод же найти не могу.

Нужно для назначения прав на страницу контрагента в БП без использования Terrasoft.Core.DB

Нравится

11 комментариев
Лучший ответ

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

В БП в элементе 'Задание-сценарий' можно реализовать произвольный запрос, в котором выполнять добавление/изменение/удаление данных напрямую в базу данных без использования Terrasoft.Core.DB:

var customQuery = new CustomQuery(context.UserConnection);
customQuery.SqlText = @"insert into Cases (Id) values (newid())";
using (DBExecutor dbExecutor = context.UserConnection.EnsureDBConnection())
{
	var datareader = customQuery.ExecuteReader(dbExecutor);
}
return true;

Вот ещё другой пример:

var userConnection = context.UserConnection;
var dr = new CustomQuery(userConnection, String.Format(
"update case set SolutionProvidedOn = null where Id = 974ca9fc-c066-4a7a-ac65-7ec91a44a067")).ExecuteReader(dbExecutor);
return true;

 

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

В БП в элементе 'Задание-сценарий' можно реализовать произвольный запрос, в котором выполнять добавление/изменение/удаление данных напрямую в базу данных без использования Terrasoft.Core.DB:

var customQuery = new CustomQuery(context.UserConnection);
customQuery.SqlText = @"insert into Cases (Id) values (newid())";
using (DBExecutor dbExecutor = context.UserConnection.EnsureDBConnection())
{
	var datareader = customQuery.ExecuteReader(dbExecutor);
}
return true;

Вот ещё другой пример:

var userConnection = context.UserConnection;
var dr = new CustomQuery(userConnection, String.Format(
"update case set SolutionProvidedOn = null where Id = 974ca9fc-c066-4a7a-ac65-7ec91a44a067")).ExecuteReader(dbExecutor);
return true;

 

Спасибо, Алла.

В БП этот код вызывает ошибку компиляции "The name dbExecutor does not exist in the current context"

Либо "The type or namespace name 'IDataReader' coul not be found" в первом варианте.

То есть это работает только для неинтерпетируемого процесса? 

Естественно, использование в БП блоков скриптов на C# требует компиляции процесса.

Виталий Егоров,

Если Вы используете второй вариант, попробуйте вместо UserConnection написать context.UserConnection.

 

Если первый вариант, то приблизительно такой код:

var userConnection = context.UserConnection;
var customQuery = new CustomQuery(userConnection);
customQuery.SqlText = @"insert into Cases (Id) values (newid())"; 
using (DBExecutor dbExecutor = userConnection.EnsureDBConnection())
{
	var reader = customQuery.ExecuteReader(dbExecutor);
}
return true;

 

Виталий Егоров пишет:

В БП этот код вызывает ошибку компиляции "The name dbExecutor does not exist in the current context"

Нужно обернуть в using, как и в первом фрагменте. 

 Либо "The type or namespace name 'IDataReader' coul not be found" в первом варианте.

А тут нужно включить нужную библиотеку System.Data в Usings (в дизайнере БП справа на вкладке «Методы»).

Спасибо, Алла, все работает.

Александр, спасибо, попробую добавить DataReader.

Добавил в этот же БП еще один сценарий с кодом:

foreach (string accountId in accountIdList){

    try {

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

               .Set("OwnerId", Column.Parameter(newOwner))

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

        update.Execute();

    }

    catch (SqlException ex){

        errorsList.Add(ex.Message);

    }

    finally {

        var sel = new Select(UserConnection)

            .Column("Name")

            .From("Account")

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

             using (DBExecutor dbExecutor = context.UserConnection.EnsureDBConnection()) {

            using (IDataReader dataReader = sel.ExecuteReader(dbExecutor)){

                       accountName = CreateJson(dataReader);

            }

        }

        accountNameList.Add(accountName);

    }

}

На выходе получаю ошибку:

'Query' does not contain a definition for 'ExecuteReader' and no extension method 'ExecuteReader' accepting a first argument of type 'Query' could be found (are you missing a using directive or an assembly reference?)

 

 

Может, дело в забытом «as Select» в конце объявления sel? Как тут:

Select select = 
	new Select(UserConnection)
		.Column("Id")
		.From("ActivityStatus")
		.Where("Finish").IsEqual(Column.Parameter(true))
		as Select;
using (var dbExecutor = UserConnection.EnsureDBConnection()) {
	using (IDataReader dr = select.ExecuteReader(dbExecutor)) {
		while (dr.Read()) {
			finishActivityStatuses.Add(UserConnection.DBTypeConverter.DBValueToGuid(dr[0]));
		}
	}
}

 

Спасибо, добрый человек! :)

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