Поделиться через


Метод TimeSheet.ApproveNonProjectTime

Изменяет состояние элементов указанное время не относящихся к проекту, ожидающих утверждения или отклонения.

Пространство имен:  WebSvcTimeSheet
Сборка:  ProjectServerServices (в ProjectServerServices.dll)

Синтаксис

'Декларация
<SoapDocumentMethodAttribute("https://schemas.microsoft.com/office/project/server/webservices/TimeSheet/ApproveNonProjectTime", RequestNamespace := "https://schemas.microsoft.com/office/project/server/webservices/TimeSheet/",  _
    ResponseNamespace := "https://schemas.microsoft.com/office/project/server/webservices/TimeSheet/",  _
    Use := SoapBindingUse.Literal, ParameterStyle := SoapParameterStyle.Wrapped)> _
Public Sub ApproveNonProjectTime ( _
    approvedTimesheetLines As Guid(), _
    rejectedTimesheetLines As Guid() _
)
'Применение
Dim instance As TimeSheet
Dim approvedTimesheetLines As Guid()
Dim rejectedTimesheetLines As Guid()

instance.ApproveNonProjectTime(approvedTimesheetLines, _
    rejectedTimesheetLines)
[SoapDocumentMethodAttribute("https://schemas.microsoft.com/office/project/server/webservices/TimeSheet/ApproveNonProjectTime", RequestNamespace = "https://schemas.microsoft.com/office/project/server/webservices/TimeSheet/", 
    ResponseNamespace = "https://schemas.microsoft.com/office/project/server/webservices/TimeSheet/", 
    Use = SoapBindingUse.Literal, ParameterStyle = SoapParameterStyle.Wrapped)]
public void ApproveNonProjectTime(
    Guid[] approvedTimesheetLines,
    Guid[] rejectedTimesheetLines
)

Параметры

  • approvedTimesheetLines
    Тип: []

    Уникальные идентификаторы TimesheetLines для утверждения.

  • rejectedTimesheetLines
    Тип: []

    Уникальные идентификаторы TimesheetLines отклоняет.

Замечания

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

Этот метод отправляет задания объект QueueSystem . Свойство CorrelationGUID для задания равно свойству TS_UID .

Разрешения Project Server

Разрешение

Описание

Нестандартные

Управляющий расписаниями ресурса является текущий пользователь.

Примеры

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

Примечание

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

