Как в событие DatasetBeforePost прервать отправку данных на вставку, без сообщений об ошибках. Может ключ в DataSet можно поменять?

Нравится

2 комментария
DoPost.Value = false;

Спасибо. Завтра, протестирую. Интуитивно пробовал так: DoPost= false, не посмотрел на объект в режиме дебага.

Показать все комментарии
Grid
Скрипты
Разработка

Подскажите, пожалуйста:
есть у меня грид в состоянии IsEditable = true
есть колонки которые можно править.
как можно сделать, чтоб в зависимости от поля в строке запрещать или разрешать редактирование?

Нравится

2 комментария
Отчёты
Разработка

Хочу создать отчет на основе таблицы tbl_OfferingPriceLog. Для этого создаю новый Запрос в Запросах, но при выборе главной таблицы в Запросах такой таблицы (tbl_OfferingPriceLog) нет.
Каким образом таблицы добавляются в Запросы. И можно ли туда добавить Представления?

Нравится

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

Alex, пользовательские запросы можно формировать по всем таблицам кроме системных: таблиц логирования (таблицы, которые заканчиваются на Log), таблиц прав доступа (таблицы, которые заканчиваются на Right), таблиц поиска дублей (таблицы, которые заканчиваются на FD).
Ограничение включается через применение фильтра в функции wnd_SelectReportTableOnPrepare сервиса wnd_SelectReportTableScript.
А именно, таким образом:

EnableDatasetFilters(dlData.Dataset, true, 
			'NotRightsTableEx', 'NotLogTableEx', 'ServiceTypeCode');

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

Подскажите, как правильно и в какой последовательности создать сервис таблицы на основе представления, чтобы потом создать Запрос для Отчета.
Я делал так:
1. В БД на основании таблицы tbl_OfferingPriceLog создал представление view_OfferingPriceL.
2. В TSAdmin создаю новый сервис Table. Сохраняю его с именем view_OfferingPriceL (как Вы и говорили, названия должны быть одинаковыми), но сохранять не дает - "Объект с таким именем уже существует".

(Нужно ли ещё для такого Отчета создавать ds и sq?)

Update: Прикрепил пример Отчета, который хочу создать. Возможно есть другие пути создания такого типа Отчетов или может есть шаблоны таких Отчетов?

Alex, Вы все делаете правильно, только когда нажимаете "Сохранить" на предложение системы "обновить структуру таблицы в базе данных" нужно ответить "Нет".

Сервисы ds и sq можно не создавать.

Шаблона приложенного Вами отчета, к сожалению, нет. Реализовать отчет Вы можете как через пользовательский отчет MS Excel, так и через отчет формата FastReport.

Наталия, создал запрос, создал на основе него свой первый отчет (Excel), все работает.
Единственное не могу добиться в запросе, чтобы данные выстраивались по схеме мастер-детэил.
Т.е. сверху ID Продукта, внизу все его изменения. У меня сейчас получилось вверху все ID (все записи), внизу изменение одной (выбранной) записи.
Возможно ли это сделать средствами конфигуратора запросов? Или как-то по другому?
(Представление стандартное:

SELECT   ...
FROM         dbo.tbl_OfferingPriceLog AS tbl_OfferingPriceLog LEFT OUTER JOIN
                      dbo.tbl_Contact AS CreatedBy ON CreatedBy.ID = tbl_OfferingPriceLog.CreatedByID
ORDER BY tbl_OfferingPriceLog.CreatedOn DESC

)

Чтобы данные выстраивались по схеме мастер-детэил достаточно добавить подчиненную деталь по отношению к главной (скриншот прилагаю).

После просмотра вебинара сделал Запрос для Отчета немного по другому:
Master - Таблица tbl_Offering, Detail - таблица вTS на основе представления view_OfferingPriceL.
В MSAdmin в Таблице view_OfferingPriceL создаю связь: Первичный ключ tbl_Offering.ID, вторичный ключ view_OfferingPriceL.OfferingID (связь продукта с изменением). Т.е. выбирая продукт, мы должны получить его изменения.
Иду в Запросы, выбираю главную таблицу tbl_Offering, поле Название.
Добавляю вторую деталь и разворачиваю "Обратные связи", чтобы там найти view_OfferingPriceL и добавить оттуда поля в Деталь2. Но в "Обратные связи" view_OfferingPriceL нету.
Как эту таблицу туда добавить? // И правильный ли у меня алгоритм для этого Отчета?

Alex, выполнила те же действия - таблица в обратных связях появилась.
Вы перезапускали приложение после внесения изменений?

Наталия, а у Вас tbl_OfferingPriceLog - это представление в базе? У меня это представление.
Все перегружал, в связях не появляется.
Может я что-то упустил в настройках?

"Alex GF" написал:Наталия, а у Вас tbl_OfferingPriceLog - это представление в базе?

