Вопрос

Доброго времени суток! Подскажите, пожалуйста, как добавить CheckBox в средства связи. Для средства связи добавил в объекте логическое значение, например с названием "UsrIsMain".

У меня такой же вопрос

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

Мягко говоря не тривиальная задача, посмотрите как в BaseCommunication формируются конфиги для элементов управления для существующих в короюке типов комуникации и по аналогии для своего (добавленного) логического типа создайте конфиг для контрола. 

Григорий Чех,

В принципе мне понятно, как конфиг строится. Добавлял TextEdit поле, Lookup поле. А вот CheckBox не получается, выбрасывает ошибку следующую:
 

message: Cannot read property 'changeEvent' of undefined 
 date: Thu Jun 13 2019 11:01:45 GMT+0300 (Москва, стандартное время)
moduleId: CardModuleV2_########GUID###########_ContactPageV2_detail_ContactCommunication
moduleName: DetailModuleV2

Строил сам CheckBox вот так:
{
                        className: "Terrasoft.CheckBoxEdit",
                        id: "CheckBoxEditId",
                        classes: {
                            wrapClass: ["communication-detail-edit-user-class", "communication-additional-edit-label-wrap"]
                        },
                        value: {
                            bindTo: "UsrIsMain"
                        },
                        change: {
                            bindTo: "changeIsMainFlag"
                        }
  };

Сама функция changeIsMainFlag объявлена в ViewConfig'е.

 

Григорий Чех,

Вообще видел уже два поста в коммьюнити, которые тоже не понимали, как CheckBox вставить в Средства связи. Ответа там так и не было.

В детали средств связи контакта в пакете MarketingCampaign есть такое поле «Не актуальный» (NonActual) у каждого средства связи. Посмотреть на реализацию можно в схеме ContactCommunicationDetail.

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

Приветствую. Проблема с созданием Join'а.

Имеется вот такой SelectQuery.

SELECT
    [tbl_OfferingInMovement].[ID] AS [ID],
    [tbl_OfferingInMovement].[OfferingMovementID] AS [OfferingMovementID],
    [tbl_OfferingInMovement].[OfferingID] AS [OfferingID],
    [Offering].[Name] AS [OfferingName],
    [Offering].[Code] AS [OfferingCode],
    [Unit].[Name] AS [UnitName],
    [OfferingMovement].[StoreID] AS [StoreID],
    [tbl_Store].[Store] AS [Store],
    [tbl_OfferingInMovement].[Quantity] AS [Quantity],
    [tbl_OfferingInMovement].[BasicPrice] AS [BasicPrice],
    [tbl_OfferingInMovement].[BasicAmount] AS [BasicAmount],
    [tbl_OfferingInMovement].[SignedQuantity] AS [SignedQuantity],
    [tbl_OfferingInMovement].[SignedAmount] AS [SignedAmount],
    [tbl_OfferingInMovement].[Description] AS [Description],
    [OfferingMovementType].[ID] AS [OfferingMovementTypeID],
    [OfferingMovementType].[Name] AS [OfferingMovementType],
    [tbl_OfferingInMovement].[PlanQuantity] AS [PlanQuantity],
    [tbl_OfferingInMovement].[PlanAmount] AS [PlanAmount],
    [OfferingMovement].[StatusID] AS [OfferingMovementStatusID],
    [tbl_OfferingInMovement].[Price] AS [Price],
    [tbl_OfferingInMovement].[Amount] AS [Amount],
    [OfferingMovement].[CurrencyID] AS [CurrencyID],
    [tbl_Currency].[Currency] AS [Currency],
    [OfferingMovement].[CurrencyRate] AS [Rate],
    [tbl_OfferingInMovement].[ConsignmentID] AS [ConsignmentID],
    [Consignment].[Number] AS [ConsignmentNumber],
    [Offering].[OfferingChargeMethodID] AS [OfferingChargeMethodID],
    [OfferingMovement].[Number] AS [OfferingMovementNumber],
    [tbl_OfferingInMovement].[TZR] AS [TZR],
    [tbl_OfferingInMovement].[PrimeCost] AS [PrimeCost],
    [tbl_OfferingInMovement].[PrimeAmount] AS [PrimeAmount],
    [Offering].[Volume] AS [Volume],
    [Offering].[Weight] AS [Weight],
    [Offering].[BasicPrice] AS [OfferingBasicPrice],
    [tbl_OfferingInMovement].[TZRAmount] AS [TZRAmount],
    [tbl_OfferingInMovement].[DocumentID] AS [DocumentID],
    [tbl_OfferingInMovement].[ContractID] AS [ContractID],
    [tbl_OfferingInMovement].[InvoiceID] AS [InvoiceID],
    [tbl_Document].[Title] AS [DocumentNumber],
    [tbl_Contract].[Title] AS [ContractNumber],
    [tbl_Invoice].[InvoiceNumber] AS [InvoiceNumber],
    [tbl_OfferingInMovement].[PurchaseID] AS [PurchaseID],
    [tbl_Purchases].[Number] AS [PurchaseNumber],
    [OfferingMovement].[SupplierID] AS [SupplierID],
    [tbl_OfferingInMovement].[Date] AS [Date],
    [OfferingMovement].[ModifiedOn] AS [ModifiedOn],
    [OfferingMovement].[DateOfShipment] AS [DateOfShipment],
    [AccountBillingInfoItelon].[Name] AS [ItelonName],
    [AccountBillingPayerInfo].[Name] AS [PayerName]
