ĐÀO TẠO DOANH NGHIỆP : SỞ KHOA HỌC CÔNG NGHỆ TỈNH ĐỒNG NAI

ENTERPRISE TRAINING: DONG NAI DEPARTMENT OF SCIENCE AND TECHNOLOGY.

HÌNH ẢNH TẬP HUẤN LỚP SHAREPOINT WORKFLOW VÀ KIẾN TRÚC SHAREPOINT

PHOTOS OF SHAREPOINT WORKFLOW AND ARCHITECTURE CLASS.

HÌNH ẢNH TẬP HUẤN LỚP SHAREPOINT WORKFLOW VÀ KIẾN TRÚC SHAREPOINT

PHOTOS OF SHAREPOINT WORKFLOW AND ARCHITECTURE CLASS.

Wednesday, March 7, 2012

Create Leave Form Application of Employees Apply Workflow Sequential To Approved Process


1.      Requirement: when an Item create and send to Boss1, then sent to Boss2.
2.      Process: Author was created Item sent to Boss1 and Boss2, after create successful Boss1 will receive one Task on Task List. Boss1 will approve it, then Boss2 will receive one similar Task on Task List and Boss2 will approve it. In the end, Boss1 and Boss2 approved, status of Item Leave Form is completed.
3.      Repair:
List: Employees, Holiday, TotalLeaveFormOfEmployeeLeaveForm.
Employees: store persional information of Employees.
Holiday: store holiday of year.
TotalLeaveFormOfEmployee: store Total holiday, Remain holiday, number holiday.
LeaveForm: store information leave form of Employees.
4.      Build
Create Item:
AcUser1 create new Item, system will test Total Leave Form default is 12 day, test remain holiday plus number holiday, if greater than Total Leave Form is alert as below (we must calculate saturday, Sunday and Holiday List)
Else, system will save item (don’t plus Saturday is ½ day and Sunday is 1 day)
The result is: number day is 1.5 day and workflow was initialed and status is in Progress. Boss1 and Boss2 will receive them task
Open Task List:
Only Boss1 with Item was created is LeaveFormTest see it, moreover  all users don’t see it.
Example: ItUser2 login will not see item
Now, Boss1 is ItUser1 login and see Task
Before approve, we will test total holiday of AcUser1 (Open List TotalLeaveFormOfEmployee)
Then Boss1 Edit Item and Completed
Then Boss2 Edit Item and Completed
We go back List LeaveForm and see status of Item is Completed

How to create code in NewForm.aspx
Open SPD | NewForm.aspx

1.        Import javascript:
<script type="text/javascript" src="../../JqueryLibrary/jquery-1.4.2.js"></script>
<script type="text/javascript" src="../../JqueryLibrary/jquery.SPServices-0.5.6.js"></script>
<script type="text/javascript" src="../../JqueryLibrary/jsFunction.js"></script>

2.        Declare variable
var idStartDate = "#ctl00_m_g_a941c007_3f57_4116_b13c_615f85871015_ctl00_ctl05_ctl01_ctl00_ctl00_ctl04_ctl00_ctl00_DateTimeField_DateTimeFieldDate";
 var idEndDate = "#ctl00_m_g_a941c007_3f57_4116_b13c_615f85871015_ctl00_ctl05_ctl02_ctl00_ctl00_ctl04_ctl00_ctl00_DateTimeField_DateTimeFieldDate";
var idNumberDay= "#ctl00_m_g_a941c007_3f57_4116_b13c_615f85871015_ctl00_ctl05_ctl06_ctl00_ctl00_ctl04_ctl00_ctl00_TextField";

3.        Hide Fied NumberDay
var hideControl=HideControl();
          function HideControl()
          {
                  $("#idAttachmentsRow").prev().css("display","none");
          }

4.        Get ID of Author who create Item Leave Form
function GetIDUser() {
              var idLookup = '';
              $().SPServices({
                  operation: "GetListItems",
                  async: false,
                  listName: "Employees",
                  CAMLQuery: '<Query><Where><Eq><FieldRef Name="UserName" /><Value Type="Integer"><UserID Type="Integer" /></Value></Eq></Where></Query>',
                  completefunc: function (xData, Status) {
                      //alert(xData.responseXML.xml);
                      $(xData.responseXML).find("z\\:row").each(function () {
                          idLookup = $(this).attr("ows_ID");
                          idLookup = idLookup.split(';');
                          idLookup = parseInt(idLookup[0]);
                      });
                  }
              });
              return idLookup;
          }