For critical information about running this code sample, see Необходимые условия для образцов кода на основе ASMX в Project 2013.

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Data;
using System.Web.Services.Protocols;
using System.Threading;
using PSLibrary = Microsoft.Office.Project.Server.Library;
namespace Microsoft.SDK.Project.Samples.ApproveNonProjectTime
{
   class Program
   {
      [STAThread]
      static void Main()
      {
         try{
            #region Setup
            const string PROJECT_SERVER_URI = "https://ServerName/ProjectServerName/"; // <<--Change to be the name of your server running Project Server and the name of your directory.
            const string TIMESHEET_SERVICE_PATH = "_vti_bin/psi/timesheet.asmx";
            const string RESOURCE_SERVICE_PATH = "_vti_bin/psi/resource.asmx";
            const string ADMIN_SERVICE_PATH = "_vti_bin/psi/admin.asmx";
            const string QUEUESYSTEM_SERVICE_PATH = "_vti_bin/psi/queuesystem.asmx";
            TimeSheetWebSvc.TimesheetDataSet timesheetDs;

            // Set up the services.
            TimeSheetWebSvc.TimeSheet timeSheetSvc = new TimeSheetWebSvc.TimeSheet();
            timeSheetSvc.UseDefaultCredentials = true;
            timeSheetSvc.Url = PROJECT_SERVER_URI + TIMESHEET_SERVICE_PATH;
            CodeSample_TimeSheetUtilities timeSheetUtils = new CodeSample_TimeSheetUtilities(timeSheetSvc);

            ResourceWebSvc.Resource resourceSvc = new ResourceWebSvc.Resource();
            resourceSvc.Url = PROJECT_SERVER_URI + RESOURCE_SERVICE_PATH;
            resourceSvc.UseDefaultCredentials = true;
            CodeSample_ResourceUtilities resourceUtils = new CodeSample_ResourceUtilities(resourceSvc);

            AdminWebSvc.Admin adminSvc = new AdminWebSvc.Admin();
            adminSvc.Url = PROJECT_SERVER_URI + ADMIN_SERVICE_PATH;
            adminSvc.UseDefaultCredentials = true;
            
            QueueSystemWebSvc.QueueSystem q = new QueueSystemWebSvc.QueueSystem();
            q.Url = PROJECT_SERVER_URI + QUEUESYSTEM_SERVICE_PATH;
            q.UseDefaultCredentials = true;

            #endregion
            #region Setup a timesheet with non-project time
            Guid sampleResourceUid = resourceUtils.EnsureLertchai();

            AdminWebSvc.TimePeriodDataSet timePeriodDs = adminSvc.ReadPeriods(AdminWebSvc.PeriodState.Open);

            Guid periodUid = timeSheetUtils.FindFirstEmptyPeriod(sampleResourceUid, timePeriodDs);
            Guid timeSheetUid = timeSheetUtils.CreateTimeSheetFor(sampleResourceUid, resourceUtils.myUid, periodUid);
            timesheetDs = timeSheetSvc.ReadTimesheet(timeSheetUid);

            // Find a line that requires approval.

            TimeSheetWebSvc.TimesheetDataSet.LinesRow[] approvalNeeded = (TimeSheetWebSvc.TimesheetDataSet.LinesRow[])timesheetDs.Lines.Select("TS_LINE_CLASS_NEED_APPROVAL = true");
            if (approvalNeeded.Length < 1)
            {
               throw(new ApplicationException("No lines requiring approval were found on the timesheet.\r\nChange your server settings so that one default admin type requires approval."));
            }

            TimeSheetWebSvc.TimesheetDataSet.ActualsRow actualsRow = timesheetDs.Actuals.NewActualsRow();
            AdminWebSvc.TimePeriodDataSet.TimePeriodsRow timePeriodsRow = timePeriodDs.TimePeriods.FindByWPRD_UID(periodUid);

            approvalNeeded[0].TS_LINE_COMMENT = "I really need a break.";
            actualsRow.TS_LINE_UID = approvalNeeded[0].TS_LINE_UID;
            actualsRow.TS_ACT_PLAN_VALUE =  1000 * 60 * 8;// 8 hours
            actualsRow.TS_ACT_NON_BILLABLE_VALUE = actualsRow.TS_ACT_PLAN_VALUE;
            actualsRow.TS_ACT_COMMENT = "Adding some time so it must be approved.";
            actualsRow.TS_ACT_FINISH_DATE = timePeriodsRow.WPRD_START_DATE.AddDays(1).AddTicks(-1);
            actualsRow.TS_ACT_START_DATE = timePeriodsRow.WPRD_START_DATE;
            timesheetDs.Actuals.AddActualsRow(actualsRow);

            actualsRow = timesheetDs.Actuals.NewActualsRow();
            actualsRow.TS_LINE_UID = approvalNeeded[0].TS_LINE_UID;
            actualsRow.TS_ACT_PLAN_VALUE = 1000 * 60 * 8;// 8 hours
            actualsRow.TS_ACT_NON_BILLABLE_VALUE = actualsRow.TS_ACT_PLAN_VALUE;
            actualsRow.TS_ACT_COMMENT = "Adding some time so it must be approved.";
            actualsRow.TS_ACT_FINISH_DATE = timePeriodsRow.WPRD_START_DATE.AddDays(2).AddTicks(-1);
            actualsRow.TS_ACT_START_DATE = timePeriodsRow.WPRD_START_DATE.AddDays(1);
            timesheetDs.Actuals.AddActualsRow(actualsRow);


            Guid jobUid = Guid.NewGuid();
            timeSheetSvc.QueueUpdateTimesheet(jobUid, timeSheetUid, timesheetDs);
            CodeSampleUtilities.WaitForQueue(q, jobUid);

            timesheetDs = timeSheetSvc.ReadTimesheet(timeSheetUid);

            CodeSampleUtilities.WriteTablesFormated("Timesheet DS data that needs approval", timesheetDs.Tables);
            #endregion
            #region Try submitting with out approval
            try
            {
               // This fails because the time must be approved.
               Console.WriteLine("Submit timesheet without approving administrative time.");
               jobUid=Guid.NewGuid();
               timeSheetSvc.QueueSubmitTimesheet(jobUid, timeSheetUid, resourceUtils.myUid, "This won't work the first time.");
               CodeSampleUtilities.WaitForQueue(q, jobUid);
            }
            catch (Exception ex)
            {
               Console.WriteLine("Submit failed because administrative time needed to be approved.");
               ExceptionHandlers.HandleException(ex);
               q.CancelJob(jobUid, true, true);
               Console.ResetColor();
            }
            #endregion
            #region Approve non-project time.

            Console.WriteLine("Approve the non-project type.");
            timeSheetSvc.ApproveNonProjectTime(new Guid[] { approvalNeeded[0].TS_LINE_UID }, null);
            #endregion
            #region Resubmit after approval
            // Now try the submission again...
            // This works because the administrative time was approved.
            Console.WriteLine("Try the submission again.");
            jobUid = Guid.NewGuid();
            timeSheetSvc.QueueSubmitTimesheet(jobUid, timeSheetUid, resourceUtils.myUid, "This will work.");
            CodeSampleUtilities.WaitForQueue(q, jobUid);

            timesheetDs = timeSheetSvc.ReadTimesheet(timeSheetUid);
            CodeSampleUtilities.WriteTablesFormated("Submission succeeded!", timesheetDs.Tables);
          
            #endregion
         }
         catch (SoapException ex)
         {
         ExceptionHandlers.HandleSoapException(ex);
         }
         catch (WebException ex)
         {
         ExceptionHandlers.HandleWebException(ex);
         }
         catch (Exception ex)
         {
         ExceptionHandlers.HandleException(ex);
         }
         finally
         {
         ExceptionHandlers.ResetConsole();
         }
      }
   }
   class ExceptionHandlers
   {
      public static void HandleSoapException(SoapException ex)
      {
         PSLibrary.PSClientError error = new PSLibrary.PSClientError(ex);
         PSLibrary.PSErrorInfo[] errors = error.GetAllErrors();
         string errMess = "==============================\r\nError: \r\n";
         for (int i = 0; i < errors.Length; i++)
         {
            errMess += "\n" + ex.Message.ToString() + "\r\n";
            errMess += "".PadRight(30, '=') + "\r\nPSCLientError Output:\r\n \r\n";
            errMess += errors[i].ErrId.ToString() + "\n";

            for (int j = 0; j < errors[i].ErrorAttributes.Length; j++)
            {
               errMess += "\r\n\t" + errors[i].ErrorAttributeNames()[j] + ": "
                  + errors[i].ErrorAttributes[j];
            }
            errMess += "\r\n".PadRight(30, '=');
         }
         Console.ForegroundColor = ConsoleColor.Red;
         Console.WriteLine(errMess);
      }

