How the ISO process of Preventive and Corrective Actions is implemented

  • Edit

Preventive and Corrective Actions Process Automation

This application is about the "Preventive and Corrective Actions Management" as it would be described in the "ISO procedure" of any kind of company. The requirement for the application is to automate the "procedure" of "Preventive and Corrective Actions". This means that the successive "steps" of the procedure are automatically forwarded from one employee to another without any kind of "manager" intervention (the "procedure" is the manager). At any time the manager has the ability to see on what tasks (steps) the employees are engaged. He can also see what tasks are "scheduled" for the next days. After a certain period of time, the manager has a complete report on what tasks each employee has been assigned, when has started and when has finished the tasks.


The requirements, put on the application for the "Preventive and Corrective Actions Procedure", are the following:


"1. Every employee can start the "New Preventive and Corrective Actions" in order to fill in the appropriate form. In this form the employee puts the subject, describes the problem and its causes. He/She can also fill in the corrective actions and the employees that have to take those actions.

2. After posting the form a task is assigned to "Quality Assurance Manager" in order to fill in the form of the names of the associates that must approve those actions.

3. The forwarding of the form from "Quality Assurance Manager" goes to each associate (in parallel) that they have to approve or reject the described actions.

4. If all of the assigned associates, for approval or rejection,  approve the required actions the procedure forwards tasks to every associate (employee) that is assigned for the execution of the corrective activities. (those tasks are assigned in parallel).

5. After all of the employees execute the required actions (filling in and some comment) then the procedure terminates"


All of the above requirements are put on a coordinator agent. The action_code of the agent is the following:



     id = __params[1]

     call bpm_setprocedureowner(__activation_user) {.....set the procedure owner}

     num = SelectFrom("SELECT MAX(PNUM) FROM P10003_PREV_CORR")
     num = num + 1
     call UpdateField("P10003_PREV_CORR",id,"PNUM",num,"PDATE",crDate)

     comm = LookUpId("P10003_PREV_CORR",id,"PSUBJECT")
     call bpm_setprocedurecomment(comm) {.....set the procedures comment}

     {.....fill in the form from the activating assosiate..............................}
     call bpm_openatonce()
     callwait bpm_assign_job("Peventive and Corrective Action",__activation_user,"",0,id)

     {.....catalog of approving associates....................}
     callwait bpm_assign_job("Approvals for the Corrective Actions","","QUALITY ASSURANCE MANAGER",0,id)

     {...........get the group of approving associates.....................}
     start_sql "*" "KOSMOS"
          WHERE (PREV_CORR = :A)
     q = QueryByName()
     call TSetParam(q,"A",id)
     call TExecute(q)
     appr_count = TRecordCount(q)
     call TFirst(q)
     for i = 1 to appr_count
          appr_name[i] = TGetFld(q,"AU_USER")
          appr_name[i] = LookUpId("AU_USER",appr_name[i],"UNAME")
          appr_id[i] = TGetFld(q,"PREV_CORR_APPR")
          call TNext(q)
     call FreeEmbSQL(q)

     {...........sent tasks for approving (parallel execution)......................}
     split_for i = 1 to appr_count

          callwait bpm_assign_job("Approval/Rejection of Corrective Actions", appr_name[i], "", 0, id, appr_id[i] )

          appr_flag[i] = LookUpId("P10003_PREV_CORR_APPR",appr_id[i],"YES_FLAG")


     {.....does everybody has approved?.....}
     flag = 1
     for i = 1 to appr_count

          if (appr_flag[i] <> "1") then
               flag = 0


     {.......get the group of correction associates..................................}
     start_sql "*" "KOSMOS"
          SELECT * FROM P10003_PREV_CORR_EXE
          WHERE (PREV_CORR = :A)
     q = QueryByName()
     call TSetParam(q,"A",id)
     call TExecute(q)
     corr_count = TRecordCount(q)
     call TFirst(q)
     for i = 1 to corr_count
          corr_name[i] = TGetFld(q,"AU_USER")
          corr_name[i] = LookUpId("AU_USER",corr_name[i],"UNAME")
          corr_id[i] = TGetFld(q,"PREV_CORR_EXE")
          call TNext(q)
     call FreeEmbSQL(q)

     {.....if everybody has approved send the tasks to correction assosiates......}
     if (flag = 1) then

          {...............correction in parallel split......................}
          split_for i = 1 to corr_count

               callwait bpm_assign_job("Corrective Action", corr_name[i], "", 0, id, corr_id[i] )

               corr_flag[i] = LookUpId("P10003_PREV_CORR_EXE",corr_id[i],"YES_FLAG")




We can see the callwait and split_for keywords. Those keywords give the opportunity to the agent to wait (until a job has been finished) or to have parallel code execution (for an undefined initially number of parallel tasks). Those are capabilities that are not presented every day in a programming language (ok script!). Notice that the callwait "calls" the user's activity as it would be a "program's subroutine". Notice also that we have a flow of procedure that is defined by conditions into the code. This is a case of ad hoc control flow (not known in advance to the programmer!)


We have to admit that the effect (coordination and historic data collection of the procedure) is far too big for the lines of code that are written by the application programmer. To be precise the code is a little bigger (the agent contains the code that "describes" the task (activities) assigned to employees). 

The agent (agent prototype precisely) can be viewed form Right Mouse Click on Application's Background->Developer->Resources->Agent Prototypes. The system creates, for every "service" requested, a new "alive" agent that starts to execute his action_code.


Where we define users and roles?


Another issue is that the jobs are assigned to users (employees) not only by name but also (and mainly) by their roles into the company. The users and roles as they are defined into the application can be found at Menu->System->Users/Positions.


How we activate the agent?


A "new preventive and corrective action" can be activated on the application from the "New Action" button in the left on the application window. In order the users see the activities (jobs) that are assigned to them exit the demo application and log in as the user in question. 


How can the user see the incoming jobs?


Every user has the incoming activities window defined as "Tasks" in the menu. Notice that the same activity is sent to all users that happen to have the same role in the company or organization. When the user "completes" the data that the activity required, he/she "forwards" the completed activity to the next step. Then the activity disappears from the window.


In order, a user to see activities that assigned to him for today or are uncompleted from yesterday he/she has to activate "Finished Tasks".


How the manager can see the current jobs?


By activating Menu->CPO Control Panel->Active Tasks we see every activity (job) that is assigned at the time and is in the phase of completion, i.e. presented to users "incoming activities" and are worked by them.


How we can evaluate our employees?


When we activate Menu->System->Associates we can see a button captioned "Has Done". By activating it we get all the activities that the user (employee) has finished and by which role. The time of staring and completing each activity is also available. This way the real effort that the user has given to the company can be estimated.


How we can improve the demo application?


The demo application comes with "Developer" capabilities. That means we have the opportunity to change the database schema (Right Click->Developer->Resources->Database Manager->Edit Schema). We can also change the forms (Right Click over a form->Designing).