Добрый день!
Столкнулся с проблемой и теряюсь в решении
При создании Отчета на Счет, при наличии нескольких значений Платежных реквизитов для данного Контрагента, формируется отчет для всех значений.
Как решение принял добавление на карточку редактирования Платежных реквизитов BoolDataControl'а (напр. "Основной"). Теперь возникает вопрос: как реализовать проверку на наличие отметки и формирование отчета только для этого Платежного реквизита и на каком этапе формирования отчета осуществлять проверку?
Спасибо!
Нравится
"Fishi" написал:как реализовать проверку на наличие отметки и формирование отчета только для этого Платежного реквизита и на каком этапе формирования отчета осуществлять проверку?
В сервисе select query отчета создать фильтр и оставить его включенным по полю "Основной" = true.
Хотел еще сделать проверку по полю "Основной", является ли он единственным (по примеру поля "Базовая" для Валют)
//----------------------------------------------------------------------------- // ds_AccountBillingInfoScript //----------------------------------------------------------------------------- function SetDefaultDatasetValues(Dataset) { Dataset.Values('IsDefault') = false; } function CheckIsDefault(Dataset) { var IsDefaultField = Dataset.DataFields.ItemsByName('IsDefault'); if (IsDefaultField.Value == true) { var OldDefaultID = GetDatasetFieldValueFromDatasetByUSI( 'ds_AccountBillingInfo', 'IsDefault', true, 'ID'); if ((OldDefaultID != Dataset.Values('ID')) && !(IsEmptyGUID(OldDefaultID))) { IsDefaultField.Value = false; System.MessageDialog(CouldntBeMoreThenOneDefaultAccountBilling, mdtWarning, mdbYes, 0); } } } // ---------------------------------------------------------------------------- // Event handlers // ---------------------------------------------------------------------------- function SelfOnDatasetAfterAppend(Dataset) { SetDefaultDatasetValues(Dataset); } function SelfOnDatasetBeforePost(Dataset) { CheckIsDefault(Dataset); }
Но при закрытии окна редактирования вместо окна уведомления System.MessageDialog выскакивает ошибка: "Ошибка выполнения метода 'SelfOnDatasetBeforePost'. Exception thrown and not caught"
Не подскажете что я пропустил?
Возможно, у Вас не создан фильтр 'IsDefault' в sq_AccountBillingInfo.
var OldDefaultID = GetDatasetFieldValueFromDatasetByUSI( 'ds_AccountBillingInfo', 'IsDefault', true, 'ID');
В этой строчке реализовано получение значения записи с галочкой в поле "Основной", но при этом не учтено, что ее нужно искать впределах текущего контрагента.
Вместо строчки
var OldDefaultID = GetDatasetFieldValueFromDatasetByUSI( 'ds_AccountBillingInfo', 'IsDefault', true, 'ID');
можно написать
var AccountBillingInfoDataset = GetSingleItemByCode('ds_AccountBillingInfo', 'DefaultInfo'); ApplyDatasetFilter(AccountBillingInfoDataset, 'AccountID', Dataset('AccountID'), true); ApplyDatasetFilter(AccountBillingInfoDataset, 'IsDefault', true, true); AccountBillingInfoDataset.Open(); var OldDefaultID = AccountBillingInfoDataset('ID'); AccountBillingInfoDataset.Close();
Не самый оптимальный способ найти нужную запись, но мне кажется Вам так понятнее будет.
Первый фильтр
ApplyDatasetFilter(AccountBillingInfoDataset, 'AccountID', Dataset('AccountID'), true);
работает нормально. Но вот второй - нет. Значение OldDefaultID каждый раз равно ID первой добавленной записи Платежные реквизиты, следовательно при установке признака Основной на других Реквизитах срабатывает System.MessageDialog и изменения не сохраняются.
Services.GetNewItemByUSI(USI) - всегда создает новый экземпляр сервиса.
Services.GetSingleItemByUSI(USI) - сначала ищет среди закешированных сервисов, созданных этим же методом, если находит, возвращает ссылку, иначе создает, кеширует и тоже возвращает ссылку.
GetSingleItemByCode(USI, UniqueCode) - сначала ищет среди закешированных сервисов, при поиске использует еще и параметр UniqueCode, если не находит также создает экземпляр, кеширует, используя UniqueCode и возвращает ссылку.
"Fishi" написал:DefaultInfo? (подумал что опечатка, изменил на IsDefault, а на результате это не отобразилось)
Таким образом это изменение ничего не даст.
Перед
AccountBillingInfoDataset.Open();
посмотрите
Connector.DBEngine.GetSelectQuerySQLText(AccountBillingInfoDataset.SelectQuery)
или после прохождения этой строчки, какой запрос идет в базу.
Получается вот такой запрос:
SELECT [tbl_AccountBillingInfo].[ID] AS [ID], [tbl_AccountBillingInfo].[BankAccountNumber] AS [AccountNumber], [tbl_AccountBillingInfo].[Description] AS [Description], [tbl_Bank].[Name] AS [BankName], [tbl_AccountBillingInfo].[BankID] AS [BankID], [tbl_AccountBillingInfo].[AccountID] AS [AccountID], [tbl_Bank].[MFO] AS [MFO], [tbl_Bank].[Address] AS [Address], [tbl_AccountBillingInfo].[IsDefault] AS [IsDefault] FROM [dbo].[tbl_AccountBillingInfo] AS [tbl_AccountBillingInfo] LEFT OUTER JOIN [dbo].[tbl_Bank] AS [tbl_Bank] ON [tbl_Bank].[ID] = [tbl_AccountBillingInfo].[BankID]
Причем значение OldDefaultID присваеваеются в том порядке, в котором отображается результат запроса в Администраторе, что в принципе логично) но непонятно почему так и не работает фильтр по полю IsDefault и его значению true.
Часто бывает, что в результате использования GetSingleItemByCode фильтры датасета не обновляются. Попробуйте перед применением фильтров вставить:
EnableDatasetFilters(AccountBillingInfoDataset, false);
Олег Лабьяк,
разработчик,
3-я линия Службы поддержки Terrasoft.
1.
"Лабьяк Олег Игоревич" написал:Попробуйте перед применением фильтров вставить:EnableDatasetFilters(AccountBillingInfoDataset, false);
Изменений ноль((, OldDefaultID по-прежнему не обновляется.
2.Кстати, если уже говорим о фильтрах, может еще одну проблему поможете решить:
В разделе Документы создал свой отчет. Отчет создается и все поля заполняются, но нужно особу, которая должна подписывать документ выбирать по признаку (Роль в разделе Контакты) из справочника ds_DecisionRole.
В скрипте отчета пробую реализовать фильтр:
var ContactDataset = GetSingleItemByUSI('ds_Contact'); ApplyDatasetFilter(ContactDataset, 'AccountID', Dataset('SupplierID'), true); ApplyDatasetFilter(ContactDataset, 'DecisionRoleID', '{ID значения из справочника}', true);
Но на GetSingleItemByUSI выдает ошибку "Ошибка выполнения метода 'ds_DocumentMyReport'. Object expected «Call Stack»"
По поводу второго вопроса как раз всё понятно, такой функции нет. Есть функция GetSingleItemByCode, а GetSingleItemByUSI - метод объекта Services, так же, как и GetNewItemByUSI. Правильно будет: Services.GetSingleItemByUSI('ds_Contact'). Но в данном случае лучше использовать GetSingleItemByCode.
Над первым вопросом ещё подумаю.
Олег Лабьяк,
разработчик,
3-я линия Службы поддержки Terrasoft.
Насчет первого вопроса: какое у Вас значение параметра IsDefault? Попробуйте в SelectQuery установить значение этого параметра равным 1, а в скрипте использовать функцию EnableDatasetFilters:
var AccountBillingInfoDataset = GetSingleItemByCode('ds_AccountBillingInfo', 'DefaultInfo'); EnableDatasetFilters(AccountBillingInfoDataset, false); ApplyDatasetFilter(AccountBillingInfoDataset, 'AccountID', Dataset('AccountID'), true); EnableDatasetFilters(AccountBillingInfoDataset, true, 'IsDefault'); AccountBillingInfoDataset.Open(); var OldDefaultID = AccountBillingInfoDataset('ID'); AccountBillingInfoDataset.Close();
Олег Лабьяк,
разработчик,
3-я линия Службы поддержки Terrasoft.
1.
"Лабьяк Олег Игоревич" написал:Насчет первого вопроса: какое у Вас значение параметра IsDefault? Попробуйте в SelectQuery установить значение этого параметра равным 1, а в скрипте использовать функцию EnableDatasetFilters
Значение с самого начала установил 1. Проблема с OldDefault осталась (даже если вместо второго ApplyDatasetFilter (как советовала Раловец Ольга) использовать EnableDatasetFilters (рекомендация Лабьяк Олег)).
2.
"Лабьяк Олег Игоревич" написал:Но в данном случае лучше использовать GetSingleItemByCode
Services.GetSingleItemByUSI('ds_Contact') работает. На GetSingleItemByCode('ds_Contact, 'DefaulyInfo') и ApplyDatasetFilter(ContactDataset, AccountID, Dataset('AccouuntID'), true)та же ошибка выполнения метода (Object expected). Все нужные поля в sq_Отчета и ds_Отчета есть, отмечены как поле фильтрации и тд. Никак не пойму чего еще((((
Спасибо!
По второму вопросу - скорее всего, к скрипту отчёта не подключен скрипт scr_DB. Упомянутые функции находятся именно в нём.
По первому - теряюсь в догадках... Можете выложить скрипт с функцией (и остальные сервисы, необходимые для корректной его работы)? Уточните, пожалуйста, Вашу версию.
Олег Лабьяк,
разработчик,
3-я линия Службы поддержки Terrasoft.
Олег Лабьяк,
разработчик,
3-я линия Службы поддержки Terrasoft.
Спасибо! Второй вопрос закрыт!!!
Осталось дело за малым:wink:
Вот скрипт функции с подключенным scr_DB
// ds_AccountBillingInfoScript function SetDefaultDatasetValues(Dataset) { Dataset.Values('IsDefault') = false; } function CheckIsDefault(Dataset) { var IsDefaultField = Dataset.DataFields.ItemsByName('IsDefault'); var DatasetID = Dataset.Values('ID'); if (IsDefaultField.Value == true) { var AccountBillingInfoDataset = GetSingleItemByCode('ds_AccountBillingInfo','DefaultInfo'); EnableDatasetFilters(AccountBillingInfoDataset, false); ApplyDatasetFilter(AccountBillingInfoDataset, 'AccountID', Dataset('AccountID'), true); EnableDatasetFilters(AccountBillingInfoDataset, true, 'IsDefault'); AccountBillingInfoDataset.Open(); var OldDefaultID = AccountBillingInfoDataset('ID'); AccountBillingInfoDataset.Close(); if ((OldDefaultID != Dataset.Values('ID')) && !(IsEmptyGUID(OldDefaultID))) { IsDefaultField.Value = false; System.MessageDialog(CouldntBeMoreThenOneDefaultAccountBilling, mdtWarning, mdbYes, 0); } } } ---------------- // Event handlers ---------------- function SelfOnDatasetAfterAppend(Dataset) { SetDefaultDatasetValues(Dataset); } function SelfOnDatasetBeforePost(Dataset) { CheckIsDefault(Dataset); }
и запрос sq_AccountBillingInfo
SELECT [tbl_AccountBillingInfo].[ID] AS [ID], [tbl_AccountBillingInfo].[BankAccountNumber] AS [AccountNumber], [tbl_AccountBillingInfo].[Description] AS [Description], [tbl_Bank].[Name] AS [BankName], [tbl_AccountBillingInfo].[BankID] AS [BankID], [tbl_AccountBillingInfo].[AccountID] AS [AccountID], [tbl_Bank].[MFO] AS [MFO], [tbl_Bank].[Address] AS [Address], [tbl_AccountBillingInfo].[IsDefault] AS [IsDefault] FROM [dbo].[tbl_AccountBillingInfo] AS [tbl_AccountBillingInfo] LEFT OUTER JOIN [dbo].[tbl_Bank] AS [tbl_Bank] ON [tbl_Bank].[ID] = [tbl_AccountBillingInfo].[BankID]
Хотел уточнить, какая функциональность всё-таки требуется в итоге. Дело в том, что я реализовал у себя доработки по Вашему описанию, и не заметил каких-либо проблем в работе, фильтры срабатывают корректно.
Насколько я понимаю, сейчас ситуация следующая: первая запись на детали у Вас с признаком IsDefault = true. Соответственно, в данной реализации Вы никогда не измените её на false, а любую другую - на true, поскольку запрос всегда находит эту запись и срабатывает условие if ((OldDefaultID != Dataset.Values('ID')) && !(IsEmptyGUID(OldDefaultID))).
Возможно, Вам поможет следующий вариант функции CheckIsDefault:
function CheckIsDefault(Dataset) { var IsDefaultField = Dataset.DataFields.ItemsByName('IsDefault'); var DatasetID = Dataset.Values('ID'); if (IsDefaultField.Value == true) { var AccountBillingInfoDataset = GetSingleItemByCode('ds_AccountBillingInfo','DefaultInfo'); EnableDatasetFilters(AccountBillingInfoDataset, false); ApplyDatasetFilter(AccountBillingInfoDataset, 'AccountID', Dataset('AccountID'), true); EnableDatasetFilters(AccountBillingInfoDataset, true, 'IsDefault'); AccountBillingInfoDataset.Open(); try { var OldDefaultID = AccountBillingInfoDataset('ID'); if ((OldDefaultID != Dataset.Values('ID')) && !(IsEmptyGUID(OldDefaultID))) { if (ShowConfirmationDialog("Запись с признаком 'IsDefault' уже существует. " + "Вы хотите установить этот признак для текущей записи?") == wmrYes) { AccountBillingInfoDataset.DisableEvents(); AccountBillingInfoDataset.Edit(); AccountBillingInfoDataset('IsDefault') = false; AccountBillingInfoDataset.Post(); AccountBillingInfoDataset.EnableEvents(); } else { IsDefaultField.Value = false; } } } finally { AccountBillingInfoDataset.Close(); } } }
Для её корректной работы необходимо подключить скрипт scr_WindowUtils. Результат работы будет виден после обновления реестра детали.
Функция проверяет, существует ли на детали контрагента запись с признаком IsDefault. Если да, предлагает установить этот признак для текущей записи и убрать его для прежней.
Олег Лабьяк,
разработчик,
3-я линия Службы поддержки Terrasoft.
"Лабьяк Олег Игоревич" написал:Насколько я понимаю, сейчас ситуация следующая: первая запись на детали у Вас с признаком IsDefault = true. Соответственно, в данной реализации Вы никогда не измените её на false, а любую другую - на true, поскольку запрос всегда находит эту запись и срабатывает условие if ((OldDefaultID != Dataset.Values('ID')) && !(IsEmptyGUID(OldDefaultID))).
Вот тут-то я и не мог разобраться - даже если для всех записей IsDefault = false, OldDefaultID все равно присваивается значение ID первой записи (вместо пустого).
"Лабьяк Олег Игоревич" написал:Функция проверяет, существует ли на детали контрагента запись с признаком IsDefault. Если да, предлагает установить этот признак для текущей записи и убрать его для прежней.
И также убирает признак только с первой записи, для остальных событие не срабатывает, поскольку запрос постоянно выдает только ID первой записи(((
В принципе можно просто внимательно следить за полем IsDefault и недопускать нескольких значений одновременно, но хотелось чтоб всё было красиво:smile:
TS X25 3.1.1.26
Понятно, сейчас проверю на Вашей версии.
Олег Лабьяк,
разработчик,
3-я линия Службы поддержки Terrasoft.
Проверил на версии 3.1.1.26, работает корректно. Попробуйте поставить debugger перед AccountBillingInfoDataset.Open(); и посмотреть, какой запрос выполняется в профайлере во время открытия датасета.
Проверьте, пожалуйста, если заменить
var AccountBillingInfoDataset = GetSingleItemByCode('ds_AccountBillingInfo','DefaultInfo');
на
var AccountBillingInfoDataset = Services.GetNewItemByUSI('ds_AccountBillingInfo');
фильтрация тоже не работает?
Олег Лабьяк,
разработчик,
3-я линия Службы поддержки Terrasoft.
Если заменить GetSingleItemByCode на Services.GetNewItemByUSI результат не изменился.
"Лабьяк Олег Игоревич" написал:Попробуйте поставить debugger перед AccountBillingInfoDataset.Open(); и посмотреть, какой запрос выполняется в профайлере во время открытия датасета.
Тут посложнее))
Не подскажете как в MS SQL2005 найти Profiler?
Если у Вас не Express, а более полная версия, то он находится в меню Tools->SQL Server Profiler. Если Express, то бесплатный профайлер, говорили, можно здесь скачать: http://sqlprofiler.googlepages.com/
Олег Лабьяк,
разработчик,
3-я линия Службы поддержки Terrasoft.