Take the 2-minute tour ×
SharePoint Stack Exchange is a question and answer site for SharePoint enthusiasts. It's 100% free, no registration required.

Code share, and looking for better solution. 1. use ribbon bar button to call the page by ajax. 2. reload current page.

Question: 1. After the queueSvc return JobState.Success, the timesheet still not available, we had to uglily wait another 10 seconds before reload the page.

share|improve this question

1 Answer 1

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);
}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.