Поиск блогу

пятница, 7 октября 2011 г.

Создание связанных карточек

При создании сложной системы может потребоваться связывать карточки, т.е. сделать так, чтобы одна карточка, порождала другие, а при удалении главной карточки, карточки, связанные с ней удалялись тоже.
Например, создается карточка Проблемы (родительская), а к ней должна быть прикреплена карточка Решения (дочерняя).
Для этого необходимо следующее:
1. Создать в схеме данных карточки новое поле, которое будет представлять собой ссылку на карточку (refcardid) и в типе ссылки указать "Hard".


2. Положить на форму контрол карточки и привязать его к созданному полю (CardLink).

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

пятница, 9 сентября 2011 г.

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

понедельник, 8 августа 2011 г.

Рассылка уведомлений

В версии конструктора 4.5 есть сервис уведомлений.

С его помощью можно настроить рассылку уведомлений в виде ярлыка или почтового сообщения на изменения полей карточки. На данный момент уведомления рассылаются при изменении поля и последующем сохранении карточки. В связи с этим есть проблема, если необходимо отправить уведомление о смене состояния карточки. Для того, чтобы отправить такое уведомление, придется в скрипте карточки, меняющем ее состояние прописать принудительное изменение значения контрола состояния через PropertyController.UpdateProperty, либо (что будет оптимальнее при необходимости отправки нового состояния в уведомлении) записывать новое состояние в скрытый строковый контрол. Например, вот так:
 CardData cStates = Session.CardManager.GetCardData(new Guid("{7984F2CE-9345-4C59-B66B-7125DD9195A1}"));// Получаем справочник ролевой модели. В нем хранятся состояния
 PropertyController.UpdateProperty("СтрокаСостояния",cStates.Sections[new Guid("{521B4477-DD10-4F57-A453-09C70ADB7799}")].Rows[DomainObject.StateId].GetString("DefaultName"));// Получаем название текущего состояния и записываем его в контрол.

четверг, 21 июля 2011 г.

Изменение вида карточки

Предположим, что на карточке лежит контрол "Вид".
Опытным путем я установил, что при изменении значения в нем, само изменение вида карточки происходит уже после события ControlValueChanged.

Это означает то, что при написании ControlValueChanged для этого контрола нужно использовать PropertyController.GetPropertyValue("НазваниеКонтролаВида") вместо DomainObject.KindId, чтобы получить в скрипте новое значение вида.

вторник, 12 июля 2011 г.

Скрипт на привязку карточки с табличному контролу.

Всем привет :-)
В одну из составляющих моей разработки решения"Управление совещаниями", входит объединение всех трёх карточек в единую работающую систему. Для этого мне требуется написать несколько скриптов на событие AddButtonClick табличного контрола. Мои познания в ООП находятся на уровне основных понятий, поэтому самостоятельно выполнить поставленную задачу будет крайне трудно, и если уважаемые разработчики помогут мне с преодолением этой проблемы, я буду им очень благодарен за проявленное содействие в достижении личных и организационных успехов.

Итак, задача:
В основной карточке "Совещание" ( Card 1 ) в таблице с вопросами повестки, при нажатии на добавить "+", должна появляться новая карточка "Вопросы повестки" ( Card 2 ). Так же, при каждом нажатии на добавить "+" карточка должна обновляться.




Был использован метод:
{
object newCard = Session.CardManager.CreateCard(new Guid("{5763AAF2-BF9B-4373-AF1B-6360EF4A2FFA}"));
}
но при загрузке карточки он выдаёт ошибку, что "Данный метод не поддерживается".

Вопрос : Какой скрипт будет выполнять поставленную задачу?

Спасибо)

четверг, 30 июня 2011 г.

Как подключать сборки в конструкторе DocsVision

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

Находятся все сборки по пути Windows/assembly/GAC_MSIL

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

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