FROM
    [dbo].[tbl_OfferingInMovement] AS [tbl_OfferingInMovement]
LEFT OUTER JOIN
    [dbo].[vw_Offering] AS [Offering] ON [Offering].[ID] = [tbl_OfferingInMovement].[OfferingID]
LEFT OUTER JOIN
    [dbo].[tbl_Unit] AS [Unit] ON [Unit].[ID] = [Offering].[DefaultUnitID]
LEFT OUTER JOIN
    [dbo].[vw_OfferingMovement] AS [OfferingMovement] ON [OfferingMovement].[ID] = [tbl_OfferingInMovement].[OfferingMovementID]
LEFT OUTER JOIN
    [dbo].[tbl_OfferingMovementType] AS [OfferingMovementType] ON [OfferingMovementType].[ID] = [OfferingMovement].[TypeID]
LEFT OUTER JOIN
    [dbo].[tbl_Store] AS [tbl_Store] ON [tbl_Store].[ID] = [OfferingMovement].[StoreID]
LEFT OUTER JOIN
    [dbo].[vw_OfferingMovement] AS [Consignment] ON [Consignment].[ID] = [tbl_OfferingInMovement].[ConsignmentID]
LEFT OUTER JOIN
    [dbo].[tbl_Currency] AS [tbl_Currency] ON [tbl_Currency].[ID] = [OfferingMovement].[CurrencyID]
LEFT OUTER JOIN
    [dbo].[vw_Document] AS [tbl_Document] ON [tbl_Document].[ID] = [tbl_OfferingInMovement].[DocumentID]
LEFT OUTER JOIN
    [dbo].[vw_Contract] AS [tbl_Contract] ON [tbl_Contract].[ID] = [tbl_OfferingInMovement].[ContractID]
LEFT OUTER JOIN
    [dbo].[vw_Invoice] AS [tbl_Invoice] ON [tbl_Invoice].[ID] = [tbl_OfferingInMovement].[InvoiceID]
LEFT OUTER JOIN
    [dbo].[vw_Purchases] AS [tbl_Purchases] ON [tbl_Purchases].[ID] = [tbl_OfferingInMovement].[PurchaseID]
LEFT OUTER JOIN
    [dbo].[tbl_AccountBillingInfo] AS [AccountBillingInfoItelon] ON [AccountBillingInfoItelon].[ID] = [OfferingMovement].[InfoItelonID]
LEFT OUTER JOIN
    [dbo].[tbl_AccountBillingInfo] AS [tbl_AccountBillingInfoPayer] ON [tbl_AccountBillingInfoPayer].[ID] = [tbl_OfferingInMovement].[PayerID]

Предпоследний Join(AS [AccountBillingInfoItelon]) создан мною. Работает отлично.

Вот его код. Заранее извиняюсь за синтаксис VBA.

    Set oTable = TSConnector.Services.GetNewItemByUSI(AccountBillingInfoTableName)
    Set oJoin = oSelectQuery.Items(0).Joins.Items(4).CreateCopy
    oJoin.UID = TSConnector.GenGUID
    oJoin.RightField = oJoin.RightField.ParentFields.Items(40)
    oJoin.LeftField = oTable.Fields.ItemsByName("ID")
    oJoin.LeftTableAlias = "AccountBillingInfoItelon"
    oJoin.JoinType = jtLeftOuter
    oSelectQuery.Items(0).Joins.AddItem oJoin
    oSelectQuery.Items(0).Joins.Items(oSelectQuery.Items(0).Joins.Count - 1).CanDisable = False