Нет, таблица.
Завтра проверю с представлением и напишу.

Alex, представления не будут попадать в обратные связи, так как список объектов для обратных связей формируется из БД (а не по внешним связям сервисов).
Если требуется использовать именно представления для формирования отчетов master - detail, нужно будет создать отчет формата FastReport.

Показать все комментарии
Скрипты
Разработка

Каким образом можно получить и в зависимости от полученного значения передать другое значение в LookupDataControl?
Для примера: На карточке "Контакт" есть поле с выпадающим списком "Средства связи". В нем значения: Мобильный, Телефон, Факс, Личный и т.п.
Каким образом сделать так, чтобы при выборе значения "Личный" выдавалось предупреждение, к примеру "Личным" пользоваться запрещено"!!! и значение в LookupDataControl'е с "Личного" менялось на к примеру "Телефон".
Выбираю так

var Name = DataField.Name;
var Dataset = DataField.ParentDataFields.ParentDataset;
if (Name == 'ID') {
var Value = DataField.Value;
if (Value == '{5C0A-4C2D-8684}'/*Личный*/){
ShowWarningDialog('Личным пользоваться запрещено!!!');
// Здесь как перевести в выборе с Личного на Телефон

А вот как с "Личного" поменять на "Телефон"?

Нравится

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

Меняйте не значение поля, а значение датасета

dlData.Dataset('Communication1TypeID') = 'id нужного типа';

Используйте событие OnDatasetDataChange невизуального компонента dlData:

if(DataField.Name == 'Communication1TypeID') {
     if(DataField.Value == 'some_id') {
            DataField.Value = DataField.OldValue;
            ShowErrorDialog('ERROR!');
     }
}

Все идентификаторы желательно выносить в scr_Consts, и затем писать так:
if(DataField.Name == myComTypeConst)

ps: желательно просто отфильтровать источник данных, чтобы в списке просто не отображались те варианты, которые выбрать нельзя. Так корректней согласитесь.

Спасибо, за варианты, все работает. Единственное, после нажатия ОК на ShowErrorDialog это диалоговое окно открывается повторно и после второго его закрытия в LookupDataControl'е изменяется значение на OldValue и можно закрыть карточку Контакта. Как можно сделать, чтобы окно ShowErrorDialog открывалось только 1 раз?
Для дальнейшего изучения Террасофта немного усложнил эту задачу:
ShowErrorDialog открывается в зависимости не только от some_id, но и от условий, данные которых находятся в Деталях.
Пример: У Контакта есть в Деталях Счета, у Счетов есть поле "Состояние оплаты".
В зависимости от:
при выборе значения "Личный" в карточке Контакта и если в поле "Состояние оплаты" Счетов этого Контакта, к примеру, есть значения "Не оплачен" запрещаем менять значение ("Личный") в нашем предыдущем примере:

if(DataField.Name == 'Communication1TypeID') {
     if(DataField.Value == 'some_id') && /*Состояние оплаты Счетов == 'Не оплачен'*/ {
            DataField.Value = DataField.OldValue;
            ShowErrorDialog('ERROR!');
     }
}

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

По поводу двойного входа в условие, при установлении старого значения, проще всего отключить события датасета:

var Dataset = DataField.ParentDataFields.ParentDataset;
if(DataField.Name == 'Communication1TypeID') {
     if(DataField.Value == 'some_id') && /*Состояние оплаты Счетов == 'Не оплачен'*/ {
            Dataset.DisableEvents();
            DataField.Value = DataField.OldValue;
            Dataset.EnableEvents();
            ShowErrorDialog('ERROR!');
     }
}

Вариант обхода двойного открытия окна с отключением эвентов

            Dataset.DisableEvents();
            DataField.Value = DataField.OldValue;
            Dataset.EnableEvents();

не проходит. Все равно два раза вызывается диалоговое окно.

Скорее всего у Вас в скрипте условие прописано дважды или выполняется в каком-то цикле.

Прикрепите, пожалуйста, к посту весь скрипт (экспортируйте его из конфигурации).

По поводу Вашего вопроса с модификацией условия:

if (DataField.Name == 'Communication1TypeID') {   
	var bool = false;
	var ContactID = Dataset.Values('ID');
	var InvoiceDataset = Services.GetNewItemByUSI('ds_Invoice');
	ApplyDatasetFilter(InvoiceDataset, 'ContactID', ContactID, true); 
   	InvoiceDataset.Open(); 
  	if (InvoiceDataset.Values('BillStatusID')=='{89E2E62C-E2B0-47E6-A183-B774ED20CDE8}') //если по Контакту есть счет с состоянием оплаты = Ожидание оплаты
        {
            bool = true;
  	}
   	InvoiceDataset.Close(); 
	if((DataField.Value == '{FA08FC2A-9D55-40C9-9576-0017EAED3E49}')&&(bool==true)) {
              ShowErrorDialog('ERROR!');
     	}	
	return;
}

Андрей, в твоем примере проверится только первый счет, а их может быть несколько :)
Лучше всего, конечно, это создать новый сервис sq_MySelectQuery (сервис выборки данных с определенной таблицы), в котором добавить фильтр сравнения по ContactID с параметром ContactID и по StatusID с параметром StatusID, оба фильтра сразу же включить в сервисе. Из таблицы выбирать только одну колонку, к примеру ID. Затем в коде прописать что-то вроде следующего:

var ContactID = Dataset('ContactID');
var StatusID = isWaiting; //isWaiting - это константа в scr_Consts
//var isWaiting = '{id_состояния_оплаты_счета_в_ожидании}';
var mySQ = Services.GetNewItemByUSI('sq_MySelectQuery');
SetParameterValue(mySQ.Parameters, 'ContactID', ContactID, true);
SetParameterValue(mySQ.Parameters, 'StatusID', StatusID, true);
var Result = mySQ.Open();
if(Result.IsEOF) {
     ShowWarningDialog('Для тек. контакта счетов в состоянии "Ожидание оплаты" нет');
} else {
     ShowWarningDialog('Для тек. контакта есть счета в состоянии "Ожидание оплаты"! Их количество: ' + Result.RecordsCount);     
}

А вот по поводу двойного входа сюда:

if(DataField.Name == 'Communication1TypeID') {
     if(DataField.Value == 'some_id') {
            DataField.Value = DataField.OldValue;
            ShowErrorDialog('ERROR!');
     }
}

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

if(DataField.Value == 'some_id')

т.е. по сути - второй раз мы не должны зайти внутрь условия:

if(DataField.Value == 'some_id') {
            DataField.Value = DataField.OldValue;
            ShowErrorDialog('ERROR!');
     }

, т.к. мы изменили это значение на другое. Но раз заходит, значит что-то пошло не так. Тут нужна отладка - поставьте перед условием отладчик (Ctrl+F5), включите в реестре Windows регистр JitDebug в 1 и перезапустите Террасофт. Для отладки нужна Visual Studio (либо MS Script Debugger, но он крайне неудобен).

Если что - пишите.

Кажется Вам поможет следующая конструкция:

1. В самом начале скрипта объявите глобальную переменную-объект. Чаще всего её называют по имени сервиса. Она может быть у Вас уже и объявлена (если это коробочный датасет):

var myObject = {};

2. Структуру события OnDatasetDataChange нужно сделать следующей:

function SelfOnDatasetDataChange(DataField) {
try {
   if(myObject.IsUpdating) {
         return;
   }
   myObject.IsUpdating = true;
   if(DataField.Name == 'Name') {
         //ваш код
   }
   //....
} finally {
   myObject.IsUpdating = false;   
}
}

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

Так должно работать:

if (DataField.Name == 'Communication1TypeID') {   
	var bool = false;
	var ContactID = Dataset.Values('ID');
	var InvoiceDataset = Services.GetNewItemByUSI('ds_Invoice');
	ApplyDatasetFilter(InvoiceDataset, 'ContactID', ContactID, true);
	InvoiceDataset.Open(); 
   	while(!InvoiceDataset.IsEOF) {
		  if (InvoiceDataset.Values('BillStatusID')=='{89E2E62C-E2B0-47E6-A183-B774ED20CDE8}')
  		       {
  			    bool = true; 
  	               }
		  InvoiceDataset.GotoNext();
	 }
   	InvoiceDataset.Close(); 
	if((DataField.Value == '{FA08FC2A-9D55-40C9-9576-0017EAED3E49}')&&(bool==true)) {
	       ShowErrorDialog('ERROR!');
     	}	
	return;
}

Спасибо, Дмитрий, Андрей!
Вот код, который отлично работает, за исключением пресловутого двойного открытия диалогового окна:

function dlDataOnDatasetDataChange(DataField) {
   if (System.GetLocalComputerName() == 'MYCOMP') { debugger; }   
   if(ContactEdit.IsUpdating) { 
         return;
   };
   var Dataset = DataField.ParentDataFields.ParentDataset;   
       ContactEdit.IsUpdating = true;
try {  
    var Communication1TypeName = dlData.Dataset.DisplayValues('Communication1TypeID'); 
    if (DataField.Name == 'Communication1TypeID') {   
        var bool = false;
        var ContactID = Dataset.Values('ID');
        var InvoiceDataset = Services.GetNewItemByUSI('ds_Invoice');
        ApplyDatasetFilter(InvoiceDataset, 'ContactID', ContactID, true);
        InvoiceDataset.Open();
        while(!InvoiceDataset.IsEOF) {
                  if (InvoiceDataset.Values('BillStatusID')=='{89E2E62C-E2B0-47E6-A183-B774ED20CDE8}')     //Ожидание оплаты
                       {
                            bool = true; 
                       }
                  InvoiceDataset.GotoNext();
         }
        InvoiceDataset.Close();
        if((DataField.Value == '{63153BB8-52E0-468A-8DDA-1EFD4B959780}')&&(bool==true)) { //Личный
               DataField.Value = DataField.OldValue;
	       ShowErrorDialog('Внимание! В Контакте есть счета на стадии "Ожидание оплаты"!\r\n\Пользоваться ' + Communication1TypeName + ' запрещено!');
        }       
        return;
      }
    }
     finally {
       ContactEdit.IsUpdating = false;   
   }
}

На основе дебаггера удалось выяснить, что после того как выбрали "Личный" открывается ДО (Диалоговое окно) первый раз.
После закрытия окна в LookupControl'e "Личный меняется" на OldValue.
Затем OldValue опять меняется на "Личный" и ДО открывается второй раз.
После второго раза закрытия ДО "Личный" меняется на OldValue.
После этого процесс завершается и можно закрыть карточку Контакта.
Между этими двумя открытиями дебаггер заходит в scr_Contact в
function SelfOnDatasetDataChange(DataField). Но не только сюда.
Это из основного что удалось проанализировать, но механизма, чтобы открывалось только 1 раз ДО не нашел.

Alex GF,

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

Нужно ставить доп. условие. Посмотрите значения Value и OldValue перед каждым вызовом ДО - они у Вас должны отличаться. И затем дополните условие, что то вроде

DataField.OldValue != DataField.Value

Если не выйдет, напишите значения OldValue и Value перед каждым вызовом ДО.

Значение перед вызовом ДОкна:
Value - 'Личный'
OldValue - 'Мобильный'
После первого вызова ДОкна:
Value - 'Мобильный'
OldValue - 'Мобильный'

Затем уходит на второй круг и возвращается к нашему debbuger:
Value - 'Личный'
OldValue - 'Мобильный'
После 2-го вызова ДОкна:
Value - 'Мобильный'
OldValue - 'Мобильный'

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

if((DataField.Value == '{63153BB8-52E0-468A-8DDA-1EFD4B959780}')&&(bool==true)) { //Личный
debugger;
DataField.Value = DataField.OldValue;

И вот прямо в месте остановки, посмотрите DataField.Value и DataField.OldValue, и запостите сюда еще раз пожалуйста. Т.е. должно быть только две остановки, соответственно два значения.

В момент остановки
Value = 'Личный'
OldValue = 'Мобильный'

Далее, в момент открытия ДО
Value = 'Мобильный'
OldValue = 'Мобильный'

После закрытия ДО
Value = 'Личный'
OldValue = 'Мобильный'

Заходим второй раз в нашу функцию, значения теже, выходим из нашей функции делаем цикл, опять заходим в нашу функцию, значения теже.
Проходим циклом по while(!InvoiceDataset.IsEOF), далее по функции, далее открывается второй раз Диалоговое Окно.
Value = 'Мобильный'
OldValue = 'Мобильный'

P.S. Версия Террасофт 3.3.2

Что-то странное. Не смог воспроизвести. Кажется, виноват return, выделенный жирным.

InvoiceDataset.Close();
if((DataField.Value == '{63153BB8-52E0-468A-8DDA-1EFD4B959780}')&&(bool==true)) { //Личный
DataField.Value = DataField.OldValue;
ShowErrorDialog('Внимание! В Контакте есть счета на стадии "Ожидание оплаты"!\r\n\Пользоваться ' + Communication1TypeName + ' запрещено!');
}
return;
}
}
finally {
ContactEdit.IsUpdating = false;
}
}

