Реализовать запрет на изменение просроченных задач несложно - достаточно программно отключать кнопку Ok в окне редактирования задачи, если задача просрочена. Однако как можно препятствовать перетягиванию задач в расписании?

Для этого следует отлавливать события

1) OnBeforeDragEvent
2) OnAfterDragEvent
3) OnBeforeSizingEvent
4) OnAfterSizingEvent

Они появились начиная со сборки 227 версии 3.3.2.

Откройте Terrasoft Administrator и найдите wnd_SchedulerArea
Для реализации запрета перетаскивания задач необходимо создать событие ScheduleControlOnAfterDragEvent:

В визуальных компонентах выберите ScheduleControl, перейдите на вкладку События и создайте событие двойным кликом в соответствующем поле:
111

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

                var Dataset = SchedulerArea.EventsDataset;
                Dataset.Locate('ID', Event.ID);
                if (GetDateDiff(new Date().getVarDate(), Event.Finish, 'Minute')0){
                               DoAccept.Value = false;
                               //MessageBox("Нельзя перетаскивать просроченные задачи!");
                }

111

Сохранить скрипт scr_SchedulerArea. Сохранить карточку wnd_SchedulerArea.

В результате перетаскивание визуально будет происходить, однако сроки меняться не будут, а задача после перетаскивания будет возвращаться на прежнее место. Можно добавить дополнительное сообщение-уведомление, раскомментировав строку (уберите двойной слеш //).

Для предотвращения изменения просроченных событий менеджерами необходимо также добавить аналогичный функционал на событие OnAfterSizingEvent

В результате если одна из перетаскиваемых задач не может быть перемещена, то все задачи останутся на прежних местах. Таким же образом если расширять задачу, нужно использовать обработчик OnBeforeSizingEvent или OnAfterSizingEvent

Нравится

Поделиться

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

Ой какая хорошая реализация!!!

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

Доброго времени суток, коллеги!

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

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

         var StartDate = Dataset.ValAsDateTime('StartDate');
         var DueDate = Dataset.ValAsDateTime('DueDate');
         var OwnerIDDataField = Dataset.DataFields.ItemsByName('OwnerID');  
         while(GetIsTaskCoverExists(Dataset, OwnerIDDataField.Value, StartDate,
         DueDate))
         {
              var StartDate = new Date(Dataset.ValAsDateTime('StartDate'));
              var DueDate = new Date(Dataset.ValAsDateTime('DueDate'));            
              StartDate.setHours(StartDate.getHours() + 1);
              DueDate.setHours(DueDate.getHours() + 1);
              StartDate = StartDate.getVarDate();
              DueDate = DueDate.getVarDate();
              Dataset.Values('StartDate') = StartDate;
              Dataset.Values('DueDate') = DueDate;
         }

В итоге получим примерно следующее содержимое функции обработчика события:

1

Нравится

Поделиться

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

Если есть короткое "окно", в которое всё же влезет новая задача, алгоритм может его перешагнуть и не заметить?

Да, такое возможно. Для коротких задач можно сдвигать время не на час, а к примеру, на 10 минут вперед.

Коллеги, мною данная задача была реализована запросом SQL который пригоден для использования даже в триггере.
Кроме выше описанного, он (запрос) умеет находить наименьшее окно под которое подходит задача. И все это добро может быть легко «прикручено» к расписанию каждого сотрудника в календаре (если не ошибаюсь - это уже тоже реализовано).

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

Добрый день!

Подскажите пожалуйста, как решить проблему:

Нужен отчет в Fast Report в котором записи фильтруются по диапазону дат, введенных пользователем во время запуска отчета. + Возможность запуска генерации отчета по расписанию и рассылки с автоматическим проставлением дат.

Что меня смущает и поправьте пожалуйста, если я не прав:
1) Я не могу использовать для построения отчета датасет, который базируется на запросе с параметрами. Т.к. как передать из FR параметры в запрос я не нашел. Какой выход - писать кастомный запрос в самом FR?
2) Допустим, я создам датасет, который будет выбирать все данные независимо от дат. Но когда я жму кнопку "Установить фильтры" то я не могу задать там фильтр >= и =. Вопрос - эти фильтры работают только для текстовых полей?
3) Насколько я понимаю, функционал запуска по расписанию придется решать как то так:
создавать форму, на которой ничего не будет, в обработчике OnPrepare например писать скрипт который сформирует отчет и потом разошлет пользователям а затем закроет форму. Потом в Scheduled Tasks создавать задачу, которая будет по расписанию запускать террасофт с параметром - кодом окна.