Последний создаётся не правильно.

    Set oJoin = oInvoiceSelectQuery.Items(0).Joins.Items(0).CreateCopy
    oJoin.UID = TSConnector.GenGUID
    oJoin.LeftField = oTable.Fields.ItemsByName("ID")
    oJoin.LeftTableAlias = "tbl_AccountBillingPayerInfo"
    oJoin.RightField = TSConnector.Services.GetNewItemByUSI(InvoiceTableName).Fields.Items(31)
    oJoin.JoinType = jtLeftOuter
    oSelectQuery.Items(0).Joins.AddItem oJoin
    oSelectQuery.Items(0).Joins.Items(oSelectQuery.Items(0).Joins.Count - 1).CanDisable = False

Проблема с RightField. Поле верное, то что нужно [PayerID]. Но мне надо чтобы оно доставала его именно из [tbl_Invoice]. А она же в SQL подставляет [tbl_OfferingInMoment]. Где можно изменить таблицу в Join'е или ещё где-то в SelectQuery. Целую неделю мучаюсь не могу понять.

У меня такой же вопрос

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

В коробке в скрипте wnd_IWTGraphWizardScript есть функция:

function GetPathByColumn(Column) {
	var Result = Column.Field.ParentFields.ParentTable.UID + snpFields + Column.Field.UID;
	var ParentJoin = Column.ParentJoin;
	while (ParentJoin) {
		Result = ParentJoin.RightField.ParentFields.ParentTable.UID +
			snpFields +
			ParentJoin.RightField.UID +
			jtLeft +
			ParentJoin.LeftField.ParentFields.ParentTable.UID +
			snpFields +
			ParentJoin.LeftField.UID +
			snpSegment +
			Result;
		ParentJoin = ParentJoin.ParentJoin;
	}
	return Result;
}  

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

 

О, спасибо Александр! Не думал что достучусь на этот форум. laugh Завтра с утра буду пробовать. Спасибо ещё раз. Отпишу что да как. 

Не получилось записывать название таблицы в Join. Что за связь используется так и не получилось выяснить. Я пользуюсь редактором VBA непосредственно в EXCEL. За Visual Studio еще не садился.

Воспользовался oSubSelectColumn. Отличная штука. Всё что хотел, получилось.

    Set oSubSelectColumn = oSelectQuery.Items(0).Columns.CreateSubSelectColumn
    Set oTable = TSConnector.Services.GetNewItemByUSI(AccountBillingInfoTableName)
 
    Dim oSQLFilter As CustomSQLFilter
    Dim oSelect As TSObjectLibrary.Select
    Set oSelect = oSelectQuery.CreateItem
    oSelect.FromTable = oTable
    oSelect.FromTableAlias = "AccountBillingInfo"
    Set oGeneralColumn = oSelectQuery.Columns.CreateGeneralColumn
    oGeneralColumn.Field = oTable.Fields.ItemsByName("Name")
    oGeneralColumn.ColumnAlias = "Name"
    oSelect.Columns.Add oGeneralColumn
    Set oSQLFilter = oSelect.Filters.CreateCustomSQLFilter
    oSQLFilter.SQLText = "[AccountBillingInfo].[ID] = [OfferingMovement].[InfoItelonID]"
    oSelect.Filters.Add oSQLFilter
    oSubSelectColumn.ColumnSelectQuery.Add oSelect
    oSubSelectColumn.ColumnAlias = "AccountBillingInfoItelon"
    oSelectQuery.Items(0).Columns.Add oSubSelectColumn
    oSelectQuery.Items(0).Columns.Items(oSelectQuery.Items(0).Columns.Count - 1).IsEnabled = True

 

В редакторе VBA тоже есть отладка. Не знаю, показывает ли структуру объектов, но вроде бы должен.

Можно и через SubSelect. Когда-то в базе на Orcacle упирались в лимит Join-ов и приходилось в дизайнере переделывать в sq часть колонок на колонки-подзапросы.

Зверев Александр, есть, да, структура объектов.

Если видно структуру, можно посмотреть, как устроен нормальный join. Ну, или использовать подзапросы.

Зверев Александр, Пользовался более года подзапросами. Сегодня столкнулся с проблемой фильтрации по столбцам от подзапросов. Долго не стал вникать в суть проблемы.

Решил вернуться к Join'ам. smiley

Решение к проблеме в самом низу этого сообщения.

Пошёл по вашему совету, Александр. Решил сравнивать структуры созданного мною нового Join'а и уже готового Join'а из другого готового SelectQuery.

Задача была поставлена аналогична упомянутой выше: прикрепить таблицу(создать join) к запросу(SelectQuery). При этом из прикрепленной таблицы(join'а) должны выбираться те строки, значения ключевых полей которых равны значениям полей не из исходной таблицы, на основе которой сформирован запрос(SelectQuery), а из таблицы, прикрепленной ранее (уже прикрепленного join'а). Всё тоже самое, что и в предыдущей задаче. Выражаясь кратким языком, присоединить join к уже имеющемся join'у в SelectQuery.