Если нет - ставьте заглушку... После первого показа окна установите значение в свойство глобального объекта, к примеру:

if(!ContactEdit.WindowWasShowed) {
 ShowErrorDialog('Внимание! В Контакте есть счета на стадии "Ожидание оплаты"!\r\n\Пользоваться ' + Communication1TypeName + ' запрещено!'); 
}
ContactEdit.WindowWasShowed = true;

И где-то на OnPrepare Еще добавьте строку:

ContactEdit.WindowWasShowed = false;

Спасибо Дмитрий, помогла только заглушка!

Проделал тоже самое (тот же самый код, но без заглушки) на версии террасофт 3.5.1. Там двойного открытия Диалогового окна нет! Единственный неопределенный (для меня) момент там:
После закрытия Диалогового Окна в LookupDataControl значение Value не меняется на OldValue. Хотя затем при нажатии на карточке "ОК" результат в базе правильный - OldValue.
В версии 3.3.2 в LookupDataControl значения меняются как надо.

Показать все комментарии
администрирование
Установка и Администрирование
Разработка

Здравствуйте!
Можно ли сделать администрирование по записям для справочника в версии 3.2. Я пытался сделать для одного из своих справочников - не удалось. Выставил флаг "Администрирование по записям", занес права пользователей, но доступ пользователей к записям справочника стал невозможен несмотря на выставленные права, пока не убрал администрирование по записям, да и убрать удалось далеко не с первой попытки.

