How to update Non-work Time in a TimeSheet using PSI?
-
quarta-feira, 30 de maio de 2012 10:26
Hi,
I am working on a migration utility that will import time sheet data from Excel sheets to PS 2010. In the legacy system there used to be dedicated projects for administrative (overhead) work for every department. With the arrival of PS it was decided that all such data would be migrated in the built-in 'Administrative' project. I have written some code which is working fine with 'Actual' work but failing for 'Admin' non-work.
1. First the code creates all time-sheets using the following code:
TimesheetDataSet dsTimeSheet = TimeSheetSvc.ReadTimesheetByPeriod(
tsi.ResourceInfo.UId, tsi.PeriodInfo.UId, Navigation.Current);
if (dsTimeSheet.Headers.Count < 1)
{
uidTimeSheet = Guid.NewGuid();
dsTimeSheet = new TimesheetDataSet();
TimesheetDataSet.HeadersRow hdr = dsTimeSheet.Headers.NewHeadersRow();
hdr.TS_UID = uidTimeSheet;
hdr.RES_UID = tsi.ResourceInfo.UId;
hdr.WPRD_UID = tsi.PeriodInfo.UId;
hdr.TS_CREATOR_RES_UID = tsi.ResourceInfo.UId;
hdr.TS_NAME = "My Timesheet";
hdr.TS_COMMENTS = "Created during migration process.";
hdr.TS_ENTRY_MODE_ENUM = (byte)PSLib.TimesheetEnum.EntryMode.Daily;
dsTimeSheet.Headers.AddHeadersRow(hdr);
PSI.TimeSheetSvc.CreateTimesheet(dsTimeSheet, PreloadType.Default);
}2. Later I want to book the hours as per the Time Sheet Line Classes using following:
StatusingSvc.UpdateStatus(CreateChangeXml(tsi, start, finish, effort));
Please note that for Project ID in xml I am using PSLibrary.TimesheetConst.const_AdminTimeProjectGuid.
but I am getting the following error:
Error details:
<errinfo xmlns=""><general><class name="Invalid Project GUID"><error id="1009" name="ProjectIDInvalid" uid="7f39f258-99c5-4c8e-979c-9ea30a632c3c"></error></class><class name="An unhandled exception occurred in Microsoft.Office.Project.Server.BusinessLayer.Statusing.UpdateStatus."><error id="42" name="GeneralUnhandledException" uid="0ef6cf27-75f8-4c92-8cd0-0bc9f3508f6e" Exception="System.NullReferenceException: Object reference not set to an instance of an object.
 at Microsoft.Office.Project.Server.BusinessLayer.Statusing.SaveChanges(SvrDoc doc, DalDataAccess dataaccess)
 at Microsoft.Office.Project.Server.BusinessLayer.Statusing.UpdateStatusHelper(String changexml, String originalxml, UPDATE_TYPE updatetype, Boolean determineNodeConsistencyChanges, ProjectUpdatesDataSet& projectUpdatesData, ISvrDataAccess dataAccess, Dictionary`2 projSvrDocs, Boolean doSave)
 at Microsoft.Office.Project.Server.BusinessLayer.Statusing.UpdateStatusHelper(String changexml, String originalxml, UPDATE_TYPE updatetype, Boolean determineNodeConsistencyChanges, ProjectUpdatesDataSet& projectUpdatesData, Boolean doSave)
 at Microsoft.Office.Project.Server.BusinessLayer.Statusing.UpdateStatus(String changexml)
 at Microsoft.Office.Project.Server.Wcf.Implementation.StatusingImpl.UpdateStatus(String changexml)"></error></class></general></errinfo>
System.ServiceModel.FaultException`1[SvcStatusing.ServerExecutionFault]: ProjectServerError(s) LastError=GeneralUnhandledException Instructions: Pass this into PSClientError constructor to access all error information (Fault Detail is equal to SvcStatusing.ServerExecutionFault).
============================
PSClientError output:
ProjectIDInvalid
============================
PSClientError output:
GeneralUnhandledException
Exception: System.NullReferenceException: Object reference not set to an instance of an object.
at Microsoft.Office.Project.Server.BusinessLayer.Statusing.SaveChanges(SvrDoc doc, DalDataAccess dataaccess)
at Microsoft.Office.Project.Server.BusinessLayer.Statusing.UpdateStatusHelper(String changexml, String originalxml, UPDATE_TYPE updatetype, Boolean determineNodeConsistencyChanges, ProjectUpdatesDataSet& projectUpdatesData, ISvrDataAccess dataAccess, Dictionary`2 projSvrDocs, Boolean doSave)
at Microsoft.Office.Project.Server.BusinessLayer.Statusing.UpdateStatusHelper(String changexml, String originalxml, UPDATE_TYPE updatetype, Boolean determineNodeConsistencyChanges, ProjectUpdatesDataSet& projectUpdatesData, Boolean doSave)
at Microsoft.Office.Project.Server.BusinessLayer.Statusing.UpdateStatus(String changexml)
at Microsoft.Office.Project.Server.Wcf.Implementation.StatusingImpl.UpdateStatus(String changexml)
Regards,
Naveed SaqibRegards, Naveed Saqib
Todas as Respostas
-
segunda-feira, 11 de junho de 2012 08:11
Hello,
I found the solution to this problem at http://msdn.microsoft.com/en-us/library/gg227119.aspx
Basically my mistake was that I was not using the 'Actuals' collection and trying to submit the actuals using Statusing Web Service. Following is final copy of the working code:
private static void FillResourceTimeSheetsOverhead(TimeSheetLineInfo tsi)
{
TimesheetDataSet dsTimeSheet = tsi.TimeSheetDs;
if ((dsTimeSheet.Headers.Count > 0) &&
(dsTimeSheet.Headers[0].RES_UID == tsi.ResourceInfo.UId) &&
(dsTimeSheet.Lines.Count > 0))
{
var q = from line in dsTimeSheet.Lines
where line.PROJ_UID == tsi.ProjectUId
&& line.TS_LINE_CACHED_ASSIGN_NAME == tsi.LineClass.Name
select line;
if (q.Count() > 0)
{
DateTime dtStart = tsi.PeriodInfo.Start;
TimesheetDataSet.LinesRow line = q.First();
line.TS_LINE_COMMENT = "Effort hours entered by migration utility.";
FillLineOverheadEfforts(tsi, line);
using (OperationContextScope ocs = Impersonater.Impersonate(
PSI.TimeSheetSvc.InnerChannel, tsi.ResourceInfo.UId, tsi.ResourceInfo.NetworkId))
{
Guid jobUid = Guid.NewGuid();
PSI.TimeSheetSvc.QueueUpdateTimesheet(jobUid, tsi.TimeSheetUId, tsi.TimeSheetDs);
Helpers.WaitForQueue(jobUid);
}
}
}private static void FillLineOverheadEfforts(TimeSheetLineInfo tsi, TimesheetDataSet.LinesRow line)
{
int i = 0;
foreach (double effort in tsi.Efforts)
{
DateTime start = tsi.PeriodInfo.Start.AddDays(i);
DateTime finish = start.AddDays(1).AddTicks(-1);
if (effort > 0)
{
TimesheetDataSet.ActualsRow actual = tsi.TimeSheetDs.Actuals.NewActualsRow();
actual.TS_LINE_UID = line.TS_LINE_UID;
actual.TS_ACT_VALUE = (decimal) Helpers.ToWork(effort);
actual.TS_ACT_START_DATE = start;
actual.TS_ACT_FINISH_DATE = start.AddDays(1).AddTicks(-1);
tsi.Dirty = true;
tsi.TimeSheetDs.Actuals.AddActualsRow(actual);
_timesheets.Add(tsi.TimeSheetUId);
}
i++;
}
}Naveed Saqib
Regards, Naveed Saqib
- Marcado como Resposta Naveed Saqib segunda-feira, 11 de junho de 2012 08:11