Из-за особенностей Конструтора у вас не получится подключить сборки сразу из assembly, поэтому скопируйте сначала нужные сборки в отдельную папку и уже оттуда подключайте. Но лучше удалить из GAC_MSIL скрытый файл "Desktop.ini". После этого папки со сборками станут видны из конструктора и их не придется никуда копировать. Также одном из плюсов данного способа является тот факт, что при переносе решения на другую машину, вам не придется заново прописывать пути к сборкам.

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

Получение данных выделенной строки из таблицы

Вывод выделенной строки оказался весьма нетривиальным заданием.

Данный фрагмент кода выведет в MessageBox содержимое выделенной строки в табличном контроле с названием "Журнал заявки".

LayoutHelper layoutHelper = new LayoutHelper(CardControl.LayoutControl, CardControl.BarManager, Session, CardData.Type.Id);
DocsVision.BackOffice.View.WinForms.LayoutItems.ICustomPropertyItem propertyItem = layoutHelper.GetCustomPropertyItem("Журнал заявки");
var refMapper = new CardPropertyDescriptionMapper(Session);
DocsVision.BackOffice.Model.CardProperties.Entities.CardPropertyTable cpt = null;
foreach (DocsVision.BackOffice.Model.Layouts.Entities.CardPropertyTableDescription refPropertyTableDesc in refMapper.FindTableProperties(CardData.Type.Id))
          {
              if (refPropertyTableDesc.Name == "Журнал заявки")
               {
                 var propertyMapper = new CardPropertyMapper(Session, CardData.Id, DomainObject.CustomPropertiesSectionId);
                   cpt = propertyMapper.FindTable(refPropertyTableDesc);
                   break;
               }
          }
System.Reflection.Assembly asm = System.Reflection.Assembly.Load("DocsVision.BackOffice.View, Version=4.5.0.0, Culture=neutral, PublicKeyToken=7148afe997f90519");
Type tableType = asm.GetType("DocsVision.BackOffice.View.WinForms.PropertyControls.TablePropertyControl");
var propInfo = tableType.GetProperty("GridView");
object ooo = propInfo.GetValue(propertyItem.Control, System.Reflection.BindingFlags.NonPublic, null, null, System.Globalization.CultureInfo.InvariantCulture);
DocsVision.BackOffice.View.WinForms.Controls.GridExView gridExView = ooo as DocsVision.BackOffice.View.WinForms.Controls.GridExView;
DevExpress.XtraGrid.Views.Grid.GridView gridView = gridExView as DevExpress.XtraGrid.Views.Grid.GridView;
object key = ((System.Data.DataRowView)gridView.GetFocusedRow()).Row[gridExView.KeyField];
          foreach (DocsVision.BackOffice.Model.CardProperties.Entities.CardPropertyTableRow row in cpt.Rows)
          {
              if (row.Key == (Guid)key)
              {
                  string message = "";                  
                  foreach (DocsVision.BackOffice.Model.CardProperties.Entities.CardProperty cellProp in row.Cells)
                      {
                       object val = cellProp.Value;                          
                       message += val == null ? "null" : val.ToString();
                       message += " ";    
                      }
                      MessageBox.Show(message);
                      }
    
              }


Для работы скрипта нужно прописать в using:

using DocsVision.Platform.WinForms.DataSource;
using DocsVision.BackOffice.Model.CardProperties.DataAccess;


Возможно, что-то еще...

а также подключить сборки DevExpress. А именно
DevExpress.XtraLayout.9.2.dll
DevExpress.XtraGrid.9.2.dll
DevExpress.Data.9.2.dll
DevExpress.Utils.9.2.dll

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

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

Рассмотрим на примере таблицы, содержащей 3 столбца: Дату, идентификатор сотрудника и некоторый текст.

в приведенном скрипте:
secComment - это идентификатор табличной секции(Guid);
comment - какая-то строка(string)

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