Нравится

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

Добрый день!

Во вложении находится руководство по настройке прав доступа на справочники.prava_dostupa_na_otdelnye_spravochniki.doc

Спасибо! Вопрос снят. Новую группу создавать не нужно, можно выставить права на группу "Справочники". Чтобы правами можно было управлять пришлось создать подобие раздела для справочника.

Показать все комментарии
Скрипты
Разработка

BaseGridArea не видит dlData

function wnd_BaseGridAreaOnPrepare(Window) {
        InitializeGridArea(Window, BaseGridArea, dlData); //ВОТ ТУТ
        InitializeGridAreaHotKeyList(Window);
}

хотя

Window.ComponentsByName('dlData')

видит его.

Что-то нужно прописать для создаваемого грида?

Нравится

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

продолжение истории, там же в scr_BaseGridArea не видно Self

function btnAddOnClick(Control) {
	AddGridAreaData(Self, Self, BaseGridArea);
}

Здравствуйте, Alex!
Не совсем понятно, что Вы делаете. Проверьте, унаследовано ли Ваше окно от wnd_BaseGridArea.
Вообще, необходимо добавлять обработчик события OnPrepare для своего окна, в котором вызывать базовый и инициализировать другие параметры окна:

function wnd_AccountsGridAreaOnPrepare(Window) {
	wnd_BaseGridAreaOnPrepare(Window);
	Initialize(Window);
 
}

