ProjectsMain. Интерфейс ввода, просмотра и корректировки проектов Назад В начало Вперед

Файл: Example\Src\VIP\PrjMng\Projects.vip

Издание 01.2007. Добавлены директивы документирования.

Издание 01.2006. Исправлена ошибка: в обработчике cmPrjmanReCalc добавлен вызов ReReadRecord для обновления визуализации после перерасчета данных.

Издание 01.2006. В интерфейсе ввода, просмотра и корректировки проектов ProjectsMain убрана панель (как лишняя сущность). Соответствующие табличные события вынесены в обработчик tableEvent.

Издание 03.2005. В интерфейс ввода, просмотра и корректировки проектов ProjectsMain добавлены вызовы отчетов PrjMngFR и RepStaffUsage.

//******************************************************************************
//													(c) корпорация Галактика
// Демопроект 1.0 - Управление проектами
// Интерфейс ввода и корректировки проектов
//******************************************************************************

#include IResources.vih
#include IPrjResources.vih

//******************************************************************************
#doc
 Интерфейс ввода и корректировки проектов.</brief>
 Основной интерфейс управления проектами.
#end

interface ProjectsMain 'П Р О Е К Т Ы' EscClose, Cyan;
  show at (0,0,79,25);

create view

var
  cSuperStage : comp; // вышестоящий этап, 0 для проектов
  cCurProject : comp; // текущий проект (Projects.NRec)
  iResourcesEdit : ResourcesTab; // панель всех ресурсов этапа

as select

  if(Stages.Status = 'З','Завершенный проект',
	if(Stages.Status = 'Т','Текущий проект',
	if(Stages.Status = 'П','Планируемый проект',
							 'Неопределенное состояние проекта')))
	(FieldName = ProjectStatus),

  Projects.*, Stages.*

from
  Projects,
  Projects TempStages,
  Projects TempStages2,
  Projects Stages

where
((
	// Cвязь: Проект/Этап -> Подэтапы
	cCurProject == Projects.NRec  // текущий проект
  and cSuperStage == Stages.cParent // текущие проекты (этапы)
))
;
  
//------------------------------------------------------------------------------

form ProjectBreefRef('ProjectBreefRef.OUT');
 
//------------------------------------------------------------------------------

#doc
  <p>Функция проверяет наличие ресурсов у заданного владельца.</brief>
  <p>Параметры:
  <ul>
	<li>cMaster - NRec владельца ресурсов
  </ul>
  <p>Возвращаемое значение:
  <ul>
	<li>true  - у владельца нет ресурсов
	<li>false - у владельца есть ресурсы
  </ul>
#end

function IsEmpty(cMaster : comp) : boolean;
{
  if (getFirst TempStages
	where ((cMaster == TempStages.cParent)) = tsOK)
	IsEmpty := false;  // есть подэтапы
  else
	IsEmpty := iResourcesEdit.IsEmpty(cMaster);
}
 
//------------------------------------------------------------------------------

#doc
  <p>Функция удаляет все ресурсы у заданного владельца.</brief>
  <p>Параметры:
  <ul>
	<li>cMaster - NRec владельца ресурсов
  </ul>
  <p>Возвращаемое значение:
  <ul>
	<li>true  - удаление прошло успешно
	<li>false - в противном случае
  </ul>
#end

public function DeleteAll(cMaster : comp) : boolean;
{
  // пока удаляет только листы дерева
  // в следующей версии добавить обход поддерева
  DeleteAll := iResourcesEdit.DeleteAll(cMaster);
}

//------------------------------------------------------------------------------

#doc
  <p>Обработка события "изменилась стоимость ресурсов по текущему этапу проекта".</brief>
  Перерасчитываем суммарный расход только по текущему этапу и по проекту =
  для оперативного контроля. Полный перерасчет (включая промежуточные этапы)
  выполняется из меню "Операции".
  <p>Параиетры:
  <ul>
	<li>d - величина изменения
  </ul>
#end

procedure ResourceSumChanged (d : double);
{
  Stages.SummP := Stages.SummP + d;

  if (update current Stages <> tsOK)
	message('Ошибка корректировки стоимости этапа.' + chr(13) +
			'Выполните перерасчет стоимости этапа.', OkButton + Error);

  if (cCurProject <> 0)
  {
	if (getFirst Projects <> tsOK)
	message('Внутренняя ошибка.', OkButton+Error);

	Projects.SummP := Projects.SummP + d;

	if (update current Projects <> tsOK)
	message('Ошибка корректировки стоимости проекта.' + chr(13) +
			'Выполните перерасчет стоимости проекта.', OkButton+Error);
  }

  RescanPanel(tnStages);
}

//------------------------------------------------------------------------------

#doc
  <p>Выполнить перерасчет ресурсов.</brief>
  <p>Рекурсивно перерасчитывает потребность в ресурсах для
  поддерева проектов начиная с cMaster.
  <p>Параметры:
  <ul>
	<li>cMaster - NRec, для которого выполняется перерасчет
  </ul>