      public static void HandleWebException(WebException ex)
      {
         string errMess = ex.Message.ToString() +
            "\n\nLog on, or check the Project Server Queuing Service";
         Console.ForegroundColor = ConsoleColor.Red;
         Console.WriteLine("Error: " + errMess);
      }

      public static void HandleException(Exception ex)
      {
         Console.ForegroundColor = ConsoleColor.Red;
         Console.WriteLine("Error: " + ex.Message);
      }

      public static void ResetConsole()
      {
         Console.ResetColor();
         Console.WriteLine("\r\n\r\nPress any key...");
         Console.ReadKey();
      }
   }
   class CodeSampleUtilities
   {
      // Write all contents of a table collection to the console.
      public static void WriteTablesToConsole(System.Data.DataTableCollection theTables)
      {
         Console.ForegroundColor = ConsoleColor.DarkGreen;
         foreach (System.Data.DataTable table in theTables)
         {

            int[] columnWidths = new int[table.Columns.Count];
            int tableWidth = 0;
            string dataString;
            Console.WriteLine("Table: " + table.TableName);

            // Write out the column names and get their spacing.
            StringBuilder tableRow = new StringBuilder();
            for (int i = 0; i < table.Columns.Count; i++)
            {
               columnWidths[i] = GetColumnWidth(table.Columns[i]);
               tableRow.Append(table.Columns[i].ColumnName.PadRight(columnWidths[i]));

               tableWidth += columnWidths[i];
            }
            // Add a space so that it will not wrap.
            tableWidth += 1;
            // Make the console as wide as the widest table.
            Console.BufferWidth = (Console.BufferWidth > tableWidth ? Console.BufferWidth : tableWidth);
            tableRow.Append("\r\n");
            Console.Write(tableRow.ToString());

            // Write out the data.
            foreach (DataRow row in table.Rows)
            {
               tableRow = new StringBuilder();
               for (int i = 0; i < table.Columns.Count; i++)
               {

                  dataString = row[i].ToString();
                  // Truncate output if it is wider than 
                  // the desired column width.
                  if (dataString.Length >= columnWidths[i])
                  {
                     dataString = dataString.Substring(0, columnWidths[i] - 1);
                  }
                  // Add the output to the stringbuilder and pad right to fill
                  // up to the column width.
                  tableRow.Append(dataString.PadRight(columnWidths[i]));
               }
               tableRow.Append("\r\n");
               Console.Write(tableRow.ToString());
            }
            Console.Write("\r\n".PadLeft(tableWidth, '-'));
         }
         Console.ResetColor();
      }
      // Helper function for WriteTablesToConsole.
      private static int GetColumnWidth(DataColumn column)
      {
         // Note: Might not handle byte[]data types well.
         const int MAX_COL_WIDTH = 40;
         int dataWidth = 0;

         //Return 12 for numbers, 30 for dates, and string width for strings.
         switch (column.DataType.UnderlyingSystemType.ToString())
         {
            case "System.Boolean":
            case "System.Byte":
            case "System.Byte[]":
            case "System.Char":
            case "System.Decimal":
            case "System.Double":
            case "System.Int16":
            case "System.Int32":
            case "System.Int64":
            case "System.SByte":
            case "System.Single":
            case "System.UInt16":
            case "System.UInt32":
            case "System.UInt64":
               dataWidth = 12;
               break;
            case "System.DateTime":
            case "System.TimeSpan":
               dataWidth = 30;
               break;
            case "System.Guid":
               dataWidth = 37;
               break;
            case "System.String":
               // If it has a maxlength, use it.
               if (column.MaxLength > 0)
               {
                  dataWidth = column.MaxLength;
               }
               else
               {
                  // Otherwise, use the max col width.
                  dataWidth = MAX_COL_WIDTH;
               }
               break;
            default:
               dataWidth = column.ColumnName.Length;
               break;
         }
         // Truncate if over the maxlength.
         if (dataWidth > MAX_COL_WIDTH)
         {
            dataWidth = MAX_COL_WIDTH;
         }
         // Always be at least as wide as the colum name.
         return (column.ColumnName.Length > (dataWidth) ? column.ColumnName.Length + 1 : dataWidth);
      }
      public static void WriteTablesFormated(string Title, System.Data.DataTableCollection theTables)
      {
         WriteSeparator();
         Console.WriteLine(Title);

         CodeSampleUtilities.WriteTablesToConsole(theTables);

      }
      public static void WriteSeparator()
      {
         Console.ForegroundColor = ConsoleColor.DarkYellow;
         Console.WriteLine("".PadRight(Console.BufferWidth, '='));
         Console.ResetColor();

      }