5.        Get total remain holiday of Employee
function GetTongNgayNghiConLaiCuaIDUser() {
              var tongNgayNghiConLai = 0;
              var idLookup = GetIDUser();
              //alert(idLookup);
              $().SPServices({
                  operation: "GetListItems",
                  async: false,
                  listName: "TotalLeaveFormOfEmployee",
                  CAMLQuery: '<Query><Where><Eq><FieldRef Name="Employee_x003a_ID" /><Value Type="Lookup">' + idLookup + '</Value></Eq></Where></Query>',
                  completefunc: function (xData, Status) {
                      //alert(xData.responseXML.xml);
                      $(xData.responseXML).find("z\\:row").each(function () {
                          tongNgayNghiConLai = $(this).attr("ows_TongNgayNghiConLai");
                          tongNgayNghiConLai = tongNgayNghiConLai.split('#');
                          tongNgayNghiConLai = tongNgayNghiConLai[1];
                          tongNgayNghiConLai = tongNgayNghiConLai.split('.');
                          tongNgayNghiConLai = tongNgayNghiConLai[0];

                      });
                  }
              });
              return tongNgayNghiConLai;
          }

6.        Function get day in week
function ConvertMonth(month) {
            var converThang = "";
            switch (month) {
                case "1":
                    converThang = "January";
                    break;
                case "2":
                    converThang = "February";
                    break;
                case "3":
                    converThang = "March";
                    break;
                case "4":
                    converThang = "April";
                    break;
                case "5":
                    converThang = "May";
                    break;
                case "6":
                    converThang = "June";
                    break;
                case "7":
                    converThang = "July";
                    break;
                case "8":
                    converThang = "August";
                    break;
                case "9":
                    converThang = "September";
                    break;
                case "10":
                    converThang = "October";
                    break;
                case "11":
                    converThang = "November";
                    break;
                case "12":
                    converThang = "December";
                    break;
                default:
                    converThang = "January";
                    break;
            }
            return converThang;
        }

7.        Caculate day Saturday (1/2 day), Sunday (1 day)
function TotalSaturdaySunDay(startDay, endDay, startMonth, startYear) {
            thuBay = 0;
            chuNhat = 0;

            for (var i = startDay; i <= endDay; i++) {
               
                //---------------------------Bat dau kiem tra ngay thu 7, chu nhat
                //Đổi tháng kiểu số thành tiếng anh
                thangEng = ConvertMonth(startMonth);
                //khai báo ngày tương úng với từng ngày được chạy từ for (20/11/2010, 21/11/2010 ...)
                var ngayNhanDangThuMay = new Date(i + " " + thangEng + " " + startYear);
                //Lấy ra gía trị của ngày ("01 February 2011" => 2: là thứ 3)
                thuMay = ngayNhanDangThuMay.getDay();
                //alert(i + " " + thangEng + " " + startYear + " so: " + thuMay);
                //Kiểm tra nếu giá trị là số 0: tương ứng là chủ nhật               
                if (thuMay == 0) {
                    //alert(i + " " + thangEng + " " + startYear + "chu nhat");
                    chuNhat += 1;
                }
                //Kiểm tra nếu giá trị là số 0: tương ứng là thứ 7
                if (thuMay == 6) {
                    //alert(i + " " + thangEng + " " + startYear + "thu 7");
                    thuBay += 0.5;
                }
            }
            var tongNgayThu7ChuNhat = thuBay + chuNhat;
            //alert(tongNgayThu7ChuNhat);
            return tongNgayThu7ChuNhat;
        }

8.        Get holiday in year
function TotalHoliday(startDay, endDay, month) {           
            var soNgayLe=0;
                              for(var i=startDay;i<=endDay;i++)
                              {
                  holiday=i+"/"+month;
                  $().SPServices({
                              operation: "GetListItems",
                              async: false,
                              listName: "Holiday",               
                              completefunc: function (xData, Status) {
                                  //alert(xData.responseXML.xml);
                                  $(xData.responseXML).find("z\\:row").each(function () {
                                      if(holiday== $(this).attr("ows_Day"))
                                      {
                                          soNgayLe+=1;
                                      }
                                  });
                              }
                          });
              }
              //alert(soNgayLe);
      return soNgayLe;
        }

9.        Calculate all holiday (leave day, Saturday, Sunday, holiday)
function SoNgayXinNghi() {
              //6/10/2011
              var startDate = $(idStartDate).val();
              startDate = startDate.split('/');
              //6/12/2011
              var endDate = $(idEndDate).val();
              endDate = endDate.split('/');

              startDay = startDate[1];
              startMonth = startDate[0];
              startYear = startDate[2];

              endDay = endDate[1];
              endMonth = endDate[0];
              endYear = endDate[2];
                             
              var totalSaturdaySunDay= TotalSaturdaySunDay(startDay,endDay,startMonth,startYear);
              var totalHoliday=TotalHoliday(startDay,endDay,startMonth);
              //alert(totalSaturdaySunDay);
              var soNgayXinNghi = endDay - startDay + 1 - totalSaturdaySunDay - totalHoliday;
              return soNgayXinNghi;
          }

