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.