      // Wait for the job to finish.
      // Outputs job status to the console.
      static public void WaitForQueue(QueueSystemWebSvc.QueueSystem q, Guid jobId)
      {
         QueueSystemWebSvc.JobState jobState;
         const int QUEUE_WAIT_TIME = 1; // One second
         bool jobDone = false;
         string xmlError = string.Empty;
         int wait = 0;

         //Wait for the project to get through the queue.
         // Get the estimated wait time in seconds.
         wait = q.GetJobWaitTime(jobId);

         // Wait for it.
         Console.Write("Waiting on queue. Estimate: {0} seconds.\r\n ", wait);

         // Wait until it is finished.

         do
         {
            // Get the job state.
            jobState = q.GetJobCompletionState(jobId, out xmlError);

            if (jobState == QueueSystemWebSvc.JobState.Success)
            {
               jobDone = true;
            }
            else
            {
               if (jobState == QueueSystemWebSvc.JobState.Unknown
               || jobState == QueueSystemWebSvc.JobState.Failed
               || jobState == QueueSystemWebSvc.JobState.FailedNotBlocking
               || jobState == QueueSystemWebSvc.JobState.CorrelationBlocked
               || jobState == QueueSystemWebSvc.JobState.Canceled)
               {
                  // If the job failed, error out.
                  throw (new ApplicationException("Queue request " + jobState + " for Job ID " + jobId + ".\r\n" + xmlError));
               }
               else
               {
                  //Console.WriteLine("Job State: " + jobState + " for Job ID: " + jobId);
                  Console.Write("~");
                  Thread.Sleep(QUEUE_WAIT_TIME * 1000);
               }
            }
         }
         while (!jobDone);
         Console.Write("\r\n");
      }
   }
   class CodeSample_TimeSheetUtilities
   {
      TimeSheetWebSvc.TimeSheet timeSheetSvc;