"Андрей Каспаревич" написал:Проверьте, унаследовано ли Ваше окно от wnd_BaseGridArea.

Андрей, а как проверить?

У окна свойство

TemplateWindowUSI = wnd_BaseGridArea

OnPrepare для окна именно так и написал:

wnd_BaseGridAreaOnPrepare(Window);

и зайдя внутрь появляется ошибка dlData, при этом и BaseGridArea "чистый" объект!

Проблема закрыта. Спасибо.
зачем-то добавил в INCLUDE scr_BaseGridArea!

Показать все комментарии
Скрипты
Разработка

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

Подскажите в таком вопросе.
Есть функция,

function OneRecord(MyDataset ) {
...//Выполняем вычисления
...//Вставляем записи в Detail
}

которая в зависимости от вычислений делает обновления и добавляет новые записи в разные Детали.
Вызываем её на строке грида
function aOneRecordOnExecute(ActionMenuItem, Sender) {
        var MyDataset = dlData.Dataset;
        OneRecord(MyDataset );     
}

Все работает на данной выделенной строке.
А каким образом можно выделив более одной строки в гриде, заставить эту функцию отработать все выделенные строки? Пока она это делать не может.

Нравится

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

Выделить больше одной строки можно с помощью клавиш Ctrl и Shift
Ctrl - выбирает только те строки, которые вы щелкаете при нажатой клавише (так же Ctrl выполняет функцию "Перейти к", если щелкните на поле типа Lookup. Так что будьте осторожны)
Shift - выделит все строки между текущей выделенной и той, которую вы щелкните.
Функцию попробуйте переписать так:

function aOneRecordOnExecute(ActionMenuItem, Sender) {
	var SelectedIDs = grdData.SelectedIDs.CommaText.split(',');
	var MyDataset = Services.GetNEwItemByUSI(dlData.Dataset.USI);
	for(var i=0;i<SelectedIDs.length;++i) {
		MyDataset.Close();
		ApplyDatasetFilter(MyDataset, 'ID', SelectedIDs[i], true);
		MyDataset.Open();
		OneRecord(MyDataset);
	}     
}

Переделал функцию по вышеописанному способу: при отработке дебаггер пишет "grdData - Определение отсутствует". Насколько я понял не может достучаться до грида.
Функция находится в отдельном скрипте scr_OneRecord.
wnd_OneRecord, в котором находится грид лежит рядом. Как достучаться до grdData?
Пробовал так:

var wndOneRecord= Services.GetNewItemByUSI('wnd_OneRecord');
var SelectedIDs = wndOneRecord.grdData.SelectedIDs.CommaText.split(',');

Но в этом случае выдает ошибку: " 'grdData.SelectedIDs' - есть null или не является объектом".

Не понимаю, в своем варианте вы берете dlData, значит достукиваетесь до элементов окна. Проверьте, может они по другому у вас названы. Если же нет, то должен помочь этот скрипт (если все окна унаследованы от базовых):