На следующей картинке представлен SQL текст уже (упомянутого в первом сообщения топика) готового запроса "sq_OfferingInMovement", сформированный на основе таблицы "tbl_OfferingInMovement" и нескольких прикрепленных таблиц к нему. В этом тексте можно увидеть, что к запросу прикреплена таблица(join), к заранее прикрепленному (join'у). В этом запросе всё правильно.

Синим выделены строки, означающие что к запросу прикреплено представление(если не понятно что такое представление, можно прочесть как "таблица") "[vw_Offering], у которого значение ключевого поля "[ID]" равняется значению поля исходной таблицы  "[tbl_OfferingInMovement].[OfferingID]". Этому присоединенному представлению присвоен псевдоним(alias) "[Offering]".

Красным выделены строки, означающие что к запросу прикреплена таблица "[tbl_Unit]", у которого значение ключевого поля "[ID]" равняется значению поля не исходной таблицы, а значению поля прикрепленного (синим выделено) представления [Offering].[DefaultUnitID].

В этом примере всё отлично.

Проблема заключалась в том, что при создании нового собственного прикрепления (join'а), которое должно было крепиться к уже имеющемуся прикреплению (join'у), в SQL тексте отображалось что новое прикрепление (join) крепиться не к уже имеющемуся прикреплению, а к исходной таблице. То есть, если взять пример выше, и прикрепление, которое выделено красным, было бы создано мною, то там вместо [Offering].[DefaultUnitID] было бы [tbl_OfferingInMovement][DefaultUnitID], что было бы неверным и, естественно, выдавало бы ошибку. Так как в [tbl_OfferingInMovement] нет поля [DefaultUnitID] и вообще это не то что мне нужно.

В ходе сравнения join'ов выяснилось, что у объекта Join, оказывается, есть параметр ParentJoin, которому необходимо присваивать тот Join, к которому будет необходимо прикреплять новый join.

Вот код правильно созданного Join'а и необходимого нам столбца из него.

Создание нового прикрепления (join'а) к исходной таблице запроса.

 
//Таблица, строки которой будем крепить. 
   Set objTSTable = objTSConnector.GetService(strAssemblingInTaskTableName)
 
   Set objTSAssemblingInTaskJoin = objTSSelect.Joins.CreateItem
   objTSAssemblingInTaskJoin.ParentJoins = objTSSelect.Joins
   objTSAssemblingInTaskJoin.LeftField = objTSTable.Fields.ItemsByName("ID")
   objTSAssemblingInTaskJoin.RightField = 
   objTSSelect.FromTable.Fields.ItemsByName("AssemblingInTaskID")
   objTSSelect.Joins.Add objTSAssemblingInTaskJoin

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

    Set objTSColumn = objTSSelect.Columns.CreateGeneralColumn
    objTSColumn.ParentColumns = objTSSelect.Columns
    objTSColumn.ParentJoin = objTSAssemblingInTaskJoin
    objTSColumn.ParentParametriticQuery = objTSSelectQuery
    objTSColumn.Field = objTSTable.Fields.ItemsByName("TaskID")
    objTSColumn.DependsOn.CommaText = objTSTable.SQLName
    objTSSelect.Columns.Add objTSColumn
    objTSColumn.IsEnabled = True

Теперь добавляем ещё одно прикрепление (join) к уже созданному выше прикреплению.

    'Таблица нового прикрепления.
    Set objTSTable = objTSConnector.GetService(strTaskTableName)
 
    Set objTSTaskJoin = objTSSelect.Joins.CreateItem
 
    'Вот здесь обязательно указать то прикрепление, к которому будем крепить это.
    objTSTaskJoin.ParentJoin = objTSAssemblingInTaskJoin
 
    objTSTaskJoin.ParentJoins = objTSSelect.Joins
    objTSTaskJoin.LeftField = objTSTable.Fields.ItemsByName("ID")
    objTSTaskJoin.RightField = objTSAssemblingInTaskJoin.LeftField.ParentFields.ItemsByName("TaskID")
    objTSSelect.Joins.Add objTSTaskJoin

Ну и добавляем обязательно столбец из этого прикрепления. Без него join не включиться, если не указать параметр у Join'а CanDisable = False. Без особой причины CanDisable можно не трогать. Достаточно просто добавить столбец из этого join'а, как его параметр IsEnabled сразу же станет True.

    Set objTSColumn = objTSSelect.Columns.CreateGeneralColumn
    objTSColumn.ParentColumns = objTSSelect.Columns
    objTSColumn.ParentJoin = objTSTaskJoin
    objTSColumn.ParentParametriticQuery = objTSSelectQuery
    objTSColumn.Field = objTSTable.Fields.ItemsByName("StatusID")
    objTSColumn.DependsOn.CommaText = objTSTable.SQLName
    objTSSelect.Columns.Add objTSColumn
    objTSColumn.IsEnabled = True

Всё.

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

Если есть какие-то замечания, то обязательно напишите.

Можно и так. Всё ли правильно, по коду сказать сложно. Если в результате в профайлере идёт нужный SQL-запрос, то нормально.

По поводу свойства ParentJoin, в SDK о нём есть, но очень кратко. Лучше смотреть примеры использования поиском по скриптам конфигурации.

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

Хочу DataSet, создаваемый SelectQuery, вывести в Excel через VBA. С этим проблем нет. SelectQuery является готовым сервисом, созданным администратором. К админке доступа нету. Всё прекрасно работает. Проблема в одном. Не могу Join по нормальному прикрепить.

Вот SQLText это SelectQuery:

SELECT
    [Offering].[Name] AS [OfferingName],
    [Offering].[Code] AS [OfferingCode],
    [tbl_OfferingInMovement].[Quantity] AS [Quantity],
    [OfferingMovementType].[Name] AS [OfferingMovementType],
    [OfferingMovement].[StatusID] AS [OfferingMovementStatusID],
    [tbl_OfferingInMovement].[InvoiceID] AS [InvoiceID],
    [tbl_Invoice].[InvoiceNumber] AS [InvoiceNumber],
    [tbl_OfferingInMovement].[Date] AS [Date]
FROM
    [dbo].[tbl_OfferingInMovement] AS [tbl_OfferingInMovement]
LEFT OUTER JOIN
    [dbo].[vw_Offering] AS [Offering] ON [Offering].[ID] = [tbl_OfferingInMovement].[OfferingID]
LEFT OUTER JOIN
    [dbo].[vw_OfferingMovement] AS [OfferingMovement] ON [OfferingMovement].[ID] = [tbl_OfferingInMovement].[OfferingMovementID]
LEFT OUTER JOIN
    [dbo].[tbl_OfferingMovementType] AS [OfferingMovementType] ON [OfferingMovementType].[ID] = [OfferingMovement].[TypeID]
LEFT OUTER JOIN
    [dbo].[vw_Invoice] AS [tbl_Invoice] ON [tbl_Invoice].[ID] = [tbl_OfferingInMovement].[InvoiceID]
LEFT OUTER JOIN
    [dbo].[tbl_AccountBillingInfo] AS [AccountBillingInfoItelon] ON [AccountBillingInfoItelon].[ID] = [OfferingMovement].[InfoItelonID]

Последняя строка, добавленный мной JOIN. Он работает на отличненько.

Его код(кстати, скажите насколько он крив):

    Set oTable = TSConnector.Services.GetNewItemByUSI(AccountBillingInfoItelonTableName)
    Set oJoin = oSelectQuery.Items(0).Joins.Items(4).CreateCopy ' создание копии join'а LEFT OUTER JOIN [dbo].[tbl_OfferingMovementType] AS [OfferingMovementType] ON [OfferingMovementType].[ID] = [OfferingMovement].[TypeID]
    oJoin.UID = TSConnector.GenGUID
    oJoin.RightField = oJoin.RightField.ParentFields.Items(40) 'нужное поле из OfferingMovement
    oJoin.LeftField = oTable.Fields.ItemsByName("ID")
    oJoin.LeftTableAlias = "AccountBillingInfoItelon"
    oJoin.JoinType = jtLeftOuter
    oSelectQuery.Items(0).Joins.AddItem oJoin
    oSelectQuery.Items(0).Joins.Items(oSelectQuery.Items(0).Joins.Count - 1).CanDisable = False

А вот этот не хочет:

    Set oTable = TSConnector.Services.GetNewItemByUSI(InvoiceTableName)
    Set oJoin = oSelectQuery.Items(0).Joins.Items(10).CreateCopy
    oJoin.UID = TSConnector.GenGUID
    oJoin.RightField = oSelectQuery.Items(0).Joins.Items(9).LeftField.ParentFields.ItemsByName("PayerID") 'проблема именно здесь. Крепиться Field от tbl_Invoice. Но в SQL_Text ошибка. Крепит Field от не того Table.
    oJoin.LeftField = oTable.Fields.ItemsByName("ID")
    oJoin.LeftTableAlias = "AccountBillingPayerInfo"
    oJoin.JoinType = jtLeftOuter
    oSelectQuery.Items(0).Joins.AddItem oJoin
    oSelectQuery.Items(0).Joins.Items(oSelectQuery.Items(0).Joins.Count - 1).CanDisable = False

После него в SQLText в конце появляется:

LEFT OUTER JOIN
    [dbo].[vw_Invoice] AS [AccountBillingPayerInfo] ON [AccountBillingPayerInfo].[ID] = [tbl_OfferingInMovement].[PayerID]

В результате ошибка. В конце должно быть не [tbl_OfferingInMovement].[PayerID], а [tbl_Invoice].[PayerID]. Ведь креплю то я PayerID именно от tbl_Invoice. А в SQLText он зачем-то подставляет PayerID из tbl_OfferingInMovement, которого там нету. Именно в этом ошибка. Где вообще в SelectQuery эти прикрепленные таблицы?

Я может быть как-то не правильно Field добавляю в Join'ы. И до конца не понимаю суть этих Field'ов. 

Может быть как-то с нуля можно создать этот join. Есть ли какие нибудь статьи?

 

У меня такой же вопрос

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

Вопрос обсудили в соседней Вашей теме.

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

Друзья,

у нас потрясающая новость! Bpm’online названа лидером в рейтинге лучших CRM-решений мира — The Forrester Wave™: CRM Suites for Midsize Organizations, 2016! Полная версия отчета уже на нашем сайте.

Поделиться

0 комментариев
Войдите или зарегистрируйтесь, чтобы комментировать
Публикация

Иногда во время открытия конфигурации появляется сообщение:

Причина появления данного сообщения связана с часовыми поясами системы.Проблема может возникнут из-за обновления часовых поясов системы или у контакта в приложении Terrasoft установлен часовой пояс, который отсутствует в реестре Windows.

Проблема может возникнуть в двух функциях конфигурации:

  • CheckTimeZone (сервис scr_Main)
  • GetTimeZoneCaption (сервис scr_DateUtils)

Для устранения проблемы необходимо заменить функцию CheckTimeZone находящуюся в сервисе scr_Main на новую:

function CheckTimeZone() {
    var UserTimeZone = Connector.CurrentUser.TimeZone;
    var SystemTimeZone = System.GetSystemTimeZone();
     
    var TimeZoneEnum = GetSingleItemByCode('enm_TimeZone');
    var EnmUserTimeZone = TimeZoneEnum.ItemsByCode(UserTimeZone);          
    if (IsEmptyValue(EnmUserTimeZone)) {
        UserTimeZone = '';
    }
     
    if (!UserTimeZone) {
        UserTimeZone = SystemTimeZone;
        Connector.CurrentUser.TimeZone = UserTimeZone;
    }
    if (UserTimeZone == SystemTimeZone) {
        return;
    }
    var Message = FormatStr(
        "Часовой пояс системы: %1\rЧасовой пояс текущего контакта: %2\rИспользовать часовой пояс системы?",
        GetTimeZoneFullCaption(SystemTimeZone), GetTimeZoneFullCaption(UserTimeZone));                          
    if (ShowConfirmationDialog(Message) != wmrYes) {
        return;
    }      
    Connector.CurrentUser.TimeZone = SystemTimeZone;
    var UpdateQuery = GetSingleItemByCode('uq_ContactTimeZone');
    UpdateRecordField(UpdateQuery, Connector.CurrentUser.ContactID,
        Array('TimeZone'), Array(SystemTimeZone));              
}

 

А также необходимо заменить функцию GetTimeZoneCaption находящуюся в сервисе scr_DateUtils на новую:

function GetTimeZoneCaption(TimeZone, ForScheduler) {
    var TimeZoneEnum = GetSingleItemByCode('enm_TimeZone');
    var TimeZoneCaption = '';
    if (!IsEmptyValue(TimeZone)) {
        var TimeZoneValue = TimeZoneEnum.ItemsByCode(TimeZone);
        if (!IsEmptyValue(TimeZoneValue)) {
            TimeZoneCaption = TimeZoneEnum.ItemsByCode(TimeZone).Caption;
        } else {
            TimeZoneCaption = TimeZone;
        }
    }
    var Result = 'GMT';  
    Result += (ForScheduler ? '\r' : '') +
        (TimeZoneCaption.substring(4, 5) == ')' ? '' : TimeZoneCaption.substring(4, 10));
    return Result;
}

 

Как еще одним решением может быть - поудалять дубли часовых поясов в ветке [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones]. Оставив те часовые пояса, которые содержат ключ Display:

Иногда помогает внесение изменений в реестр Windows, обновив значение ветки [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\Kamchatka Standard Time]. Необходимые значение находятся в файле Kamchatka Standard Time.reg

Также можно просто импортировать ветку [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\Kamchatka Standard Time] из другого реестра системы, где пользователь работает без сбоев.

Поделиться

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

Коммент по исследованию этой проблемы с версией TSXRM 3.3.1

(Похоже. что в версии TS 3.4 под Win10 этого не наблюдается)

Последнее время на Win10 обновления от MS дописывают ключи для часовых поясов в реестр, но не обновляют библиотеку - tzres.dll.mui 

  1. Программа (например TSClient.exe) запрашивает локальное имя часового пояса Судана. (о-в Св.Антония, Фиджи и т.д.)
  2. Операционка считывает значение ключа из реестра - (UTC+02:00) Хартоум - @tzres.dll,-2890
  3. Вызывает библиотеку tzres.dll
  4. Библиотека чтобы дать имя на установленном в ОС языке вызывает местную - tzres.dll.mui  и запрашивает строку за нумером -2890 Смотрим самый последний номер строки в библиотеке, например, это: STRINGTABLE LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT {2810, "(UTC+03:00) Стамбул"}
  5. Система возвращает ПУСТО (NULL)

TSClient видит пусто в энумераторе enm_TimeZone, которое при проверке на уникальность срабатывает как дублирование названия.

Возникает ошибка в бинарнике, вызванная библиотекой TSObjectLibrary.dll - там лежит вызов

GetSingleItemByCode('enm_TimeZone') -> Services.GetNewItemByUSI(Code)

Когда TSObjectLibrary видит слово enm_TimeZone, она хватается за пистолет и, очистив энумератор, заполняет его снова из реестра ОС и падает из-за  NULL.

Варианты Решения:

1. Обновить библиотеку местного диалекта для часовых поясов tzres.dll.mui. Не факт, что следующее обновление её не затрёт.

2. Создать новый энумератор (имя + ID), заполнять его кодом JScript ручками из ОС при запуске и заменить вызовы на него. Не забываем таблицы и датасеты типа ds_Contact, tbl_City etc.. 

3. Заполнять энумератор самим, а хексредактором "исправить" :)  злосчастное имя enm_TimeZone в библиотеке TSObjectLibrary

 

 

 

 

Спасибо за анализ.

Для Судана и прочего сообщение «Дублируется значение свойства 'Caption'. Значение 'Sudan Standard Time' уже существует» встречалось и в 3.4.0, и даже в 3.4.1. Помогает удаление пояса в Regedit.

Это так, но следующее обновление Вин10, скорее всего, снова его внесёт в реестр. И добавит острова Святого Антония)). Поскольку мой парк машин - велик и разбросан по стране - решение через общую конфигурацию TS представляется более оптимальным. Можно чистить реестр средствами групповой политики, можно отменить всем ВинАвтоАпдейт навсегда (не 35 дней), можно найти самый последний вариант MUI и каждому его подсунуть, но не факт, что следующее обновление не заменит и его. Можно забить корректными данными enm_TimeZone и запретить ему автообновление; обновлять централизованно разработчику по фиксации новых часовых поясов в MS-KB файлах. Можно ещё исключить все упоминания enm_TimeZone из конфигурации: часовой пояс клиента/контакта/города не всем необходим. )