      public CodeSample_TimeSheetUtilities(TimeSheetWebSvc.TimeSheet theTimeSheetSvc)
      {
         timeSheetSvc = theTimeSheetSvc;
      }
      public Guid CreateTimeSheetFor(Guid resourceGuid, Guid mgrUid,Guid periodUid)
      {

         TimeSheetWebSvc.TimesheetDataSet timesheetDs = new TimeSheetWebSvc.TimesheetDataSet();
         TimeSheetWebSvc.TimesheetDataSet.HeadersRow headersRow = timesheetDs.Headers.NewHeadersRow();
         headersRow.RES_UID = resourceGuid;
         headersRow.TS_UID = Guid.NewGuid();
         headersRow.WPRD_UID = periodUid;
         headersRow.TS_CREATOR_RES_UID = mgrUid;
         headersRow.TS_NAME = "Timesheet ";
         headersRow.TS_COMMENTS = "Timesheet for code sample";
         headersRow.TS_ENTRY_MODE_ENUM = (byte)PSLibrary.TimesheetEnum.EntryMode.Weekly;
         timesheetDs.Headers.AddHeadersRow(headersRow);

         // Create the timesheet with the default line types that are specified by the admin.
         timeSheetSvc.CreateTimesheet(timesheetDs, TimeSheetWebSvc.PreloadType.Default);

         return headersRow.TS_UID;
      }
      