#end

procedure ReCalcAllResources(cMaster : comp);
{
  var sumP1, sumF1,  sumP2, sumF2: double;

  // Обработка собственных ресурсов.
  // Служит признаком начала расчета (удаляется предыдущий расчет).
  if (not iResourcesEdit.CopyAll(cMaster, cMaster, resResourceTotal, sumP1, sumF1))
  {
	message('Ошибка расчета стоимости проекта.' + chr(13) +
			'Повторите расчет.', OkButton+Error);
	exit;
  }

  // Обработка подчиненных этапов
  _loop TempStages2 where ((cMaster == TempStages2.cParent))
  {
	// пересчитать ресурсы подэтапа
	PushPos(tnTempStages2);
	ReCalcAllResources(TempStages2.NRec);
	PopPos(tnTempStages2);

	// и добавить их к своим собственным
	if (iResourcesEdit.CopyAll(TempStages2.NRec, cMaster,
							 resResourceTotal, sumP2, sumF2))
	{
	sumP1 := sumP1 + sumP2;
	sumF1 := sumF1 + sumF2;
}
	else
	{
	message('Ошибка расчета стоимости проекта.' + chr(13) +
			'Повторите расчет.', OkButton+Error);
	exit;
}
  }

  // обновить плановую и фактическую стоимости проекта /этапа
  if (getFirst TempStages2 where ((cMaster == TempStages2.Nrec )) = tsOK)
  {
	TempStages2.SummP := sumP1;
	TempStages2.SummF := sumF1;

	if (update current TempStages2 <> tsOK)
	message('Ошибка расчета стоимости проекта.' + chr(13) +
			'Повторите расчет.', OkButton+Error);
  }
}

//------------------------------------------------------------------------------

#doc
  <p>Сформировать краткий отчет по проекту.</brief>
  <p>Параметры:
  <ul>
	<li>cMaster - NRec проекта, для которого формируется отчет
	<li>shift   - количество отступов слева для отображения вложенности
			подэтапов проекта. Параметр следует устанавливать в ноль, далее
			он автоматически увеличивается при рекурсивном вызове процедуры.
  </ul>
#end

procedure ProjectRef(cMaster : comp; shift : integer);
{
  var sh : byte;
  sh := if (shift < 8, shift, 8);

  ProjectBreefRef.PutEventById(feDoLoop,fcCycleOfSteps);

  if (getFirst TempStages2 where ((cMaster == TempStages2.NRec)) = tsOK)
  {
	ProjectBreefRef.write(Center ('', sh)+Trim(TempStages2.Code)+' '+Trim(TempStages2.Name));
	ProjectBreefRef.write(TempStages2.SummP);
	ProjectBreefRef.write(ProjectStatus);
  }
  else
  {
	ProjectBreefRef.write('');
	ProjectBreefRef.write('');
	ProjectBreefRef.write('!!! Ошибка чтения данных !!!');
	ProjectBreefRef.write('');
	ProjectBreefRef.write('');
  }

  sh := sh +2;

  _loop TempStages2 where ((cMaster == TempStages2.cParent))
  {
	if (ProjectBreefRef.error)
	exit;

	PushPos(tnTempStages2);
	ProjectRef(TempStages2.NRec, sh);
	PopPos(tnTempStages2);
  }
}

#doc
 <p>Просмотр и корректировка данных по проекту /этапу
#end

//==============================================================================
// winProjectEdit
//==============================================================================

window winProjectEdit 'Просмотр и корректировка данных по проекту/этапу';
  show at (0,1,79,19);

screen scrStagesEdit 'Этап' (,, scPrjmanProjectEdit);
  show at (,,,6);
  table Stages;

fields
  Stages.Code   : noProtect;
  ProjectStatus ('Изменяется при нажатии на <F3>', , scPrjmanProjectEditPick): pickButton, protect;
  Stages.Name   : noProtect;
  Stages.SummP  : skip;
  Stages.SummF  : skip;
  Stages.StartP : skip;
  Stages.StartF : skip;
  Stages.StopP  : skip;
  Stages.StopF  : skip;

<<
` Код этапа:`.@@@@@@@@@@		` Состояние этапа:`.@@@@@@@@@@@@@@@@@@@@
` Наименование этапа:`.@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
								 План		 Факт
` Стоимость				:`.@@@@@@@@@@  .@@@@@@@@@@
` Начало работ по этапу	:`.@@@@@@@@@@  .@@@@@@@@@@
` Завершение работ по этапу:`.@@@@@@@@@@  .@@@@@@@@@@
>>
end;   // screen scrStaticText

//------------------------------------------------------------------------------

tableEvent
  table Stages