10.     Call event PreSaveAction before save Item
function PreSaveAction() {
              if (SetNgayNghi() == true) {
                  return true;
              }
              else {
                  return false;
              }
          }

All Code:
<script type="text/javascript" src="../../JqueryLibrary/jquery-1.4.2.js"></script>
      <script type="text/javascript" src="../../JqueryLibrary/jquery.SPServices-0.5.6.js"></script>
      <script type="text/javascript" src="../../JqueryLibrary/jsFunction.js"></script>
      <script type="text/javascript">
          var idStartDate = "#ctl00_m_g_a941c007_3f57_4116_b13c_615f85871015_ctl00_ctl05_ctl01_ctl00_ctl00_ctl04_ctl00_ctl00_DateTimeField_DateTimeFieldDate";
          var idEndDate = "#ctl00_m_g_a941c007_3f57_4116_b13c_615f85871015_ctl00_ctl05_ctl02_ctl00_ctl00_ctl04_ctl00_ctl00_DateTimeField_DateTimeFieldDate";
                  var idNumberDay="#ctl00_m_g_a941c007_3f57_4116_b13c_615f85871015_ctl00_ctl05_ctl06_ctl00_ctl00_ctl04_ctl00_ctl00_TextField";
          var hideControl=HideControl();
          function HideControl()
          {
                  $("#idAttachmentsRow").prev().css("display","none");
          }
          function GetIDUser() {
              var idLookup = '';
              $().SPServices({
                  operation: "GetListItems",
                  async: false,
                  listName: "Employees",
                  CAMLQuery: '<Query><Where><Eq><FieldRef Name="UserName" /><Value Type="Integer"><UserID Type="Integer" /></Value></Eq></Where></Query>',
                  completefunc: function (xData, Status) {
                      //alert(xData.responseXML.xml);
                      $(xData.responseXML).find("z\\:row").each(function () {
                          idLookup = $(this).attr("ows_ID");
                          idLookup = idLookup.split(';');
                          idLookup = parseInt(idLookup[0]);
                      });
                  }
              });
              return idLookup;
          }

          function GetTongNgayNghiConLaiCuaIDUser() {
              var tongNgayNghiConLai = 0;
              var idLookup = GetIDUser();
              //alert(idLookup);
              $().SPServices({
                  operation: "GetListItems",
                  async: false,
                  listName: "TotalLeaveFormOfEmployee",
                  CAMLQuery: '<Query><Where><Eq><FieldRef Name="Employee_x003a_ID" /><Value Type="Lookup">' + idLookup + '</Value></Eq></Where></Query>',
                  completefunc: function (xData, Status) {
                      //alert(xData.responseXML.xml);
                      $(xData.responseXML).find("z\\:row").each(function () {
                          tongNgayNghiConLai = $(this).attr("ows_TongNgayNghiConLai");
                          tongNgayNghiConLai = tongNgayNghiConLai.split('#');
                          tongNgayNghiConLai = tongNgayNghiConLai[1];
                          tongNgayNghiConLai = tongNgayNghiConLai.split('.');
                          tongNgayNghiConLai = tongNgayNghiConLai[0];
                      });
                  }
              });
              return tongNgayNghiConLai;
          }

          var startDay = 0;
          var startMonth = 0;
          var startYear = 0;
          var endDay = 0;
          var endMonth = 0;
          var endYear = 0;

          function SetNgayNghi() {
              var ketQua = true;
              var soNgayXinNghi = SoNgayXinNghi();
              var tongSoNgayNghiConLai = GetTongNgayNghiConLaiCuaIDUser();
              if (tongSoNgayNghiConLai - soNgayXinNghi < 0) {
                  alert("Ngay nghi cua ban con lai: " + tongSoNgayNghiConLai + ". So ngay ban dang xin nghi la: " + soNgayXinNghi + ". Ban chi duoc xin <=" + tongSoNgayNghiConLai);
                  ketQua = false;
              }
              else
              {
                  $(idNumberDay).val(soNgayXinNghi);
              }
              return ketQua;
          }
                 
                  //**************************************************
                  function ConvertMonth(month) {
            var converThang = "";
            switch (month) {
                case "1":
                    converThang = "January";
                    break;
                case "2":
                    converThang = "February";
                    break;
                case "3":
                    converThang = "March";
                    break;
                case "4":
                    converThang = "April";
                    break;
                case "5":
                    converThang = "May";
                    break;
                case "6":
                    converThang = "June";
                    break;
                case "7":
                    converThang = "July";
                    break;
                case "8":
                    converThang = "August";
                    break;
                case "9":
                    converThang = "September";
                    break;
                case "10":
                    converThang = "October";
                    break;
                case "11":
                    converThang = "November";
                    break;
                case "12":
                    converThang = "December";
                    break;
                default:
                    converThang = "January";
                    break;
            }
            return converThang;
        }
                 
      function TotalSaturdaySunDay(startDay, endDay, startMonth, startYear) {
            thuBay = 0;
            chuNhat = 0;
            for (var i = startDay; i <= endDay; i++) {
                //---------------------------Bat dau kiem tra ngay thu 7, chu nhat
                //Đổi tháng kiểu số thành tiếng anh
                thangEng = ConvertMonth(startMonth);
                //khai báo ngày tương úng với từng ngày được chạy từ for (20/11/2010, 21/11/2010 ...)
                var ngayNhanDangThuMay = new Date(i + " " + thangEng + " " + startYear);
                //Lấy ra gía trị của ngày ("01 February 2011" => 2: là thứ 3)
                thuMay = ngayNhanDangThuMay.getDay();
                //alert(i + " " + thangEng + " " + startYear + " so: " + thuMay);
                //Kiểm tra nếu giá trị là số 0: tương ứng là chủ nhật               
                if (thuMay == 0) {
                    //alert(i + " " + thangEng + " " + startYear + "chu nhat");
                    chuNhat += 1;
                }
                //Kiểm tra nếu giá trị là số 0: tương ứng là thứ 7
                if (thuMay == 6) {
                    //alert(i + " " + thangEng + " " + startYear + "thu 7");
                    thuBay += 0.5;
                }
            }
            var tongNgayThu7ChuNhat = thuBay + chuNhat;
            //alert(tongNgayThu7ChuNhat);
            return tongNgayThu7ChuNhat;
        }
        
        //**************************************************
                  function TotalHoliday(startDay, endDay, month) {           
            var soNgayLe=0;
                              for(var i=startDay;i<=endDay;i++)
                              {
                  holiday=i+"/"+month;
                  $().SPServices({
                              operation: "GetListItems",
                              async: false,
                              listName: "Holiday",               
                              completefunc: function (xData, Status) {
                                  //alert(xData.responseXML.xml);
                                  $(xData.responseXML).find("z\\:row").each(function () {
                                      if(holiday== $(this).attr("ows_Day"))
                                      {
                                          soNgayLe+=1;
                                      }
                                  });
                              }
                          });
              }
              //alert(soNgayLe);
          return soNgayLe;
        }
                 
          function SoNgayXinNghi() {
              //6/10/2011
              var startDate = $(idStartDate).val();
              startDate = startDate.split('/');
              //6/12/2011
              var endDate = $(idEndDate).val();
              endDate = endDate.split('/');
              startDay = startDate[1];
              startMonth = startDate[0];
              startYear = startDate[2];
              endDay = endDate[1];
              endMonth = endDate[0];
              endYear = endDate[2];
              var totalSaturdaySunDay= TotalSaturdaySunDay(startDay,endDay,startMonth,startYear);
              var totalHoliday=TotalHoliday(startDay,endDay,startMonth);
              //alert(totalSaturdaySunDay);
              var soNgayXinNghi = endDay - startDay + 1 - totalSaturdaySunDay - totalHoliday;
              return soNgayXinNghi;
          }

          function PreSaveAction() {
              if (SetNgayNghi() == true) {
                  return true;
              }
              else {
                  return false;
              }
          }
      </script>