function aOneRecordOnExecute(ActionMenuItem, Sender) {
	var MainWindow = Connector.Attributes('MainWindow');
	var WorkspaceWindow = MainWindow.ComponentsByName('wndWorkspace').Window;
	var GridWindow = WorkspaceWindow.ComponentsByName('wndGridData').Window;
	var grdData = GridWindow.ComponentsByName('grdData');
	//var dlData = GridWindow.ComponentsByName('dlData'); //если нельзя будет достучаться до dlData
        var SelectedIDs = grdData.SelectedIDs.CommaText.split(',');
        var MyDataset = Services.GetNewItemByUSI(dlData.Dataset.USI);
        for(var i=0;i<SelectedIDs.length;++i) {
                MyDataset.Close();
                ApplyDatasetFilter(MyDataset, 'ID', SelectedIDs[i], true);
                MyDataset.Open();
                OneRecord(MyDataset);
        }     
}

Выполняю действие (меняю статус) для выделенных строк грида Накладных:

	var SelectedIDs = grdData.SelectedIDs.CommaText.split(',');
 
          var Dataset = dlData.Dataset; 
        for(var i=0;i<SelectedIDs.length;++i) {
            Dataset.Close();
            ApplyDatasetFilter(Dataset, 'ID', SelectedIDs[i], true);
            Dataset.Open();
 
	var GotNoError = true;
 
	with (Dataset) {
		try {	
			DisableEvents();
			Edit();
 
			Values(FieldName) = ToValue;	//Set a new value
 
			Post();
		} catch (err) {
			GotNoError = false;
			if (State == dstEdit) {	//Rollback if still in Edit state
				Cancel();
			}
		} finally {
			EnableEvents();
		}
	}
	}

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

Возможно не сбрасывается старый фильтр, попробуйте:

Dataset.Close();
EnableDatasetFilters(Dataset, false);
ApplyDatasetFilter(Dataset, 'ID', SelectedIDs[i], true);

И кстати, лучше создайте новый экземляр датасета, а не тот, который сейчас привязан к гриду.

Никакие манипуляции с фильтрами не помогли.
Помогло, когда вместо

 var Dataset = dlData.Dataset; 

стал использовать

 var Dataset = Services.GetNewItemByUSI('ds_OfferingMovement')
Показать все комментарии

