private const int QUEUE_WAIT_TIME = 1;
private bool IsDebug {
get {
return Request.Params["debug"] == "1";
}
}
protected override void OnInit(EventArgs e) {
base.OnInit(e);
try {
int result = Process();
Response.Write(String.Format("{{\"result\": {0}}}", result));
} catch (Exception ex) {
SPLogger.Error(ex);
Response.Write(String.Format("{{\"result\": 0, \"error\": \"{0}\"}}", ex.Message.Replace("\"", "'")));
}
}
protected int Process() {
Guid? periodId = null;
DateTime? currentDt = null;
DateTime? periodStart = null;
DateTime? periodFinish = null;
Guid? timesheetId = null;
Guid jobId, managerId;
string timesheetName = String.Empty;
TimesheetDataSet currDS, prevDS;
if (Request.Params["tsDate"] != null) {
try { currentDt = SPUtility.ParseDate(SPContext.Current.Web, Request.Params["tsDate"], "", false); } catch { }
}
if (Request.Params["tsUID"] != null) {
try { timesheetId = new Guid(Request.Params["tsUID"]); } catch { }
}
if (Request.Params["tsPRD"] != null) {
try { periodId = new Guid(Request.Params["tsPRD"]); } catch { }
}
TimeSheet tsSvc = new TimeSheet();
tsSvc.Url = SPContext.Current.Site.Url + "/_vti_bin/psi/timesheet.asmx";
tsSvc.UseDefaultCredentials = true;
Resource resSvc = new Resource();
resSvc.Url = SPContext.Current.Site.Url + "/_vti_bin/psi/resource.asmx";
resSvc.UseDefaultCredentials = true;
Admin adminSvc = new Admin();
adminSvc.Url = SPContext.Current.Site.Url + "/_vti_bin/psi/admin.asmx";
adminSvc.UseDefaultCredentials = true;
QueueSystem queueSvc = new QueueSystem();
queueSvc.Url = SPContext.Current.Site.Url + "/_vti_bin/psi/queuesystem.asmx";
queueSvc.UseDefaultCredentials = true;
Guid userId = resSvc.GetCurrentUserUid();
if (timesheetId.HasValue) {
// if tsUID is declared
periodId = GetPeriodIdByTimesheetDataSet(tsSvc.ReadTimesheet(timesheetId.Value));
}
TimePeriodDataSet periodDS = adminSvc.ReadPeriods(PeriodState.All);
if (!currentDt.HasValue) { currentDt = DateTime.Now; }
for (int i = 0; i < periodDS.TimePeriods.Count; i++) {
if (periodId.HasValue) {
// if tsPRD/tsUID is declared
if (periodId.Value.Equals(periodDS.TimePeriods[i].WPRD_UID)) {
periodStart = periodDS.TimePeriods[i].WPRD_START_DATE;
periodFinish = periodDS.TimePeriods[i].WPRD_FINISH_DATE;
break;
}
} else if ((currentDt.Value.Ticks > periodDS.TimePeriods[i].WPRD_START_DATE.Ticks) && (currentDt.Value.Ticks < periodDS.TimePeriods[i].WPRD_FINISH_DATE.Ticks)) {
periodStart = periodDS.TimePeriods[i].WPRD_START_DATE;
periodFinish = periodDS.TimePeriods[i].WPRD_FINISH_DATE;
periodId = periodDS.TimePeriods[i].WPRD_UID;
break;
}
}
try {
prevDS = tsSvc.ReadTimesheetByPeriod(userId, periodId.Value, PRU.PS.Web.TimesheetWebSvc.Navigation.Previous);
if (IsDebug) PrintTimesheet(prevDS, "before: previous");
if (prevDS == null || prevDS.Headers.Rows.Count < 1) return -1;
} catch (Exception iex) {
SPLogger.Error("error retrieving previous timesheet", iex);
return -1;
}
try {
currDS = tsSvc.ReadTimesheetByPeriod(userId, periodId.Value, PRU.PS.Web.TimesheetWebSvc.Navigation.Current);
if (IsDebug) PrintTimesheet(currDS, "before: current");
if (currDS == null || currDS.Headers.Rows.Count < 1) return -2;
} catch (Exception iex) {
SPLogger.Error("error retrieving current timesheet", iex);
return -2;
}
managerId = (Guid)prevDS.Headers.Rows[0][prevDS.Headers.RES_TIMESHEET_MGR_UIDColumn];
timesheetId = (Guid)currDS.Headers.Rows[0][currDS.Headers.TS_UIDColumn];
timesheetName = String.Format("Timesheet {0}-{1}",
SPUtility.FormatDate(SPContext.Current.Web, periodStart.Value, SPDateFormat.DateOnly),
SPUtility.FormatDate(SPContext.Current.Web, periodFinish.Value, SPDateFormat.DateOnly));
try {
// delete existing timesheet
if (currDS.Headers.Rows.Count > 0) {
timesheetId = (Guid)currDS.Headers.Rows[0][currDS.Headers.TS_UIDColumn];
jobId = Guid.NewGuid();
tsSvc.QueueDeleteTimesheet(jobId, timesheetId.Value);
WaitForQueue(queueSvc, jobId, "QueueDeleteTimesheet");
} else {
SPLogger.Debug("Current period timesheet not exist");
}
} catch (Exception iex) {
SPLogger.Error(iex);
return -3;// error when delete existing timesheet
}
// create new timesheet
timesheetId = PrepareEmptyTimesheet(tsSvc, userId, managerId, periodId.Value, timesheetName);
currDS = tsSvc.ReadTimesheet(timesheetId.Value);
// copy value to new timesheet
List<Guid> lineIds = new List<Guid>();
foreach (DataRow row in prevDS.Lines.Rows) {
TimesheetDataSet.LinesRow p_line = (TimesheetDataSet.LinesRow)row;
TimesheetDataSet.LinesRow n_line = currDS.Lines.NewLinesRow();
n_line.TS_UID = timesheetId.Value;
n_line.TS_LINE_UID = Guid.NewGuid();
n_line.TS_LINE_CLASS_UID = p_line.TS_LINE_CLASS_UID;
n_line.TS_LINE_COMMENT = p_line.TS_LINE_COMMENT;
n_line.TS_LINE_CACHED_ASSIGN_NAME = p_line.TS_LINE_CACHED_ASSIGN_NAME;
n_line.TS_LINE_CACHED_PROJ_NAME = p_line.TS_LINE_CACHED_PROJ_NAME;
n_line.TS_LINE_VALIDATION_TYPE = p_line.TS_LINE_VALIDATION_TYPE;
n_line.TS_LINE_STATUS = p_line.TS_LINE_STATUS;
if (!p_line.IsASSN_UIDNull()) n_line.ASSN_UID = p_line.ASSN_UID;
currDS.Lines.AddLinesRow(n_line);
lineIds.Add(n_line.TS_LINE_UID);
tsSvc.PrepareTimesheetLine(timesheetId.Value, ref currDS, new Guid[] { n_line.TS_LINE_UID });
var b = from a in prevDS.Actuals.AsEnumerable()
where ((TimesheetDataSet.ActualsRow)a).TS_LINE_UID.Equals(p_line.TS_LINE_UID)
select (TimesheetDataSet.ActualsRow)a;
foreach (TimesheetDataSet.ActualsRow p_actual in b) {
TimesheetDataSet.ActualsRow n_actual = currDS.Actuals.FindByTS_LINE_UIDTS_ACT_START_DATE(n_line.TS_LINE_UID, p_actual.TS_ACT_START_DATE.AddDays(7));
if (n_actual != null) {
n_actual.TS_ACT_PLAN_VALUE = p_actual.TS_ACT_PLAN_VALUE;
n_actual.TS_ACT_VALUE = p_actual.TS_ACT_VALUE;
SPLogger.Debug("Update existing Actual Row");
} else {
n_actual = currDS.Actuals.NewActualsRow();
n_actual.TS_LINE_UID = n_line.TS_LINE_UID;
n_actual.TS_ACT_START_DATE = p_actual.TS_ACT_START_DATE.AddDays(7);
n_actual.TS_ACT_FINISH_DATE = p_actual.TS_ACT_FINISH_DATE.AddDays(7);
n_actual.TS_ACT_PLAN_VALUE = p_actual.TS_ACT_PLAN_VALUE;
n_actual.TS_ACT_VALUE = p_actual.TS_ACT_VALUE;
SPLogger.Debug(String.Format("New Actual Row added: id={0},start={1},finish={2},plan={3},actual={4}", n_actual.TS_LINE_UID, n_actual.TS_ACT_START_DATE, n_actual.TS_ACT_FINISH_DATE, n_actual.TS_ACT_PLAN_VALUE, n_actual.TS_ACT_VALUE));
currDS.Actuals.AddActualsRow(n_actual);
}
}
}
jobId = Guid.NewGuid();
tsSvc.QueueUpdateTimesheet(jobId, timesheetId.Value, currDS);
WaitForQueue(queueSvc, jobId, "QueueUpdateTimesheet");
SPLogger.Debug("Copy timesheet finished");
return 1; // success
}
private Guid? GetPeriodIdByTimesheetDataSet(TimesheetDataSet tsDS) {
return (tsDS.Headers.Rows.Count > 0) ? (Guid?)tsDS.Headers.Rows[0][tsDS.Headers.WPRD_UIDColumn] : null;
}
private Guid PrepareEmptyTimesheet(TimeSheet tsSvc, Guid resourceId, Guid managerId, Guid periodId, string timesheetName) {
SPLogger.Debug(String.Format("resId={0},mgrId={1},prdId={2}", resourceId, managerId, periodId));
TimesheetDataSet tsDS = new TimesheetDataSet();
TimesheetDataSet.HeadersRow header = tsDS.Headers.NewHeadersRow();
header.RES_UID = resourceId;
header.TS_UID = Guid.NewGuid();
header.WPRD_UID = periodId;
header.TS_NAME = timesheetName;
header.TS_COMMENTS = String.Empty;
header.TS_CREATOR_RES_UID = resourceId;
header.TS_ENTRY_MODE_ENUM = 0; //TimesheetEnum.EntryMode.Daily;
tsDS.Headers.AddHeadersRow(header);
// Create the timesheet with the default line types that are specified by the admin.
tsSvc.CreateTimesheet(tsDS, PreloadType.None);
return header.TS_UID;
}
private void WaitForQueue(QueueSystem queueSvc, Guid jobId, string jobName) {
JobState state;
bool done = false;
string xmlError = string.Empty;
SPLogger.Debug(String.Format("Job:{0} submitted, waiting on queue, estimate: {1} seconds", jobName, queueSvc.GetJobWaitTime(jobId)));
do {
state = queueSvc.GetJobCompletionState(jobId, out xmlError);
if (state == JobState.Success) {
done = true;
} else {
if (state == JobState.Unknown
|| state == JobState.Failed
|| state == JobState.FailedNotBlocking
|| state == JobState.CorrelationBlocked
|| state == JobState.Canceled) {
SPLogger.Error("Queue request error:" + xmlError);
throw new Exception(xmlError);
} else {
SPLogger.Debug("Sleep...");
System.Threading.Thread.Sleep(QUEUE_WAIT_TIME * 1000);
}
}
} while (!done);
}