How to create workflow approval
Creating the Initial Project
The following steps show how to create the workflow project and set the workflow's general attributes. The attributes you set include the SharePoint site and the document library that the workflow will be associated with, and how a new workflow starts.
To create the initial project
1.        Open Visual Studio and create a new project.
2.        Select the Office project type node, and then click the Sequential Workflow template.
3.        Name the project WF_LeaveForm, and then click OK.
4.        In the first New Office SharePoint Workflow dialog box, provide a user-friendly name for the workflow (for example, Simple Document Review), and then provide a valid SharePoint site URL to use for debugging the workflow.
5.        Enter name and choice radio List Workflow
6.        In the second New Office SharePoint Workflow dialog box, select the library, history list, and task list that Visual Studio will associate with your workflow when debugging.
7.        In the final New Office SharePoint Workflow dialog box, check is created and is changed, and then click Finish.
8.        If you make a mistake or change your mind about the initial settings, you can access the initial workflow dialog boxes to make changes at any time by selecting the project in Solution Explorer, and then clicking the ellipsis in the TargetSite property (some of the other properties also exhibit this behavior).
Visually Designing the Workflow
To design a workflow, drag activities from the SharePoint Workflow and Windows Workflow v3.0 tabs in the Toolbox to the designer work surface. For the simple document workflow, you will use a couple CreateTask activities, a couple OnTaskChanged activities, and a couple While activities. To lay out the simple sequential document review workflow, perform the following steps.
To design a workflow
1.        In the Toolbox, do the following:
a.        Drag a CreateTask activity from the SharePoint Workflow tab onto the design surface directly under the OnWorkflowActivated1 activity.
b.        Drag a While activity from the Windows Workflow v3.0 tab onto the design surface, under the CreateTask1 activity.
c.        Drag an OnTaskChanged activity to within WhileActivity1, on top of the text that reads Drop an Activity Here.
d.        Drag another CreateTask activity to under (not inside of) WhileActivity1
e.        Drag another While activity to under CreateTask2
f.         Drag another OnTaskChanged activity into WhileActivity2
g.        Drag another code.
h.        Drag another logToHistoryListActivity1.
2.        Set the properties that are associated with CreateTask1, as follows:
a.        Select the CreateTask1 activity, and rename it CreateTechReviewTask
b.        Create a task correlation token by entering TechReviewToken in the CorrelationToken property; a PLUS SIGN (+) appears next to the CorrelationToken property. Click the PLUS SIGN to view the OwnerActivityName property and set this property to Workflow1
c.        Click the ellipsis in the TaskId property.
d.        On the Bind to a new member tab, click Create Field, and then click OK. (Note the name of the new field.) 
e.        Click the ellipsis in the TaskProperties property. 
f.         On the Bind to a new member tab, click Create Field, and then click OK. (Note the name of the new field.)
  1. Set the properties that are associated with CreateTask2 by repeating steps 2a–e, with the following exceptions:
    1. Rename CreateTask2 to CreateEditorialReviewTask
    2. Create a correlation token named EditorialReviewToken in the CorrelationToken property. 
    3. Set the OwnerActivityName property to Workflow1.
                          
                          
                          

  1. Set the properties that are associated with OnTaskChanged1, as follows:
    1. Select OnTaskChanged1, and then rename it OnTechReviewTaskChanged
    2. Set the CorrelationToken property to TechReviewToken
                           
  1. Bind the AfterProperties property field to a new field (similar to steps 2e–f). 
                           
  1. Set the properties associated with onTaskChanged2.
    1. Select OnTaskChanged2, and then rename it OnEditorialReviewTaskChanged
    2. Set the CorrelationToken property to EditorialReviewToken
                           
  1. Bind the AfterProperties property field to a new field (similar to steps 2e–f). 
                           
  1. Set the properties associated with Code.
    1. Select code, and then rename it UpdateNumberLeaveForm
  2. Set the properties associated with logToHistoryListActivity1.
    1. Select logToHistoryListActivity1, and then rename it logToHistoryListActivity1
    2. Right click logToHistoryListActivity1
      1. HistoryDescription select var is logDescription
      2. HistoryOutCome select var is logOutCome