Буду благодарен за любые комментарии/решения/предложения и тем более примеры :)
Спасибо.

Нравится

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

Реализовать отчет FastReport, в котором записи фильтруются по диапазону дат Вы можете двумя способами: создать собственное окно фильтрации, в котором пользователь будет выбирать период фильтрации; использовать встроенное окно фильтрации FastReport.
В качестве примера для создания отчета с собственным окном фильтрации можно использовать отчеты "Анализ конкурентов" (fr_OpportunitiesCompetitors), "Отчет по продажам" (fr_ReportOpportunitiesSalesCycleAnalisys) с окном фильтрации wnd_ServiceDeskDateFilter. Также во вложении прилагаю для ознакомления файл, в котором описан принцип создания окна фильтрации для отчета.

"komgbu" написал:2) Допустим, я создам датасет, который будет выбирать все данные независимо от дат. Но когда я жму кнопку "Установить фильтры" то я не могу задать там фильтр >= и <=. Вопрос - эти фильтры работают только для текстовых полей?

Встроенное окно фильтрации FastReport позволяет устанавливать фильтры >= и <= для полей с типом "Дата/время", "Целое число", "Дробное число":
http://www.community.terrasoft.ru/system/files/1_12.png

Здравствуйте,
По поводу 1) и 2) вопроса, предлагаю вам почитать в теме http://www.community.terrasoft.ru/blogs/7286
если, что либо не понятно, опишу более подробно
3) Как вариант можно создать и так,
1
На сколько я понял, под Scheduled Tasks вы имеете ввиду Task Scheduler Windows'а

Наталия, Алексей, спасибо!

Да, под Scheduled Tasks я имел ввиду планировщик Windows.

Добрый день!

Не подскажете, как для кастомного окна фильтрации переопределить заголовок (не разваливая стандартный скрипт, который автоматически присваивает названия типа: "имя_сервиса (Просмотр)")?

Форма стандартной фильтрации конечно... не айс...

Спасибо!

Здравствуйте,
Скрипт scr_BaseFastReportPreviewScript

function PrepareReport(AWindow) {
	CheckAttribute(AWindow, 'Report');
	frpMain.Report = GetAttribute(AWindow, 'Report');
	var FiltersCaption = frpMain.Report.Caption + " (Фильтры)";
	var PreviewCaption = frpMain.Report.Caption + " (Просмотр)";
	frpMain.PrepareReport();
	Self.WindowCaption = PreviewCaption;
	if (IsAttributeExists(AWindow, 'ShowFilterForm'))
...

Строчка формирует название

var PreviewCaption = frpMain.Report.Caption + " (Просмотр)"; 

присваиваем значение,

Self.WindowCaption = PreviewCaption;

можете в этом моменте проверять с каким отчетом вы работаете

if (ExtractUSICodeEx(frpMain.Report.USI)=='fr_ReportContactTasks')
{
...
}

и формировать нужное вам значение заголовка окна

Алексей,

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

Еще один вопрос, если можно:

По поводу разграничения прав доступа к отчету.

1) Я так понимаю, через какие-то настройки прав определенной группе пользователей дать на отчет нельзя, и придется все реализовывать программно?

2) Если запрос отчета выбирает данные из таблиц/полей недоступных пользователю, они будут пустыми в отчете?

Спасибо!

1) Права доступа к отчету вы можете настроить в детали [Доступ]
1
где указать необходимые вам группы пользователей
2) Поля на которые нет доступа у пользователя отображается не будут

"komgbu" написал:когда я жму кнопку "Установить фильтры"

Подскажите, пожалуйста, где эта кнопка. Как подключить встроенное окно фильтрации FastReport?

Здравствуйте,
Нажатие кнопки (выделено красным) в Terrasoft Administrator, вызовет окно на которое показывает стрелка на рисунке
1

Спасибо! Выручили.

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

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

Нравится

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

Вы имеете ввиду, что нужно изменить подсветку с 9 до 18 для каждого дня по-своему? Не получится, она одна для всех. Мы создавали задачи с типом "Рабочее время", отображали их особым цветом в расписании, в реестре накладывали фильтр по умолчанию, чтобы их не было видно. При создании задач на это рабочее время в расписании будут параллельные задачи. Не очень удобно, не очень красиво, но без изменений в самом элементе управления Scheduler по-другому не получалось.