Guid g = Guid.NewGuid();
CardData.Sections[secComment].BeginUpdate();
RowData newComment = CardData.Sections[secComment].CreateRow(g);
newComment.SetString("Текст", comment);
newComment.SetGuid("Автор", new EmployeeMapper(Session).GetCurrentUserId());
newComment.SetDateTime("Дата", DateTime.Now);
CardData.Sections[secComment].EndUpdate();

суббота, 21 мая 2011 г.

Смена атрибутов контрола из скрипта. На примере атрибута ReadOnly

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

using System;
using System.Windows.Forms;
using DocsVision.Platform.ObjectManager;
using DocsVision.BackOffice.View.WinForms;
using DocsVision.BackOffice.Model;
using DocsVision.BackOffice.Model.Layouts.DataAccess;
using DocsVision.BackOffice.Model.Base.Entities;
using DocsVision.BackOffice.Model.CardProperties.Entities;
using DocsVision.BackOffice.Model.Layouts.Entities;
using DocsVision.BackOffice.Model.RoleModel.DataAccess;
using DocsVision.BackOffice.Model.RoleModel.Entities;
using DocsVision.BackOffice.View.WinForms.Helpers;

private void cardControl_AfterActivate(System.Object sender, System.EventArgs e)
    {
  CardProperty prop = GetCardProperty("имя контрола");
  CardPropertyDescription.LayoutAttributeSet attrSet = prop.Description.GetLayoutAttributes(CardControl.DomainObject.SelectedLayoutId);
        attrSet.ReadOnly = true;
        PropertyController.Refresh();
    }

//Поиск контрола с нужным именем  
private CardProperty GetCardProperty(string propertyName)
 {
 foreach (CardProperty property in PropertyController.CardProperties)
  {
  if (property.Name == propertyName)
  return property;
  }
 return null;
 }

среда, 11 мая 2011 г.

Перезапуск сервисов из командной строки

Думаю, что многие сталкивались с проблемой, что какие-то изменения, внесенные в структуру DV требовали перезапуска серверов, SQL и IIS. На это уходит много времени, так как надо полазать по различным административным менюшкам и покликать много кнопок.

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

1. создаем новый текстовый файл.
2. в тело пишем

NET stop DVStorageServer45
NET stop WFServer45
NET stop MSSQL$SQLEXPRESS
IISReset
NET start MSSQL$SQLEXPRESS
NET start DVStorageServer45
NET start WFServer45


3. сохраняем файл на рабочий стол под именем Reset.bat и в свойствах файла выставляем "Запускать от имени Администратора". Иногда для этого приходится создать ярлык на этот батник и в его свойствах поставить запуск от имени администратора.
4. наслаждаемся перезапуском в один клик.

P.S. Возможно, что SQL сервер у вас называется не SQLEXPRESS. В таком случае либо просто удалите из батника строку перезапуска SQL (Обычно такой перезапуск не требуется), либо впишите свое название сервера.

Скрипт смены состояния карточки из бизнес-процесса

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


// подключение системных библиотек
using System;
using System.Xml;

// подключение библиотек СУБП
using DocsVision.Workflow.Objects;
using DocsVision.Workflow.Runtime;
using DocsVision.Workflow.Gates;
using DocsVision.Platform.HelperAPI;
using DocsVision.Platform.ObjectManager;