До этого общим решением наших админов было: чистка реестра, откат последнего обновления Win10 или, вообще, откат на Win7. :) Развелось самостоятельных любителей десятки... И это - не первая проблема работы TS3.x под Win10, и что ещё нам принесут очередные обновления от MS. :)

Сбои с новыми поясами бывают нерегулярно и не на всех компьютерах. То есть, если удалили Sudan, не факт, что сразу на тот же компьютер придёт Sao Tome.

C Windows 10 есть и более серьёзные и трудноустранимые препятствия в обновлениях. Помогает от них только переход с более старых версий на 3.4.1.

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

Более серьёзные трудности - копятся. Пока что мы все их обходим..))

Да, у меня под руками TS3.4.1 так что я  - не голословен.))

Надеюсь, что вмешательство в бинарный код фирма не почтёт за нарушение её прав? Мне уже приходилось менять код екзешника TSClient - ничего, притерпелись...)

 

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

Выбивало при входе ещё при Marquesas Standard Time в 2016 году. Думал, что там просто две записи в реестре об одном поясе, но, как Вы расследовали, всё оказалось интересней.

Опять же, с часовым поясом — не самое страшное, что может случиться при обновлении Windows 10.

Помню эту историю)) 

Самое страшное мы - уже победили.. Но, чем чорт не шутит...