Correlation tokens are an important concept associated with developing workflows. Correlation tokens are used to group associated, related activities in an activity. Correlation tokens are important to understand because if you do not assign correlation tokens correctly, your workflow might not work as you expect. Specifically, events associated with activities might not receive event notifications. By default, a workflow token is created as part of creating a workflow project. You should also create a new token for each task that is created as part of a workflow. Then, for each activity associated with a given task, set the correlation token equal to the correlation token associated with the task.
Another important concept associated with the previous steps is that of BeforePropertiesAfterProperties, and TaskPropertiesTaskProperties is a property of a CreateTask activity.BeforeProperties and AfterProperties are properties used by an OnTaskChanged activity. All of these items are Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties objects. AnSPWorkflowTaskProperties object contains properties and methods that enable you to affect the fields associated with a given task item. For example, by using an SPWorkflowTaskPropertiesobject, you can assign the task to someone, set the due date, or determine the percent complete. BeforePropertiesAfterProperties, and TaskProperties are all point-in-time objects. That is, the values do not change as the task changes. For an OnTaskChanged activity, BeforeProperties represent the state of a task item before changes were made; AfterProperties represent the state of the task item after the changes were made. For a CreateTask activity, TaskProperties provides you with a way to set the initial properties of the task item when it is created. This is demonstrated later in this article.
Creating Task Items
Although you can set some of the properties of a CreateTask activity by using the designer, it is likely that many of the actual values used to set up the task need to be determined programmatically. To do this, associate an event handler with the CreateTask activity.
To associate an event handler with the CreateTask activity
1.        Select the createTechReviewTask and view the events associated with the activity in the Properties window.
2.        Double-click the MethodInvoking handler to generate an event handler stub that will respond to the MethodInvoking event that occurs before the activity is executed.
3.        Add the following code to the event handler to set the task identifier for the task, and set the due date for the following day.
            CreateTechReviewTask_TaskId1 = Guid.NewGuid();
            CreateTechReviewTask_TaskProperties1.AssignedTo = GetUserApproved("Boss1");
            CreateTechReviewTask_TaskProperties1.PercentComplete = 1;
            CreateTechReviewTask_TaskProperties1.DueDate = DateTime.Now.AddDays(1.0);
            CreateTechReviewTask_TaskProperties1.Title = "Boss1 Approved";