namespace DVScriptHost
{
   class DVScript
   {
       // стандартная функция, которая будет вызвана подсистемой СУБП
       //
       // входные параметры функции:
       //
       // process - информация о процессе. содержит коллекции
       //     Gates - коллекция шлюзов процесса
       //     Variables - коллекция переменных процесса
       // passInfo - информация о текущем проходе
       //
        private string state = "Согласование с контрагентом"; //Название состояния, в которое мы хотим перевести карточку
        private DVGate m_DVGate;
       public void Execute (DocsVision.Workflow.Runtime.ProcessInfo process, PassState passInfo)
       {
            try
            {
                //Получаем ссылку на карточку, у которой надо сменить состояние. В данном случае она хранится в переменной процесса, которая называется "Инициирующий договор"
                ProcessVariable pvCard = process.GetVariableByName("Инициирующий договор");
                DVCard dvCard = (DVCard)pvCard.Value;

                //получаем шлюз
                m_DVGate = (DVGate)process.Gates[DVGate.GateID];

                // получаем сессию
                UserSession oSes = m_DVGate.Session;
                  
                //Получаем данные карточки
                CardData card = oSes.CardManager.get_CardData(dvCard.ID);

                //Получаем ссылку на секцию "Основная информация". Так как карточка стандартная, то гуид берем из справочника в предыдущем посте. В противном случае - из DVExplorer.
                SectionData mainInfo = card.Sections["8C77892A-21CC-4972-AD71-A9919BCA8187"];

                //Получаем ссылку на справочник типов. Гуид берем из справочника в предыдущем посте.
                CardData RefTypes = oSes.CardManager.get_DictionaryData("BE14D55D-92B7-4345-AD10-32588981F83D");

                //Получаем тип карточки из справочника типов
                RowData currentType = RefTypes.Sections["49AD5A2D-17EC-46E2-A49E-C58D0BBD9C1A"].Rows[mainInfo.FirstRow.get_Value("Type")];

                //Устанавливаем состояние карточки, найдя его по имени и в соответствии с типом карточки
                mainInfo.FirstRow.set_Value("DocState", currentType.ChildRows.GetItemByValue("Name", state).ID);

            }
            catch (Exception ex)
            {
                 // запись в журнал ошибки исполнения
                 process.LogMessage("Ошибка выполнения скрипта:" + ex.Message);
            }
            return;
        }
    }
}

Описание полей стандартных карточек.

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

Также, если кому-то нужна литература по C#, то выкладываю самоучитель: Секунов С.Ю. - Самоучитель С# - 2001.pdf

И также самоучитель по xml: samou4itel_xml.rar

Новости блога. Дополнительные возможности при просмотре блога.

Благодаря нововведениям платформы Blogger, наш блог теперь можно просматривать в различных видах, используя страницу видов. Ссылка на данную страницу теперь всегда доступна из списка полезных ссылок справа.

Подробнее об этой фиче можно почитать тут.

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

четверг, 10 марта 2011 г.

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

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

Пусть у нас есть карточка договора, настроенная как дополнительный вид входящего документа через справочник типов. В карточке договора используется часть полей из карточки входящего документа (Тема, дата создания и пр.), но также имеются пользовательские свойства (Примечание, сумма договора, сумма аванса, контрагент и его адрес и тд.). Задача усложняется, если пользовательские настройки вида содержат табличный контрол.

В примере Договора в табличном контроле 2 столбца: Контрагент и его адрес.
Free Image Hosting at www.ImageShack.us
Задача: вывести в представлении фамилию контрагента. Вот так:
Free Image Hosting at www.ImageShack.us

Сначала делаем все, как и при обычном создании представления: создаем представление, добавляем колонки.
Затем нужно сделать следующие присоединения:
1.Free Image Hosting at www.ImageShack.us
Привязываем свойство с названием "Контрагент", принадлежащее данной карточке (InstanceID)
2.Free Image Hosting at www.ImageShack.us
Не очевидная привязка выбранных значений. Нужна, так как столбец табличного контрола представляет собой массив. После этого в после "Выбранное значение" будут находиться идентификаторы контрагентов
3.Free Image Hosting at www.ImageShack.us
Получение по Идентификатору из выбранного значения информации о контрагенте.

После перечисленных привязок можно сделать присвоение колонке значения поля Фамилия из привязанной карточки контрагентов:
Free Image Hosting at www.ImageShack.us

P.S. Если есть проблема с добавлением простого (не табличного) пользовательского свойства в представление, дайте знать в комментах. В таком случае напишу и про них.

воскресенье, 6 марта 2011 г.

Смена состояния карточки из скрипта

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