      public Guid FindFirstEmptyPeriod(Guid resUid,AdminWebSvc.TimePeriodDataSet timePeriodDs)
      {
         TimeSheetWebSvc.TimesheetDataSet timeSheetDs;

         for (int i = 0; i < timePeriodDs.TimePeriods.Count; i++)
         {
            timeSheetDs = timeSheetSvc.ReadTimesheetByPeriod(resUid, timePeriodDs.TimePeriods[i].WPRD_UID, TimeSheetWebSvc.Navigation.Current);
            if (timeSheetDs.Headers.Count == 0)
            {
               return timePeriodDs.TimePeriods[i].WPRD_UID;
            }
         }
         return Guid.Empty;
      }
   }
   class CodeSample_ResourceUtilities
   {

      private ResourceWebSvc.Resource m_resourceSvc;
      private Guid m_MyUid;
      private Guid sampleResource = Guid.Empty;

      public CodeSample_ResourceUtilities(ResourceWebSvc.Resource theResourceSvc)
      {
         m_resourceSvc = theResourceSvc;
         m_MyUid = resourceSvc.GetCurrentUserUid();
      }

      public Guid myUid
      {
         get { return m_MyUid; }
      }

      public ResourceWebSvc.Resource resourceSvc
      {
         get {return m_resourceSvc;}
      }

      public Guid EnsureLertchai()
      {
         return EnsureSampleResource("Lertchai Treetawatchaiwong", "LT");
      }

      public Guid EnsureSampleResource(string name,string inits)
      {
         Guid resGuid = GetResourceGuid(name);
         if (resGuid == Guid.Empty)
         {
            resGuid = this.CreateResource(name, inits, myUid);
         }
         return resGuid;
      }

      public Guid GetResourceGuid(string resourceName)
      {
         ResourceWebSvc.ResourceDataSet resourceDs = new ResourceWebSvc.ResourceDataSet();

         PSLibrary.Filter resourceFilter = new Microsoft.Office.Project.Server.Library.Filter();
         resourceFilter.FilterTableName = resourceDs.Resources.TableName;
         resourceFilter.Fields.Add(new PSLibrary.Filter.Field(resourceDs.Resources.TableName, resourceDs.Resources.RES_UIDColumn.ColumnName, PSLibrary.Filter.SortOrderTypeEnum.None));
         resourceFilter.Fields.Add(new PSLibrary.Filter.Field(resourceDs.Resources.TableName, resourceDs.Resources.RES_NAMEColumn.ColumnName, PSLibrary.Filter.SortOrderTypeEnum.None));
         PSLibrary.Filter.FieldOperator existingResource = new PSLibrary.Filter.FieldOperator(PSLibrary.Filter.FieldOperationType.Equal, resourceDs.Resources.RES_NAMEColumn.ColumnName, resourceName);
         resourceFilter.Criteria = existingResource;
         resourceDs = resourceSvc.ReadResources(resourceFilter.GetXml(), false);
         if (resourceDs.Resources.Count >= 1)
         {
            return resourceDs.Resources[0].RES_UID;
         }
         else
         {
            return Guid.Empty;
         }
      }

      private Guid CreateResource(string resourceName, string initials, Guid timesheetMgr)
      {
         ResourceWebSvc.ResourceDataSet resourceDs = new ResourceWebSvc.ResourceDataSet();
         ResourceWebSvc.ResourceDataSet.ResourcesRow resourceRow = resourceDs.Resources.NewResourcesRow();
         resourceRow.RES_UID = Guid.NewGuid();
         resourceRow.RES_NAME = resourceName;
         resourceRow.RES_INITIALS = initials;
         resourceRow.RES_TYPE = (int)PSLibrary.Resource.Type.WorkResource;
         resourceRow.RES_TIMESHEET_MGR_UID = timesheetMgr;
         resourceDs.Resources.AddResourcesRow(resourceRow);
         resourceSvc.CreateResources(resourceDs, false, true);
         return resourceRow.RES_UID;
      }
   }
}

См. также

Справочные материалы

TimeSheet класс

Элементы TimeSheet

Пространство имен WebSvcTimeSheet