4.        Perform the same steps for the createEditorialReview activity, but add the following code to the event handler.
            CreateEditorialReviewTask_TaskId1 = Guid.NewGuid();
            CreateEditorialReviewTask_TaskProperties1.AssignedTo = GetUserApproved("Boss2");
            CreateEditorialReviewTask_TaskProperties1.PercentComplete = 1;
            CreateEditorialReviewTask_TaskProperties1.DueDate =        DateTime.Now.AddDays(1.0);
            CreateEditorialReviewTask_TaskProperties1.Title = "Boss2 Approved";

Waiting for Tasks to Complete
In task-based workflows such as the simple document review workflow discussed in this article, While activities are used to implement the loop needed to watch for task-changed activities, and to see whether a task was marked as complete. To use a While activity, drag a While activity onto the design surface, and then drag any activities that you want to execute repetitively until the Whileactivity terminates and drop them in the While activity.
There are two methods for terminating a While activity: using a code condition or using a declarative rule condition. To use a code condition, add a procedure to the project that sets a Boolean result flag to true or false. To use a declarative rule condition, add a rule to the project. In each pass through the While activity, the rule is evaluated to determine whether the terminating condition was met.
To show how to use both methods for terminating a While activity, we use a code condition for the While activity that is associated with the technical review task and a declarative rule condition for the While activity associated with the editorial review task.
To terminate a While activity
1.        Implement the terminating condition of whileActivity1, as follows:
a.        Switch to the code view and add the following code to Workflow1.cs

        private bool bTaskNotFinished = true;
        private void TaskNotFinished(object sender, System.Workflow.Activities.ConditionalEventArgs e)
        {
            e.Result = bTaskNotFinished;
        }

b.        Switch back to the workflow designer and select the onTechReviewTaskChanged activity. 
c.        Click the Events button in the Properties window to see the events that are associated with onTechReviewTaskChanged. 
d.        Double-click the Invoked event to generate a handler for it. 
e.        Add the following code to the onTechReviewTaskChanged_Invoked handler. 

private void OnTechReviewTaskChanged_Invoked(object sender, ExternalDataEventArgs e)
        {
            if (OnTechReviewTaskChanged_AfterProperties1.PercentComplete == 1.0)
            {
                bTaskNotFinished = false;
            }
        }

f.         Switch back to the workflow designer, and then select the whileActivity1 activity. 
g.        Set the Condition property to Code Condition. 
h.        Click the PLUS SIGN (+) , and then set the subsequent Condition property to TaskNotFinished.
2.        Implement the terminating condition of whileActivity2, as follows:
a.        Select the onEditorialReviewTaskChanged activity in the designer, and then generate an event handler for the Invoked event.
b.       Add a class-level Boolean variable named bEditorialTaskNotFinished to the class.
private bool bEditorialTaskNotFinished = true;
c.        Add the following code to the onEditorialReviewTaskChanged_Invoked event handler.

private void OnEditorialReviewTaskChanged_Invoked(object sender, ExternalDataEventArgs e)
        {
         if (OnEditorialReviewTaskChanged_AfterProperties1.PercentComplete == 1.0)
            {
                bEditorialTaskNotFinished = false;
            }
        }

d.        Switch back to the workflow designer, and then select the whileActivity2 activity.
e.        Set the Condition property to Declarative Rule Condition.
f.         Expand the Condition property. 
g.   Click the ellipsis in the ConditionName property to open the Select Condition dialog box.
Use the Select Condition dialog box to create declarative rule conditions
        
a.    Click New, enter the condition shown in the following figure, and then click OK.
Example of a declarative rule condition
       

b.    Click OK in the Select Condition dialog box.
 Successfully created declarative rule condition