На данный момент простого способа сменить состояние из скрипта я не нашел. Единственный способ требует знания гуида конечного состояния. Данный идентификатор не доступен ни в одном из стандартных справочником и контекстных меню, поэтому приходится идти в обход.

Создаем строковый контрол на карточке. Затем на какую-нибудь кнопку ставим команду, записывающую в этот котрол значение из DomainObject.StateManager.CurrentStateId. (В моем случае по какой-то причине на активацию карточки поставить не удалось, только на кнопку или команду меню). Сохраняем карточку, закрываем конструктор.

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

Далее в конструкторе в нужном Вам месте пишем:
DomainObject.StateManager.SetCurrentState(new Guid("fce438e8-d38c-4552-86d0-36d464920265"));

CardControl.RefreshLayout();

Вместо "fce438e8-d38c-4552-86d0-36d464920265" конечно же нужно поставить нужный гуид.

P.S. Я полагаю, что возможно как-то менять состояние карточки проще, используя команду DomainObject.ChangeCardState(StateMachineBranch branch), но я так и не смог понять, как ей пользоваться. Если кто-то разберется, то очень хотел бы получить совет в комментах.

среда, 2 марта 2011 г.

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

System.Drawing.Image image = System.Drawing.Image.FromFile(@"c:\Img.jpg");

PropertyController.UpdateProperty("imageControl", image); //imageControl - имя контрола типа "Изображение"

CardControl.RefreshLayout();

четверг, 24 февраля 2011 г.

Работа блога

Думаю, что все заметили раздел "Полезные ссылки".
Он будет время от времени дополняться. Сегодня была добавлена ссылка на довольно обширную базу знаний о DocsVision от компании-партнера TeamLead.

Также существует страница с частыми вопросами по работе блога: FAQ. К ней в комментариях можно оставлять свои вопросы по работе блога и его настройкам. Также там можно оставлять свои пожелания по добавлению/изменению/удалению каких-то функций в блоге.

вторник, 22 февраля 2011 г.

DVCardManager

Недавно столкнулся с проблемой, что не мог загрузить библиотеку в базу при помощи CardManager.

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

Следовательно, кроме "тестовой" должны быть добавлены следующие библиотеки:
Free Image Hosting at www.ImageShack.us.

После этого будут работать функции Update Database и Upload Library.

понедельник, 21 февраля 2011 г.

Вывод значения нумератора в дайджест

Иногда нужно вывести значения из нумератора в дайджест. Например, нужно вывести регистрационный номер документа.

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

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

PropertyController.UpdateProperty("НомерПрописью",number.Number);// в скрытое поле записываем номер в виде строки

В дайджест добавляем что-то вроде этого:
Номер: 

Результат будет выглядеть так:
Free Image Hosting at www.ImageShack.us

P.S. Если Вы не используете автоматическое заполнение нумератора, то придется написать еще обращение к нумератору через Mapper и вставить это в AfterActivate

суббота, 12 февраля 2011 г.

Баг

Ошибка: Создаем несколько разметок для разных видов карточки. При редактировании каждой разметки (добавлении контролов), причем только в случае использования многозакладочности, имена контролам могут присвоиться одинаковые для разных разметок. КР сначала не видит ошибку. Но при закрытии КР и повторном входе выдает ошибку о нескольких контролах с одинаковым именем.
Способ решения: при добавлении контролов в разные разметки карточки нужно не допускать совпадания имен контролов, иначе карточка станет недоступна для редактирования. При перезагрузке КР и навигатора карточка загружается без последних изменений.

Продолжение рассмотрения пространства имен BusinessCalendar.

Пару постов назад я начал писать про пространство имен DocsVision.BackOffice.Model.BusinessCalendar.Entities. Упоминал, что в нем содержатся 2 перечислимых типа DayType и TimeType.