"Раловец Ольга" написал:Не очень удобно, не очень красиво, но без изменений в самом элементе управления Scheduler по-другому не получалось.

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

Средствами конфигурации нет. Возможно, в последней версии там больше возможностей для кастомизации, у меня была 3.2.

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

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

Нравится

Поделиться

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

Супер! Спасибо!

Ха, точно! Сам как то не додумался )

Вау! Спасибо! :)

А я знал, сам нашел, действительно удобно, главное в нужный день поставить выделение:smile:

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

Здравствуйте.
Хотим настроить регулярный запуск интеграции по расписанию в конце рабочего дня.
Дано:
Terrasoft XRM 3.3.2.43, в которой настроена интеграция с 1С7.7.

Как удобнее всего настроить регулярный запуск этой интеграции по расписанию?
Если я и могу запустить с помощью sheduler'а террасофт, то как стартовать саму интеграцию?
Спасибо.

Нравится

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

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

Прежде всего, не совсем понятно, что Вы имеете ввиду под sheduler Terrasoft, если имеются ввиду Задачи, то там возможности такой нет.
Начиная с версии 3.4 для таких целей можно будет использовать утилиту TSJobManagerService.

На данный момент можем предложить Вам следующие варианты:

1. Реализовать выполнение синхронизации из окна Terrasoft:
- в качестве утилиты для запуска используем некий scheduler ОС, который способен выполнить командную строку;
- в Terrasoft нужно будет реализовать окно(назовем его wnd_1CAutoSynchro), которое на подготовке будет запускать нужную интеграцию. Скрипт самого запуска будет примерно такой:
var Attributes = GetNewDictionary();
Attributes('IsMain') = true;
Attributes('IsShowError') = true;
ImportAllObject(DataflowID, Attributes); // в скрипте scr_Dataflow1CUtils
- командная строка будет выглядеть примерно так:
“[путь к terrasoft]\bin\tsclient” /wnd=wnd_1CAutoSynchro /usr=??? /pwd=??? /cfg=???
или для windows авторизации
“[путь к terrasoft]\bin\tsclient” /wnd=wnd_1CAutoSynchro /wauth=true /cfg=???
- в любом случае здесь возникает вопрос, так как в командной строке нужно будет хранить пароль, это плохо. В случае же windows-авторизации - такая проблема отпадает.

2. Реализовать вызов синхронизации из обычного js-скрипта
- из js-скрипта (обычный текстовый файл, обычно с расширением js) можно создать COM-объект подключения к Terrasoft (назовем файл Auto1CSynchro.js);
- в этом скрипте будет выполняться подключение, получение скрипта scr_Dataflow1CUtils и вызов его функции ImportAllObject с передачей нужных параметров.
- как и в первом варианте в scheduler-е операционной системы выполнять командную строку вида:
cscript “[путь к js файлу]\Auto1CSynchro.js”
cscript – стандартная команда Windows,
- вопрос с хранением пароля остается, но теперь его можно будет куда-то спрятать\зашифровать и в js-файле считывать.

Инна Безверхняя,
II линия службы поддержки Terrasoft.

Третий вариант, не дотягивает до первых двух, но может быть проще в реализации для новичков и проблемы с паролем отпадают. Для этого нужно добавить Timer и на его событие OnTimer отрабатывать необходимую синхронизацию из самого СРМ.

Если проблема с паролем критична, то можно создать маленькое приложение, на каком-нибудь C# и из него так же как и во 2ом варианте Инны использовать СОМы террасофта, ну а пароль захаркодить. Ну и запускать его все тем же ОСевым sheduler, хотя возможно лучше сделать его на автозагрузке и уже внутри по таймеру запускать синхранизацию, но думаю это не принципиально ...

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

Добрый день!

В соответствии с http://community.terrasoft.ru/forum/topic/4094 внес изменения в отображение заголовка задач в зависимости от типа задач. Для заголовка мне потребовались дополнительные поля. Их я прописал в EnableAnyQueryColumns функции Initialize скрипта scr_SchedulerArea. Всё отлично отображается и работает. НО!!! Когда в расписании зажимаешь Ctrl и копируешь Задачу (перетаскиванием), то добавленные мной поля в заголовках (на всем расписании) не отображаются (null). После нажатия Обновить расписание приходит в порядок. Подскажите, где я еще что-то не доделал?

Нравится

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

Попробуйте добавить в конец обработчика ScheduleControlOnCopyEvent строку