Добрый день коллеги!
Продолжаю создавать свой первый раздел в Terrasoft
Теперь после создания Раздела и Реестра
дошло дело до Карточки редактирования
в принцbпе карточку создал унаследовал от wnd_BaseDBEdit
добавление записи получается, а вот с редактированием не могу разобраться(((
окно появляется но компоненты без данных,
Пробовал так
scr_BaseGridArea.EditGridAreaData(Self, BaseGridArea); этот код результата не дает

с этим тоже не получается

var Attributes = new ActiveXObject('Scripting.Dictionary');
var RecordID = Attributes.Add(RecordID, 'ID');
ShowEditWindowEx('wnd_LisingEdit', Attributes);

Может быть есть простой пример кода карточки редактирования с описание основных действий
при нажатии на кнопку Изменить в Реестре (wnd_BaseGridArea)
Буду очень признателен.

Нравится

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

нашел вот такой код

{
var EditWindowUSI = 'wnd_LisingEdit';
var AccountID = dlData.Dataset.Values('ID');
var Attributes = GetNewDictionary();
Attributes.Add('RecordID', AccountID);
Attributes.Add('NotifyObject', null);
ShowEditWindowEx(EditWindowUSI, Attributes);
}

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

Здравствуйте, Евгений.

Проверьте, пожалуйста, установлено ли у Вашего грида свойство TemplateWindowUSI = wnd_BaseGridArea?

"Безродный Андрей" написал:

Здравствуйте, Евгений.

Проверьте, пожалуйста, установлено ли у Вашего грида свойство TemplateWindowUSI = wnd_BaseGridArea?

да установлено

Евгений,

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

прошу приложить сервисы созданного Вами раздела, реестра и карточки редактирования, а также сообщить используемую Вами версию Terrasoft.

Андрей прикладываю созданные сервисы раздела
версия 3.3.2.294

"Безродный Андрей" написал:версия 3.3.2.294

версия 3.3.2.294

Евгений,

приложите также сервисы tbl_District, sq_District, ds_Disctrict.

Без этих сервисов не удается загрузить tbl_lising_article

"Безродный Андрей" написал:

Евгений,

приложите также сервисы tbl_District, sq_District, ds_Disctrict.

Без этих сервисов не удается загрузить tbl_lising_article

прикладываю сервисы

Евгений,

причина, вероятно, в том, что у Вас в сервисе запроса нет фильтра сравнения с параметром:

[URL=http://fastpic.ru/][IMG]http://i68.fastpic.ru/big/2014/0814/b8/819214ad…]

[URL=http://fastpic.ru/][IMG]http://i65.fastpic.ru/big/2014/0814/49/754f3462…]

Спасибо Вам!
Действительно установил фильтр и карточка работает.
Видимо при создании раздела вручную не все предусмотрел.

Андрей добрый день!
у меня еще вопрос есть. Теперь по поводу работы с полями,
каким образом можно сделать чтобы при выборе значения в LookupDaatControl
допустим Наименование клиента
в другой компонент TextDataControl выводилось значение его ИИН
Во первых не нашел у LookupDaatControl события OnChange к тому же на начальном уровне не совсем
еще овладел синтаксисом Jscript
Буду очень благодарен за помощь!

Здравствуйте, Евгений!

Вашу задачу лучше реализовать на событии OnDatasetDataChange датасета карточки, в которой содержится LookupDataControl.

http://i68.fastpic.ru/big/2014/0815/90/4a5e50285a3e1d88737e763ae33efb90.jpg

На примере ниже при выборе Контрагента в карточке Задачи в поле Заголовок задачи будет помещаться полное название выбираемого Контрагента. По аналогии Вы сможете реализовать свой функционал.

function SelfOnDatasetDataChange(DataField) {
...
if (Name == 'AccountID') { //при изменении поля AccountID в датасете задач
    var AccountID = DataField.Value; //получаем ID выбранного контрагента
    var AccountDataset = Services.GetNewItemByUSI('ds_Account'); //получаем датасет контрагентов
    ApplyDatasetFilter(AccountDataset, 'ID', AccountID, true); //фильтруем датасет по ID выбранного контрагента
    AccountDataset.Open(); //открываем датасет
    var INN = AccountDataset.Values('OfficialAccountName'); //получаем нужное значение нового контрагента
    AccountDataset.Close(); //закрываем датасет
    Dataset.Values('Title') = INN; //присваиваем полученное значение в одно из полей текущего датасета задач
    return;
}
...
}

Реализация.

У контрагента Оливия-Фарм есть полное название:

http://i65.fastpic.ru/big/2014/0815/37/4039f6e7b85da705f5278109ea3fff37.jpg

При выборе Контрагента в карточке Задачи полное название Контрагента подставляется в заголовок:

http://i65.fastpic.ru/big/2014/0815/e1/d18b615bdbba1a28275418540441fde1.jpg

"Безродный Андрей" написал:Здравствуйте, Евгений!

Вашу задачу лучше реализовать на событии OnDatasetDataChange датасета карточки, в которой содержится LookupDataControl.

Андрей добрый день
Сделал у себя все как вы рекомендовали , по примеру,
но у меня выходит ошибка((.
Скрин ошибки прилагаю.

Евгений,

а Вы уверены, что поле Контрагент в Вашем датасете "Предметы Лизинга" называется AccountID?

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

"Безродный Андрей" написал:

Евгений,

а Вы уверены, что поле Контрагент в Вашем датасете "Предметы Лизинга" называется AccountID?

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

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

if (Name == 'BorrowerId') { //при изменении поля AccountID в датасете задач
var AccountID = DataField.Value; //получаем ID выбранного контрагента
var AccountDataset = Services.GetNewItemByUSI('ds_Account'); //получаем датасет контрагентов
ApplyDatasetFilter(AccountDataset, 'ID', AccountID, true); //фильтруем датасет по ID выбранного контрагента
AccountDataset.Open(); //открываем датасет
var INN = AccountDataset.Values('Code'); //получаем нужное значение нового контрагента
AccountDataset.Close(); //закрываем датасет
dlData.Dataset.Values('BIN') = AccountID //'INN34324'; //присваиваем полученное значение в одно из полей текущего датасета задач
return;

Евгений,

смотрите детали ошибки и поставьте отладчик:
http://www.microsoft.com/ru-ru/download/details.aspx?id=40787

После установки установите значение параметра JITDebug в реестре равным 1 (параметр находится по пути:
HKEY_CURRENT_USER\Software\Microsoft\Windows Script\Settings)

При возникновении ошибки будет сразу понятно, на каком участке кода происходит свал.

Евгений, почему Вы в итоге присваиваете значению поля BIN AccountId?
Возможно, необходимо присваивать INN?

var INN = AccountDataset.Values('Code'); //получаем нужное значение нового контрагента
AccountDataset.Close(); //закрываем датасет
dlData.Dataset.Values('BIN') = AccountID //'INN34324'; //присваиваем полученное значение в одно

Также,

Вы уверены, что в датасете контрагентов у Вас присутствует поле Code?
AccountDataset.Values('Code')

"Безродный Андрей" написал:

Вы уверены, что в датасете контрагентов у Вас присутствует поле Code?

AccountDataset.Values('Code')

Андрей я тут уже пробовал присвоить хоть какое то значение этому полю)
даже просто делал строку dlData.Dataset.Values('BIN')= 'vdfsxvdf' все равно ошибка
Поле которое меня интересует точно Code

сейчас заметил что ошибка выходит именно вот когда выполняется эта строка

Dataset.Values('BIN') =INN; //присваиваем полученное значение в одно из полей текущего атасета задач

т е если ее за комментировать то ошибки нет
тип полей совпадают

Евгений,

Вы поставите отладчик?

Устанавливал Vstudiо затем установил Micrisoft Debuger с сайта скачивал отсюда,
но он не заработал, теперь в итоге нет отладчика- Vstudio тоже перестал работать

Евгений, выполните описанные мною Ваше изменения в реестре для корректной работы отладчика:
http://www.community.terrasoft.ru/forum/topic/10836#comment-49104

"Безродный Андрей" написал:

Евгений, выполните описанные мною Ваше изменения в реестре для корректной работы отладчика:

http://www.community.terrasoft.ru/forum/topic/10836#comment-49104

вот что показывает отладчик

Евгений,

в самом начале скрипта пропишите:

function SelfOnDatasetDataChange(DataField) {
if (DataField == null) {
		return;
}
var Dataset = DataField.ParentDataFields.ParentDataset;
var Name = DataField.Name;
.....

Спасибо Большое за терпение и за помощь!!
Теперь все работает!)

Показать все комментарии
Скрипты
Разработка

Добрый день
По чему при открытие не отображаются данные в гриде, таблица в базе заполнена
вызываю родительский метод
function wnd_LisingGridAreaOnPrepare(Window) {
// Initialize(Window);
wnd_BaseGridAreaOnPrepare(Window);
// dldata.Dataset.Open() ;

}

пробовал команду
dldata.Dataset.Open() ;
тоже выходит ошибка та же самая.

либо выдается ошибка что Dldata не определен
хотя в свойствах в в неdизуальных компонентах указано Ds_lising

Нравится

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

Здравствуйте, Евгений!

Проверьте, пожалуйста, корректно ли определена функция function Initialize(Window). Примеры можно посмотреть в конфигурации.

"Резниченко Сергей" написал:

Здравствуйте, Евгений!

Проверьте, пожалуйста, корректно ли определена функция function Initialize(Window). Примеры можно посмотреть в конфигурации.

С уважением,

Резниченко Сергей

Специалист 2-й линии поддержки

вот описакние

function Initialize(Window) {
Window.Attributes('EditWindowUSI') = 'wnd_LisingEdit';
}

function Initialize(Window) {

SetAttribute(Window, 'DatasetUSI', 'ds_lising');
SetAttribute(Window, 'EditWindowUSI', 'wnd_LisingEdit');

}

function wnd_LisingGridAreaOnPrepare(Window) {
Initialize(Window);
wnd_BaseGridAreaOnPrepare(Window);

}

Так а у Вас точно dlData невизуальный компонент называется?
И окно унаследовано от wnd_BaseGridArea?

"Олейник Дмитрий" написал:

Так а у Вас точно dlData невизуальный компонент называется?

И окно унаследовано от wnd_BaseGridArea?

С уважением,

Олейник Дмитрий

да точно
ниже
прилагаю скрин шот скрипта

Евгений, попробуйте заменить
wnd_BaseGridAreaOnPrepare(Window); на scr_BaseGridArea.wnd_BaseGridAreaOnPrepare(Window);

Если не выйдет сделайте явное открытие датасета:

dlData.Dataset.Open();

PS: ошибка у вас связана с тем, что язык - регистро-чувствительный, и dldata и dlData - разные вещи.

Добрый день
Спасибо проблема решилась, только при помощи явного открытия
dlData.Dataset.Open();

Показать все комментарии
Протоколирование
Установка и Администрирование
Разработка

Здравствуйте!
Существует ли возможность отслеживания входов в Террасофт?

Нравится

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

В 5.X точно есть, в 3.X не нашёл, но теоретически сделать можно.

Есть тулы, которые умеют отслеживать подключения к серверу. ActivityMonitor, наверное подойдет.

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

Табличка, запрос и набор данных:

Код в scr_Main:

Что делают функции DatasetTriggers.Load() и SetServicesEvents()? Где они описаны? В wnd_MainOnPrepare обращения к этим функциям нет.

Здравствуйте, Владимир.

Функция DatasetTriggers.Load() описана в подключенном к scr_Main скрипте scr_DatasetTriggers.

Данная функция необходима для автоматического запуска процессов в Terrasoft.

SetServicesEvents() описана в scr_Main.

Кстати, реализация Вашей задачи уже описана в теме:
http://www.community.terrasoft.ru/blogs/4671

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