Для справки: Перечислимый тип - это тип данных, переменные которого могут принимать значения заранее заданные пользователем. Например, можно создать тип "Animals", и возможными значениями у этого типа сделать "Horse, Pig, Cat, Dog, Cow". Тогда переменная типа Animals сможет принять значение Animals.Horse или, к примеру, Animals.Cat.


Ниже приведу значения для типов DayType и TimeType.
    DayType
  • Holiday
  • NonWorking
  • Working
    TimeType
  • Work
  • NotWork

пятница, 11 февраля 2011 г.

Просмотр структуры карточки.

Иногда возникает потребность просмотреть, какие свойства содержит та, или иная карточка.
Для этого можно воспользоваться утилитой DVExplorer, входящей в SDK.

После запуска утилиты и подключения к базе выбираем пункт "Card Types..."


Обращение к карточке Бизнес-календаря. Примерная структура класса.

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

Для того, чтобы обратиться к конкретной карточке календаря нужно узнать ее Guid. Проще всего это сделать, кликнув на бизнес-календарь правой кнопкой и зайти в свойства. Внизу будет указан URL карточки, он то и будет содержать легко узнаваемый Guid.


Далее в самой карточке нужно сделать следующее:
using DocsVision.BackOffice.Model.BusinessCalendar.DataAccess;
using DocsVision.BackOffice.Model.BusinessCalendar.Entities;
/*
.
.
.
*/
Guid calGuid = new Guid("F827960F-6E61-40AD-A7E4-63AF74FAB54A");  
Calendar cal = new CalendarMapper(Session).Find(calGuid);

В результате выполнения будет создан объект класса Calendar, имеющий весьма сложную структуру. Кроме свойств и методов, унаследованных от класса DomainObject, он включает в себя поле DefaultWorkTime типа IList (как я понял, так же представлены столбцы в табличном контроле). DefaultWorkTime содержит соответственно поля StartTime и EndTime, содержащие границы рабочего дня по-умолчанию. Они используются, если в календаре не приписаны рабочие часы, отличающиеся от них.
Если же рабочие часы заданы индивидуально для каждого дня, то нужно будет обращаться к полю Years (IDictionary), содержащему данные о каждом дне (int DayNumber,enum Type(Working,NonWorking,Holiday),IList WorkTime:(StartTime,EndTime)).

Также для работы с календарем может быть полезен класс WorkTimeCalculator, который содержит два метода: GetDayTimeWorkStatus(DateTime date) и GetDayWorkStatus(DayTime date), возвращающие значения типов TimeType и DayType соответственно.

Создать объект класса WorkTimeCalculator можно следующим способом:
using DocsVision.BackOffice.Model.BusinessCalendar;
using DocsVision.BackOffice.Model.BusinessCalendar.DataAccess;
using DocsVision.BackOffice.Model.BusinessCalendar.Entities;
/*
.
.
.
*/
Calendar cal = new CalendarMapper(Session).Find(new Guid("00000000-0000-0000-0000-000000000000"));
WorkTimeCalculator calc = new WorkTimeCalculator(cal);
Примечание: вместо 00000000-0000-0000-0000-000000000000 укажите нужный Guid.

среда, 9 февраля 2011 г.

Обращение к данным карточки сотрудника. Программирование действий в ответ на клик по кнопке.

Идея такова: мы выбираем сотрудника в соответствующем контроле типа "сотрудник", затем кликаем по контролу "кнопка", в ответ на что в отдельном свойстве появляется, к примеру, Email или Телефон сотрудника.

Эту задачу можно решить двумя способами:

1 способ (в обход объект-модели):