RefreshDataset(dlEvents.Dataset);

Спасибо, Олег, помогло.

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

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

var DataFields = Dataset.DataFields;
var StartDateDataField = DataFields.ItemsByName('StartDate');
var DueDateDataField = DataFields.ItemsByName('DueDate');
var OwnerIDDataField = DataFields.ItemsByName('OwnerID');
Dataset.Locate('ID', Event.ID);
var PriorStartDate = StartDateDataField.ValAsDateTime;
var PriorDueDate = DueDateDataField.ValAsDateTime;
if (!CheckTaskCovering(Dataset, OwnerIDDataField, Event.Start,
Event.Finish)) {
CancelChangeEvent(Event, PriorStartDate, PriorDueDate);
return;
}
Dataset.Edit();
strong>var RemindingToOwnerID = Dataset.Values('RemindingToOwnerID');
if (!IsEmptyValue(RemindingToOwnerID)) {
var uq_Remindings = GetSingleItemByCode('uq_Remindings', 'uq_RemindSingle');
var Parameters = uq_Remindings.Parameters;
var ColumnsValues = uq_Remindings.ColumnsValues;
SetParameterValue(Parameters, 'ID', RemindingToOwnerID);
ColumnsValues.ItemsByName('RemindTime').Value = Event.Start;
uq_Remindings.Execute();
}strong>
//Dataset.ValAsStr('Title') = Event.Caption;
StartDateDataField.ValAsDateTime = Event.Start;
DueDateDataField.ValAsDateTime = Event.Finish;
UpdateDuration(Dataset);
Dataset.Post();
UpdateEventColorsByDatasetRecord(Event, Dataset);

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

Желаю удачи!

С уважением,
Мельникова Екатерина

Нравится

Поделиться

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

Здравствуйте! Пробовал использовать этот код, но ничего не получилось, выходят ошибки... и в конце концов в приложении в разделе расписание задачи вообще не отображаються,
может ли это быть связано с тем что у меня версия 3,3,1,а код для другой версии, пожалуйста поясните для какой версии подходит данный код?

"Мамажанов Марат Кадралдыкович" написал:но ничего не получилось, выходят ошибки

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

var DataFields = Dataset.DataFields;
var StartDateDataField = DataFields.ItemsByName('StartDate');
var DueDateDataField = DataFields.ItemsByName('DueDate');
var OwnerIDDataField = DataFields.ItemsByName('OwnerID');
Dataset.Locate('ID', Event.ID);
var PriorStartDate = StartDateDataField.ValAsDateTime;
var PriorDueDate = DueDateDataField.ValAsDateTime;
if (!CheckTaskCovering(Dataset,OwnerIDDataField,Event.Start,Event.Finish)) {
    CancelChangeEvent(Event, PriorStartDate, PriorDueDate);
    return;
}
Dataset.Edit();
var RemindingToOwnerID = Dataset.Values('RemindingToOwnerID');
if (!IsEmptyValue(RemindingToOwnerID)) {
    var uq_Remindings = GetSingleItemByCode('uq_Remindings', 'uq_RemindSingle');
    var Parameters = uq_Remindings.Parameters;
    var ColumnsValues = uq_Remindings.ColumnsValues;
    SetParameterValue(Parameters, 'ID', RemindingToOwnerID);
    ColumnsValues.ItemsByName('RemindTime').Value = Event.Start;
    uq_Remindings.Execute();
}
StartDateDataField.ValAsDateTime = Event.Start;
DueDateDataField.ValAsDateTime = Event.Finish;
UpdateDuration(Dataset);
Dataset.Post();
UpdateEventColorsByDatasetRecord(Event, Dataset);

Здравствуйте! Подставил данный код,ошибок нету, но дата напоминания не всегда обновляется при переносе задачи в расписании, но когда она все-таки обновляется, время начала напоминания становится равным времени начала задачи, но оно должно перетаскиваться ровно на стольно на сколько перетаскивается сама задача

Для реализации необходимого Вам функционала на Вашей версии приложения могу посоветовать заменить функционал строки

ColumnsValues.ItemsByName('RemindTime').Value = Event.Start;

на следующий:
- найти разницу между StartDateDataField.ValAsDateTime и Event.Start;
- найти запись из таблицы tbl_Remanding, значение поля RemindTime;
- добавить к нему разницу м/д StartDateDataField.ValAsDateTime и Event.Start;
- обновить запись в таблице tbl_Remanding.