3.        Implement code UpdateNumberLeaveForm_ExecuteCode, as follows:
private void UpdateNumberLeaveForm_ExecuteCode(object sender, EventArgs e)
        {
            int id = 0;
            try
            {
                using (SPWeb spWeb = workflowProperties.Web)
                {
                    spWeb.AllowUnsafeUpdates = true;
                    SPList spList = workflowProperties.List;
                    SPListItem spListItem = workflowProperties.Item;
                    //Search Author in Employees List
                    string author = Convert.ToString(spListItem["Author"]);

                    SPList spListEmployee = spWeb.Lists["Employees"];
                    SPListItemCollection itemEmployees = spListEmployee.Items;
                    foreach (SPListItem item in itemEmployees)
                    {
                        if (Convert.ToString(item["UserName"]) == author)
                        {
                            id = Convert.ToInt32(item["ID"]);
                            break;
                        }
                    }
                    //
                    this.logDescription += "ID author in List Employees: " + id.ToString() + "--- Boss1" + spListItem["Boss1"] + "--- Boss2" + spListItem["Boss2"];
                    SPList spListNumberLeaveForm = spWeb.Lists["TotalLeaveFormOfEmployee"];
                    SPListItemCollection itemNumberLeaveForm = spListNumberLeaveForm.Items;
                    foreach (SPListItem item in itemNumberLeaveForm)
                    {
                        string[] idLookup = (Convert.ToString(item["Employee_x003a_ID"])).Split(';');

                        if (Convert.ToInt32(idLookup[0]) == id)
                        {
                            item["SoNgayDaNghi"] =
                                Convert.ToDouble(item["SoNgayDaNghi"]) + Convert.ToDouble(spListItem["NumberDay"]);
                            item.Update();
                            this.logDescription += "---ID UserName in List TotalLeaveFormOfEmployee: " + item["Employee_x003a_ID"];
                            break;
                        }
                    }                   
                    spWeb.AllowUnsafeUpdates = false;
                }
            }
            catch (Exception ex)
            {
                this.logOutCome = ex.Message;
            }                      
        }

        private string GetUserApproved(string fieldNameUser)
        {
            string userApproved;
            using (SPWeb spWeb = workflowProperties.Web)
            {
                spWeb.AllowUnsafeUpdates = true;
                SPList spList = workflowProperties.List;
                SPListItem spListItem = workflowProperties.Item;
                //Search Author in Employees List
                string[] arrayUserApproved = (Convert.ToString(spListItem[fieldNameUser])).Split('#');;
                userApproved = arrayUserApproved[1];
            }
            return userApproved;
        }
All Code:
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections;
using System.Drawing;
using System.Linq;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Serialization;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Workflow.Runtime;
using System.Workflow.Activities;
using System.Workflow.Activities.Rules;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Workflow;
using Microsoft.SharePoint.WorkflowActions;

namespace WF_LeaveForm.Workflow1
{
    public sealed partial class Workflow1 : SequentialWorkflowActivity
    {
        public Workflow1()
        {
            InitializeComponent();
        }
        public string logDescription = "";
        public string logOutCome = "";

        public Guid workflowId = default(System.Guid);
        public SPWorkflowActivationProperties workflowProperties = new SPWorkflowActivationProperties();
        public Guid CreateTechReviewTask_TaskId1 = default(System.Guid);
        public SPWorkflowTaskProperties CreateTechReviewTask_TaskProperties1 = new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();
        public Guid CreateEditorialReviewTask_TaskId1 = default(System.Guid);
        public SPWorkflowTaskProperties CreateEditorialReviewTask_TaskProperties1 = new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();
        public SPWorkflowTaskProperties OnTechReviewTaskChanged_AfterProperties1 = new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();
        public SPWorkflowTaskProperties OnEditorialReviewTaskChanged_AfterProperties1 = new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();

        private void onWorkflowActivated1_Invoked(object sender, ExternalDataEventArgs e)
        {
            this.workflowId = workflowProperties.WorkflowId;
        }

        private void CreateTechReviewTask_MethodInvoking(object sender, EventArgs e)
        {
            CreateTechReviewTask_TaskId1 = Guid.NewGuid();
            CreateTechReviewTask_TaskProperties1.AssignedTo = GetUserApproved("Boss1");
            CreateTechReviewTask_TaskProperties1.PercentComplete = 1;
            CreateTechReviewTask_TaskProperties1.DueDate = DateTime.Now.AddDays(1.0);
            CreateTechReviewTask_TaskProperties1.Title = "Boss1 Approved";
        }