Кстати, TSAdmin.exe тоже "кашляет" на эту историю.. Обходим, гладим, усмиряем..) Там то мы не можем конфигурацией помочь. Только вмешательство в тело бинарника. А это мы умеем)

 

Последний реально существующий релиз - TS3.3.1.184 Скачан два года назад с официального сайта.

 

https://c2n.me/3TZJXIb

вот такая переферналия, но это вполне победимо)

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

Главная новость лета! Крупнейшее в мире аналитическое агентство Gartner включило CRM-систему bpm’online в рейтинг лучших решений для управления продажами — Gartner Magic Quadrant for Sales Force Automation!

Огромная благодарность клиентам и партнерам — за доверие и поддержку, а всей команде Terrasoft — за профессионализм!

Ознакомиться с полной версией отчета Gartner Magic Quadrant for Sales Force Automation >>

Поделиться

0 комментариев
Войдите или зарегистрируйтесь, чтобы комментировать
Публикация

Рады сообщить, что мы выпустили новый пакет обновлений CRM-линейки bpm’online.

Сегодня наши клиенты получат более 50 различных улучшений, в частности:

  • Быстрые фильтры: настроенные вами фильтры теперь сохраняются при обновлении страницы, переходе между разделами и повторном входе в систему.
  • Мобильное приложение: по завершении звонка можно указать результат разговора и сохранить информацию в истории клиента.
  • Импорт данных из Excel: добавлена возможность отметить тегом импортированные записи.
  • Лендинги: упрощен интерфейс настройки интеграции с посадочными страницами сайта.
  • Дизайнер процессов: реализовано автосохранение схем бизнес-процессов — если вы закрыли диаграмму процесса без сохранения, то при повторном открытии сможете восстановить несохраненные данные.
  • Журнал процессов: добавлена возможность перейти по ссылке к связанным записям процесса.