private void Свойство10_Click(System.Object sender, System.EventArgs e)  //Свойство10 - у меня имя кнопки
{
Guid? employeeId=(Guid?)PropertyController.GetPropertyValue("Автор"); //employeeId - ключ на карточку по свойству "Автор". "Автор" - имя контрола типа "сотрудник"
if (employeeId.HasValue) //проверка существования значения ключа employeeId
{
var empl=new DocsVision.BackOffice.Model.StaffModel.DataAccess.EmployeeMapper(Session).Find(employeeId.Value); //новая переменная, в которую записываем значение employeeId.Value
PropertyController.UpdateProperty("Свойство12",empl.Email); //Записываем в свойство типа "строка" значение empl.Email. Соответственно мы можем вытащить в качестве значение не только Email, а практически любое свойство карточки сотрудника
PropertyController.RefreshControls(); //обновляем контролы, чтобы отобразилось новое значение
}
else
{
MessageBox.Show("Ошибка"); //сообщение об ошибке, если employeeId не имеет значения
}
}



2 способ (через объект-модель):


private void Свойство10_Click(System.Object sender, System.EventArgs e)
{
Guid? employeeId=(Guid?)PropertyController.GetPropertyValue("Автор");
if (employeeId.HasValue)
{
RowData employeeData=Session.CardManager.GetDictionaryData(new Guid("6710B92A-E148-4363-8A6F-1AA0EB18936C")).Sections[new Guid("DBC8AE9D-C1D2-4D5E-978B-339D22B32482")].GetRow(employeeId.Value);
//RefStaffCardId = 6710B92A-E148-4363-8A6F-1AA0EB18936C (Правой кнопкой на справочник сотрудников, экспорт, XML карточки)
//Employee = DBC8AE9D-C1D2-4D5E-978B-339D22B32482 (C:\Program Files\DocsVision\Platform\4.5\Server\Tools\Database\TakeOffice\RefStaff.xml - строчка с employee)
PropertyController.UpdateProperty("Свойство12",employeeData["Phone"].ToString()); //Phone - стандартное имя ячейки в базе данных, хранящей значение "Телефон" определенного сотрудника
PropertyController.RefreshControls();
}
else
{
MessageBox.Show("Ошибка");
}
}

Скрипт из мануала.

для того, чтобы при открытии карточки,ей присваивался регистрационный номер автоматически, существует след скрипт:
отыскиваете в событиях карточки событие AfterActivate, жмете три точки и открывается скрипт,первая строка генерится автоматически,а далее копируем скрипт)

private void cardControl_AfterActivate(System.Object sender, System.EventArgs e)
{ 
var numeratorProperty = GetCardProperty("Нумератор"); //здесь в скобках идет настоящее имя вашего регистратора, у меня "нумератор"

if (numeratorProperty.Value != null)
{   
return;
}

var ruleAttribute = numeratorProperty.Description.GetAttribute("Rule"); //обратите внимание,что в этом месте как раз идет НЕ настояшее имя вашего правила для регистратора,а стандартное название Rule

Guid? ruleId = (Guid?)ruleAttribute.Value;

var numeratorMapper = new DocsVision.BackOffice.Model.CardProperties.DataAccess.NumeratorNumberMapper(Session, CardData.Id, DomainObject.NumbersSectionId.Value);

var number = numeratorMapper.Create(ruleId.Value);

numeratorProperty.Value = number;
PropertyController.RefreshControls();

}

private CardProperty GetCardProperty(string propertyName)
{
foreach (CardProperty property in PropertyController.CardProperties)
{
if (property.Name == propertyName)
return property;
}
return null;
}

Пара багов

При написании скрипта наткнулся на следующую ошибку:
Ошибка
Если на карточке лежит контрол "Время", то, если в него не было принудительно записано какое-то значение через скрипт (значение по-умолчанию не в счет), то при попытке считать значение контрола возвращается объект неправильного типа.
Способ решения
Задавать значения по-умолчанию для этого контрола в событии карточки CardInitialized.



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

Получение типа значения контрола

Часто при считывании значения свойства карточки может возникнуть вопрос о том, какого типа нужно создать переменную для хранения этого значения.
Для того, чтобы узнать тип значения свойства, можно воспользоваться следующим методом:
MessageBox.Show(PropertyController.GetPropertyValue("ИмяСвойства").GetType().ToString());

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

Вступление

Всем привет!

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

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