Здравствуйте!
Подскажите пожалуйста как фильтровать, у меня есть 2 датасета (задачи и напоминания) и мне нужно, по мере изменения расписания задачи изменять и время напоминания, так чтобы время напоминания изменялось на столько же насколько изменяется расписание,
я было написал определенный скрипт, но когда я пытаюсь записать данные в таблицу напоминаний, у меня выходит ошибка, что поле "описание" не заполнено, и значение "нуль" в нем, не допустимо, вот пример:

function UpdateDatasetRecordByEvent(Dataset, Event) {

var DataFields = Dataset.DataFields;
var StartDateDataField = DataFields.ItemsByName('StartDate');
var DueDateDataField = DataFields.ItemsByName('DueDate');
var OwnerIDDataField = DataFields.ItemsByName('OwnerID');
Dataset.Locate('ID', Event.ID);
var PriorStartDate = StartDateDataField.ValAsDateTime;
var PriorDueDate = DueDateDataField.ValAsDateTime;
if (!CheckTaskCovering(Dataset,OwnerIDDataField,Event.Start,Event.Finish)) {
CancelChangeEvent(Event, PriorStartDate, PriorDueDate);
return;
}

Dataset.Edit();
var RemindingToOwnerID = Dataset.Values('RemindingToOwnerID');
var uq_Remindings = GetSingleItemByCode('uq_Remindings', 'uq_RemindSingle');
var ds_Remindings = dl_remLNK.dataset;
var Parameters = uq_Remindings.Parameters;
var ColumnsValues = uq_Remindings.ColumnsValues;
var ds_rem = ds_Remindings.DataFields.ItemsByName('RemindTime');
SetParameterValue(Parameters, 'ID', RemindingToOwnerID);
Event.Start;
uq_Remindings.Execute();

ds_Remindings.Close();
ApplyDatasetFilter(ds_Remindings, ID',RemindingToOwnerID, true);
ds_Remindings.Open();
ds_Remindings.edit();
ds_rem.ValAsDateTime = Event.Start;
ds_Remindings.post();

StartDateDataField.ValAsDateTime = Event.Start;
DueDateDataField.ValAsDateTime = Event.Finish;
UpdateDuration(Dataset);
Dataset.Post();
UpdateEventColorsByDatasetRecord(Event, Dataset);
}
я хотел фильтровать ds_Remindings.id по полю RemindingToOwnerID из первого датасета (ds_Task.RemindingToOwnerID), чтобы изменть напоминание связанное с текущим ответственным.
буду рад любым ответам

чем отличаются ds_Reminding и ds_Remindings какова роль каждого?

"Мамажанов Марат Кадралдыкович" написал:чем отличаются ds_Reminding и ds_Remindings какова роль каждого?

ds_Remindings соответствует всплывающему окну напоминаний. Вы можете посмотреть в соответствующем запросе на выборку sq_Remindings связи с таблицами, по записям которых появляются напоминания в этом окне.
ds_Reminding соответствует закладке "Напоминания" менеджера деталей.

Что касается Вашего кода, то проблема в не совсем корректном обновлении записей в таблице напоминаний. Например, нигде не указаны параметры для UpdateQuery.
Для решения проблемы рекомендую сделать следующим образом.
Сначала отфильтровать датасет напоминаний по нужной записи:

ds_Remindings.Close();
ApplyDatasetIDFilter(ds_Remindings, RemindingToOwnerID, true);
ds_Remindings.Open();

Затем записать в переменную описание напоминания (т.к. оно обязательно должно быть в UpdateQuery):

var RemindingDescription = ds_Remindings.Description;
if (IsEmptyValue(RemindingDescription)) {
                RemindingDescription = ‘Напоминание по задаче ’ + Dataset.Values(‘Title’);
}

Затем инициализация колонок UpdateQuery:

ColumnsValues.ItemsByName(‘Description’).Value = RemindingDescription;
ColumnsValues.ItemsByName(‘RemindTime’).Value = Event.Start;

Все это можно вставить между строками:

var ds_rem = ds_Remindings.DataFields.ItemsByName('RemindTime'); и SetParameterValue(Parameters, 'ID', RemindingToOwnerID);

Что касается блока:

ds_Remindings.Close();
ApplyDatasetFilter(ds_Remindings, ID',RemindingToOwnerID, true);
ds_Remindings.Open();
ds_Remindings.edit();
ds_rem.ValAsDateTime = Event.Start;
ds_Remindings.post();

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

Желаю удачи!

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