Узнайте больше на сайте Академии Terrasoft >>

Поделиться

0 комментариев
Войдите или зарегистрируйтесь, чтобы комментировать
Публикация

Важная для нас награда! Bpm’online — в пятерке лидеров CRM-рынка в рейтинге The 2016 CRM Market Awards.

Четвертый год подряд наша система входит в список сильнейших CRM-решений мира по мнению авторитетного издания CRM Magazine. В этом году bpm’online представлена в ТОП-5 сразу в двух категориях: Sales Force Automation (автоматизация продаж) и Midmarket CRM Suite (комплексные CRM-решения для среднего бизнеса).

Как отметила Ребекка Веттерман, вице-президент Nucleus Research, благодаря последним обновлениям система стала еще более простой и удобной, обеспечивая рост продуктивности менеджеров. При этом функциональные возможности по управлению бизнес-процессами предоставляют компаниям существенное конкурентное преимущество.

Узнайте больше о награде

Поделиться

0 комментариев
Войдите или зарегистрируйтесь, чтобы комментировать
Публикация

Проблема
Не загружается надстройка Terrasoft в Outlook.
При включении надстройки вручную, надстройка не появляется.

В окне [Надстройки для модели компонентов объектов (COM)] видим сообщение: Выгружен (Unloaded)


