separate (Tracker.Report_Generator.Completion_Date_For_Ms)


procedure Calc_Date_Totals is
    ----------------------------------------------------------------------
    --|
    --|  NAME:  CALC_DATE_TOTALS
    --|
    --|  OVERVIEW:
    --|    This procedure calculates the total amount of time left by
    --|    MILESTONE and by person.
    --|
    --|  EXCEPTIONS HANDLED:
    --|    none
    --|
    --|  HISTORY:
    --|    written by   Bonnie Burkhardt   March 1985
    --|
    ----------------------------------------------------------------------

    End_List : Boolean := False;
    Ele_Ptr : Element_Pointer;
    Pr_Index : Integer := 0;
    Pr_Ptr : Personnel_Pointer;

begin
    Work_Is_Left := (others => False);
    Ms_Work_Left := False;
    Date_Done := (others => Null_Date);
    Prev_Date_Done := Null_Date;
    Ms_Date_Done := Null_Date;

    Pr_Index := 0;
    Start_Walk (Pr_List);

    loop
        Walk (Pr_List, Pr_Ptr, End_List);
        exit when End_List;
        Pr_Index := Pr_Index + 1;

        -- find the latest completion date for each element that has
        -- this milestone and this person
        Start_Walk (Pr_Ptr.Element_List);

        loop
            Walk (Pr_Ptr.Element_List, Ele_Ptr, End_List);
            exit when End_List;

            if (Ele_Ptr.Milestone_Num = Ms_Ptr.Number) then
                -- check if the current date done should be updated
                if Ele_Ptr.More_Than_One_Person then
                    for Ac_Index in 1 .. Num_Of_Activities loop
                        if (Ele_Ptr.People_Initials (Ac_Index) =
                            Pr_Ptr.Initials) and
                           ((Ele_Ptr.Dates_Done (Ac_Index) = Underflow_Date) or
                            (Date_Done (Pr_Index) = Null_Date) or
                            (Ele_Ptr.Dates_Done (Ac_Index) >
                             Date_Done (Pr_Index))) then
                            Date_Done (Pr_Index) :=
                               Ele_Ptr.Dates_Done (Ac_Index);
                            Work_Is_Left (Pr_Index) :=
                               Work_Is_Left (Pr_Index) or
                                  (Ele_Ptr.Hours_Left (Ac_Index) > 0.0);
                            Ms_Work_Left := Ms_Work_Left or
                                               Work_Is_Left (Pr_Index);
                        end if;
                    end loop;
                    -- check if the total milestone completion date should be updated

                    if Ele_Ptr.Date_Done > Ms_Date_Done then
                        Ms_Date_Done := Ele_Ptr.Date_Done;
                    end if;
                elsif (Ele_Ptr.Date_Done = Underflow_Date) or
                      (Date_Done (Pr_Index) = Null_Date) or
                      (Ele_Ptr.Date_Done > Date_Done (Pr_Index)) then
                    Date_Done (Pr_Index) := Ele_Ptr.Date_Done;
                    -- check if the total milestone completion date should be updated

                    if Ele_Ptr.Date_Done > Ms_Date_Done then
                        Ms_Date_Done := Ele_Ptr.Date_Done;
                    end if;

                    Work_Is_Left (Pr_Index) :=
                       Work_Is_Left (Pr_Index) or
                          (Ele_Ptr.Hours_To_Complete > 0.0);
                    Ms_Work_Left := Ms_Work_Left or Work_Is_Left (Pr_Index);
                end if;
                -- update the milestone's previous date done

                if (Ele_Ptr.Prev_Date_Done = Underflow_Date) or
                   (Prev_Date_Done = Null_Date) or
                   (Ele_Ptr.Prev_Date_Done > Prev_Date_Done) then
                    Prev_Date_Done := Ele_Ptr.Prev_Date_Done;
                end if;
            end if;
        end loop;

        -- update the grand total work_is_remaining flag for each person
        Work_Is_Left_Tot (Pr_Index) :=
           Work_Is_Left_Tot (Pr_Index) or Work_Is_Left (Pr_Index);
        Tot_Work_Left := Tot_Work_Left or Work_Is_Left_Tot (Pr_Index);

        -- update the grand total date done by person
        if (Date_Done (Pr_Index) = Underflow_Date) or
           (Tot_Date_Done (Pr_Index) = Null_Date) or
           (Date_Done (Pr_Index) > Tot_Date_Done (Pr_Index)) then
            Tot_Date_Done (Pr_Index) := Date_Done (Pr_Index);

            if Tot_Date_Done (Pr_Index) > Ms_Tot_Date_Done then
                Ms_Tot_Date_Done := Tot_Date_Done (Pr_Index);
            end if;
        end if;
    end loop;
end Calc_Date_Totals;