cmInsertRecord:
  if (insert current Stages <> tsOK)
	message('Ошибка при выполнении операции.' + chr(13) +
			'Повторите ввод данных.', OkButton+Error);
  else
	iResourcesEdit.MasterChanged(Stages.NRec);

cmUpdateRecord:
  if (update current Stages <> tsOK)
	message('Ошибка при выполнении операции.' + chr(13) +
			'Повторите ввод данных.', OkButton+Error);

cmDeleteRecord:
{
  var dlt : boolean;
  dlt := true;

  if (IsEmpty(Stages.NRec))
  {
	if (message('Удалить этап?' + chr(13) +
		Stages.Name, yesNo+Warning) <> cmYes)
	dlt := false;
  }
  else
  {
	if (message('Удалить этап' + chr(13) +
		Stages.Name + chr(13) +
		'вместе с назначенными ресурсами?',
		yesNo+Warning) <> cmYes)
	dlt := false;
	else
	if (not DeleteAll(Stages.NRec))
		dlt := false;
  }

  if (dlt)
	if (delete current Stages <> tsOK)
	message('Ошибка при выполнении операции.' + chr(13) +
			'Повторите удаление данных.', OkButton+Error);
}
end; // tableEvent table Stages

//------------------------------------------------------------------------------

embedded embResEdit interface iResourcesEdit;
  show at (,7,,16);
end;

//------------------------------------------------------------------------------

text Stages.comment;
  show at (,17,,);

end; // window winProjectEdit

//==============================================================================
// Main Window 
//==============================================================================

tree ProjectsTree 'Проекты / Этапы'(,, scPrjmanProjectsTree);
  table Stages;

fields
  Stages.Name   #3'Наименование': [50], noProtect;
  Stages.SummP  #3'Затраты'	 : [20], skip;
  ProjectStatus #3'Статус'	: [20], pickButton, protect;
end; 

//------------------------------------------------------------------------------

handleEvent 

cmDone:
  UnBindEvent (ResourceSumChanged, iResourcesEdit.SumChanged);

cmInit:
{
  cSuperStage := 0;
  cCurProject := 0;
  BindEvent (ResourceSumChanged, iResourcesEdit.SumChanged);
}

cmTreeTop:
{
  cSuperStage := 0;
  cCurProject := 0;
} 

cmTreeUp: 
{
  if (cSuperStage <> 0) // если не на верху, то сделать шаг вверх
  {
	if (getFirst TempStages where ((cSuperStage == TempStages.Nrec)) = tsOK)
	{
	cSuperStage := TempStages.cParent;
	if (cSuperStage = 0)
		cCurProject := 0;
}
  }
}

cmTreeDown:
{
  cSuperStage := Stages.Nrec;

  if (Stages.cProject = 0)
	cCurProject := Stages.Nrec;
  else
	cCurProject := Stages.cProject;
}

cmTreeNodeType:
{
  // для листьев у нас есть своя иконка
  if (getFirst TempStages where ((Stages.Nrec == TempStages.cParent)) <> tsOK)
	if (NOT TreeNodeIsOpen(ProjectsTree))
	TreeSetNodeType(ProjectsTree, 0, 'PrMnLeaf');

  // а для узлов используется иконка по умолчанию
}

cmPick:
{
 if (curField = #ProjectStatus)
 {
   case Stages.Status of

	 'П':
	 set Stages.Status = 'Т';

	 'Т':
	 set Stages.Status = 'З';

   else
	 set Stages.Status = 'П';
   end;
 }
}

cmSetDefault:
{
  selectField(#Stages_NAME);

  // код проекта по умолчанию -> N п/п
  var iNumber: longInt;
  iNumber := 1;

  if (GetLast TempStages where ((cSuperStage == TempStages.cParent)) = tsOK)
  {
	iNumber := LongInt(TempStages.Code);
	if(iNumber < 65535)
	iNumber := iNumber + 1;
  }

  Stages.Status := 'П';
  Stages.Code := String(iNumber);
  Stages.cProject := cCurProject;
}

cmInsert:  // здесь добавлять записи нельзя - уходим в окно редактирования
  RunWindow(winProjectEdit);

cmPrjmanEdit:
  RunWindow(winProjectEdit);

cmPositionChanged:
  iResourcesEdit.MasterChanged(Stages.NREC);

cmPrjmanReCalc:
{
  ReCalcAllResources(Stages.NREC);  // перерасчет начинаем с тек.точки
  ReReadRecord (tnStages); // отобразить результат перерасчета
}

cmPrjmanFR:
  RunInterface(PrjMngFR);

cmPrjmanSU:
  RunInterface(RepStaffUsage);

cmPrjmanRef:
{
  if (not ProjectBreefRef.error)
	ProjectRef(Stages.NREC, 0);  // начинаем с тек.точки

  if (not ProjectBreefRef.error)
	ProjectBreefRef.showfile(' Отчет по проектам ', false);

  ProjectBreefRef.ReInit;
}
end; // handleEvent
end.