Решение

Перед решением данной проблемы необходимо ознакомится со статьями

Удаляем обновление (отключаем):
KB3114409 - после установки автоматических обновлений Windows (KB3114409), Office 2010 Outlook запускается в безопасном режиме, письма не привязываются, и скрыто много полей, вопрос решается удалением обновления

Исправление проблемы

  1. Открываем реестр Windows для редактирования (C:\Windows\regedit.exe)
  2. Переходим в ветку HKEY_CURRENT_USER\Software\Microsoft\Office\15.0\Outlook\Resiliency (16.0 - Outlook 2016, 15.0 - Outlook 2013, 14.0 - 2010, 13.0 - 2007)
  3. Находим необходимый нам ключ

  4. Удаляем наш ключ (если нашли именно наш ключ иначе удаляем все) и запускаем (перезапускаем) Outlook

Поделиться

0 комментариев
Войдите или зарегистрируйтесь, чтобы комментировать
Публикация

Проблема
Настройка в Outlook присутствует, но рассылка не происходит.
Не открываются/не создаются письма в Terrasoft.

Решение
Последовательность действий для понижения безопасности Outlook:

  1. В Outlook выполните: Файл -> Параметры
  2. [Центр управления безопасности] -> [Параметры центра управления безопасности]
  3. [Программный доступ] -> [Никогда не предупреждать о подозрительной активности]
  4. [Программный доступ] -> [Включить режим предотвращения выполнения данных], снять галочку (этот пункт можно пропустить)
  5. [Программный доступ] -> [Включить все макросы], а также установить галочку в поле [Применять параметры безопасности макросов к установленным надстройкам]
  6. Перезапускаем Outlook

Важно
Понизить параметры безопасности Outlook может только пользователь имеющий права администратора.

Поделиться

0 комментариев
Войдите или зарегистрируйтесь, чтобы комментировать