        private void CreateEditorialReviewTask_MethodInvoking(object sender, EventArgs e)
        {
            CreateEditorialReviewTask_TaskId1 = Guid.NewGuid();
            CreateEditorialReviewTask_TaskProperties1.AssignedTo = GetUserApproved("Boss2");
            CreateEditorialReviewTask_TaskProperties1.PercentComplete = 1;
            CreateEditorialReviewTask_TaskProperties1.DueDate = DateTime.Now.AddDays(1.0);
            CreateEditorialReviewTask_TaskProperties1.Title = "Boss2 Approved";
        }

        private bool bTaskNotFinished = true;
        private void TaskNotFinished(object sender, System.Workflow.Activities.ConditionalEventArgs e)
        {
            e.Result = bTaskNotFinished;
        }

        private void OnTechReviewTaskChanged_Invoked(object sender, ExternalDataEventArgs e)
        {
            if (OnTechReviewTaskChanged_AfterProperties1.PercentComplete == 1.0)
            {
                bTaskNotFinished = false;
            }
        }
        private bool bEditorialTaskNotFinished = true;

        private void OnEditorialReviewTaskChanged_Invoked(object sender, ExternalDataEventArgs e)
        {
            if (OnEditorialReviewTaskChanged_AfterProperties1.PercentComplete == 1.0)
            {
                bEditorialTaskNotFinished = false;
            }
        }

        private void UpdateNumberLeaveForm_ExecuteCode(object sender, EventArgs e)
        {
            int id = 0;
            try
            {
                using (SPWeb spWeb = workflowProperties.Web)
                {
                    spWeb.AllowUnsafeUpdates = true;
                    SPList spList = workflowProperties.List;
                    SPListItem spListItem = workflowProperties.Item;
                    //Search Author in Employees List
                    string author = Convert.ToString(spListItem["Author"]);

                    SPList spListEmployee = spWeb.Lists["Employees"];
                    SPListItemCollection itemEmployees = spListEmployee.Items;
                    foreach (SPListItem item in itemEmployees)
                    {
                        if (Convert.ToString(item["UserName"]) == author)
                        {
                            id = Convert.ToInt32(item["ID"]);
                            break;
                        }
                    }
                    //
                    this.logDescription += "ID author in List Employees: " + id.ToString() + "--- Boss1" + spListItem["Boss1"] + "--- Boss2" + spListItem["Boss2"];
                    SPList spListNumberLeaveForm = spWeb.Lists["TotalLeaveFormOfEmployee"];
                    SPListItemCollection itemNumberLeaveForm = spListNumberLeaveForm.Items;
                    foreach (SPListItem item in itemNumberLeaveForm)
                    {
                        string[] idLookup = (Convert.ToString(item["Employee_x003a_ID"])).Split(';');

                        if (Convert.ToInt32(idLookup[0]) == id)
                        {
                            item["SoNgayDaNghi"] =
                                Convert.ToDouble(item["SoNgayDaNghi"]) + Convert.ToDouble(spListItem["NumberDay"]);
                            item.Update();
                            this.logDescription += "---ID UserName in List TotalLeaveFormOfEmployee: " + item["Employee_x003a_ID"];
                            break;
                        }
                    }                   
                    spWeb.AllowUnsafeUpdates = false;
                }
            }
            catch (Exception ex)
            {
                this.logOutCome = ex.Message;
            }                      
        }

        private string GetUserApproved(string fieldNameUser)
        {
            string userApproved;
            using (SPWeb spWeb = workflowProperties.Web)
            {
                spWeb.AllowUnsafeUpdates = true;
                SPList spList = workflowProperties.List;
                SPListItem spListItem = workflowProperties.Item;
                //Search Author in Employees List
                string[] arrayUserApproved = (Convert.ToString(spListItem[fieldNameUser])).Split('#');;
                userApproved = arrayUserApproved[1];
            }
            return userApproved;
        }
    }
}
Debugging the Workflow

Debugging SharePoint workflows is a particularly satisfying experience with Visual Studio 2008 versus previous versions, in which the debugging process was manual. After compiling, you had to deploy the workflow manually, recycle Microsoft Internet Information Services (IIS), attach the Visual Studio debugger to the W3WP process, open Internet Explorer, navigate to the correct document library, and associate the workflow with the library. With Visual Studio 2008, you simply press F5 and Visual Studio handles all of that for you. All you need to do is trigger a new instance of the workflow by adding an item to the list that the workflow is associated with (assuming you set up the workflow to start automatically when new items are added).
There is one thing to note about debugging workflows. Because you will be looking at Internet Explorer often while debugging the workflow, it is tempting to close the Internet Explorer window when you are finished debugging. But instead of closing the Internet Explorer window, it is best to stop debugging from Visual Studio. When you stop the debugging process, Visual Studio closes the Internet Explorer window for you.