Beispiel #1
0
        public static void InitNewDB(OdbcConnection conn)
        {
            // Creates one process, one subpr, one user
            IProcess    Ipr    = new IProcess(conn);
            ISubProcess Isubpr = new ISubProcess(conn);
            IUser       Iuser  = new IUser(conn);

            int IDprocessCCM = HELPERS.FindProcess(conn, "CCM", true);
            int IDsubpr      = HELPERS.FindSubProcess(conn, IDprocessCCM, "Pricing", true);
            int IDuser       = HELPERS.FindUser(conn, "E16034", "David Sklar", true);
        }
Beispiel #2
0
        // User wants to create a new subprocess
        protected void Button1_Click(object sender, EventArgs e)
        {
            if (!AuthCheck())
            {
                Server.Transfer("AuthFail.html");
                return;
            }


            int            IDprocess;
            OdbcConnection conn = HELPERS.NewOdbcConn();
            string         newname;
            string         processname;

            // New process or existing process?
            if (ChooserProcess.SelectedItem != null)
            {
                // Existing process!
                IDprocess   = int.Parse(ChooserProcess.SelectedItem.Value);
                processname = ChooserProcess.SelectedItem.Text;
            }
            else
            {
                IProcess Iprc = new IProcess(conn);
                newname     = ChooserProcess.Text.Trim();
                processname = newname;
                if (newname.Length < 2)
                {
                    throw new Exception("Name for new process is empty or too brief.");
                }
                IDprocess = Iprc.NewProcess(newname);
            }

            // Create the new subprocess

            ISubProcess Isprc = new ISubProcess(conn);

            newname = this.TextBox_NewSubprocess.Text.Trim();
            if (newname.Length < 2)
            {
                throw new Exception("Name for new subprocess is empty or too brief.");
            }
            int IDsubprocess = Isprc.NewSubProcess(newname, IDprocess);

            Isprc.SetSubProcess(IDsubprocess, newname, IDprocess, "Active");

            // New subprocess now created.  Record this with the session.
            LogInToSubprocess(IDsubprocess,
                              processname, newname);

            Response.Redirect("HOME.aspx");
        }
Beispiel #3
0
        // This is still in use, even with the new GUI, as of Oct2009
        private void Grid1_UpdateCommand(object sender, ComponentArt.Web.UI.GridItemEventArgs e)
        {
            int    idSubpr     = int.Parse(e.Item["c_id"] as string);
            int    idProcess   = int.Parse(e.Item["IdOfProcess"] as string);
            string nameSubpr   = e.Item["NameOfSubprocess"] as string;
            string namePr      = e.Item["NameOfProcess"] as string;
            string statusSubpr = e.Item["StatusOfSubprocess"] as string;
            string descrPr     = e.Item["DescrOfProcess"] as string;

            IProcess    engineProcess    = new IProcess(HELPERS.NewOdbcConn());
            ISubProcess engineSubProcess = new ISubProcess(HELPERS.NewOdbcConn());

            engineProcess.SetProcess(idProcess, namePr, descrPr);
            engineSubProcess.SetSubProcess(idSubpr, nameSubpr, idProcess, statusSubpr);
        }
Beispiel #4
0
        private void LoadSubProcesses(int idProc, TreeViewNode nodeProc)
        {
            ISubProcess engineProcess = new ISubProcess(HELPERS.NewOdbcConn());

            returnListSubProcessByProcess[] allprocs = engineProcess.ListSubProcessByProcess
                                                           (null, "\"Status\" = ?", new string[] { "Active" }, "c_u_Name asc", idProc);
            foreach (returnListSubProcessByProcess cur in allprocs)
            {
                ComponentArt.Web.UI.TreeViewNode rootNode = new ComponentArt.Web.UI.TreeViewNode();
                rootNode.Text               = cur.Name;
                rootNode.Expanded           = false;
                rootNode.ImageUrl           = "folder.gif";
                rootNode.ShowCheckBox       = true;
                rootNode.ID                 = "SP/" + cur.ID;
                rootNode.ContentCallbackUrl = "XMLtree_RolesInSubprocess.ashx?subproc=" + cur.ID;

                nodeProc.Nodes.Add(rootNode);
            }
        }
Beispiel #5
0
        public static int FindSubProcess
            (OdbcConnection conn, int IDprocessCCM, string name, bool buildIfNeeded)
        {
            ISubProcess Ispr = new ISubProcess(conn);

            returnListSubProcess[] ret =
                Ispr.ListSubProcess(null, "\"Name\" like ?", new string[] { name }, "");
            if (ret.Length == 1)
            {
                return(ret[0].ID);
            }
            else
            {
                if (buildIfNeeded)
                {
                    return(Ispr.NewSubProcess(name, IDprocessCCM));
                }
                else
                {
                    throw new System.NullReferenceException("No subprocess found with this name: " + name);
                }
            }
        }
        /// <summary>
        /// Returns the script ID for the named script
        /// </summary>
        /// <param name="scriptNameHex">The name of the script.  The caller must ensure that this is unique</param>
        /// <param name="recompileIfOlderThen">If the pre-compiled script is older then this date, then it's recompiled</param>
        /// <param name="loadScript">Delegate used to load the script</param>
        /// <param name="subProcess">The sub process to compile or load the script in</param>
        /// <returns></returns>
        public int GetScriptID(string scriptName, string md5, string script, ISubProcess subProcess)
        {
            // Unfortunately, all of this data won't fit in a name-value-pairs file
            // This is a quick-and-dirty way to keep filenames valid
            string scriptNameHex = StringGenerator.ToHexString(Encoding.Unicode.GetBytes(scriptName));

            string storedJSONobject = null;
            using (TimedLock.Lock(CompiledJavascriptCache))
                if (CompiledJavascriptCache.IsFilePresent(scriptNameHex))
                    storedJSONobject = CompiledJavascriptCache.OpenFile(scriptNameHex).CastFileHandler<ITextHandler>().ReadAll();

            Dictionary<string, object> precompiled = null;
            if (null != storedJSONobject)
                if (storedJSONobject.Length > 0)
                {
                    precompiled = JsonReader.Deserialize<Dictionary<string, object>>(storedJSONobject);

                    if (md5 != precompiled["MD5"].ToString())
                        precompiled = null;
                }

            int scriptID;
            if (null == precompiled)
            {
                // compile
                scriptID = script.GetHashCode();

                DateTime start = DateTime.UtcNow;
                if (log.IsDebugEnabled)
                    log.Debug("Compiling " + scriptName);

                object data;
                try
                {
                    data = subProcess.Compile(Thread.CurrentThread.ManagedThreadId, script, scriptID);
                }
                catch (Exception e)
                {
                    log.ErrorFormat("Exception compiling {0}\n{1}", e, scriptName, script);
                    throw e;
                }

                // If another thread compiled the script, we'll get back null
                if (null != data)
                {
                    log.InfoFormat("Compiling {0} took {1}", scriptName, DateTime.UtcNow - start);

                    precompiled = new Dictionary<string, object>();
                    precompiled["ScriptID"] = scriptID;
                    precompiled["MD5"] = md5;
                    precompiled["Data"] = data;

                    using (TimedLock.Lock(PrecompiledScriptDataByID))
                        PrecompiledScriptDataByID[scriptID] = data;

                    storedJSONobject = JsonWriter.Serialize(precompiled);
                    using (TimedLock.Lock(CompiledJavascriptCache))
                        if (CompiledJavascriptCache.IsFilePresent(scriptNameHex))
                            CompiledJavascriptCache.OpenFile(scriptNameHex).CastFileHandler<ITextHandler>().WriteAll(null, storedJSONobject);
                        else
                            ((ITextHandler)CompiledJavascriptCache.CreateFile(scriptNameHex, "text", null)).WriteAll(null, storedJSONobject);
                }
            }
            else
            {
                // load
                scriptID = Convert.ToInt32(precompiled["ScriptID"]);

                object data = precompiled["Data"];
                using (TimedLock.Lock(PrecompiledScriptDataByID))
                    PrecompiledScriptDataByID[scriptID] = data;

                log.Info("Loading " + scriptName);

                subProcess.LoadCompiled(Thread.CurrentThread.ManagedThreadId, data, scriptID);
            }

            return scriptID;
        }
Beispiel #7
0
        string sapviewmode = "I"; //interactive



        protected void Page_Load(object sender, EventArgs e)
        {
            try
            {
                idBR = int.Parse(Request.Params["idBR"]);
            }
            catch (Exception) { idBR = -432; }


            // Special viewing mode param added in May of 2010:
            //     sapview=interactive   or   html
            // The default is the former
            sapviewmode = "I";
            try
            {
                string mode = Request.Params["sapview"];
                sapviewmode = mode.ToUpper().Substring(0, 1);
            }
            catch (Exception) { }


            if (PANEL_tcodelistingmode_HtmlTable != null)
            {
                switch (sapviewmode)
                {
                case "I":
                    PANEL_tcodelistingmode_HtmlTable.Visible = false;
                    break;

                case "H":
                    PANEL_tcodelistingmode_interactive.Visible = false;
                    break;
                }
            }



            IProcess    engineProcess    = new IProcess(HELPERS.NewOdbcConn());
            ISubProcess engineSubProcess = new ISubProcess(HELPERS.NewOdbcConn());
            IBusRole    engineBR         = new IBusRole(HELPERS.NewOdbcConn());

            theBR         = engineBR.GetBusRole(idBR);
            theSubProcess = engineSubProcess.GetSubProcess(theBR.SubProcessID);
            theProcess    = engineProcess.GetProcess(theSubProcess.ProcessID);

            // Initialize dynamically-generated portions of the page
            if (PANELsapdesignnote != null)
            {
                IFuncApplNotes            engine   = new IFuncApplNotes(HELPERS.NewOdbcConn());
                returnListFuncApplNotes[] returned =
                    engine.ListFuncApplNotes
                        (null, "\"REFapplication\" = ?  AND  \"BusRole\" = ?" /* SAP application is ID 57 */,
                        new string[] { "57", idBR.ToString() }, "");
                if (returned.Length == 0)
                {
                    PANELsapdesignnote.Visible = false;
                }
                else
                {
                    STATICTXTsapfuncappdesignnote.Text =
                        returned[0].Comment;
                }
            }
        }
Beispiel #8
0
        /*
         * Assumes the subprocess info is already in place
         */
        public void ObtainWorkspaceContext()
        {
            System.Data.Odbc.OdbcConnection conn = HELPERS.NewOdbcConn();
            IEntAssignmentSet engineWS           = new IEntAssignmentSet(conn);


            returnListEntAssignmentSetBySubProcess[] listWS;

            if (this.nameSubprocess == null)
            {
                ISubProcess         Ispr = new ISubProcess(conn);
                returnGetSubProcess ret  = Ispr.GetSubProcess(idSubprocess);
                this.nameSubprocess = ret.Name;
                IProcess         Ipr  = new IProcess(conn);
                returnGetProcess ret2 = Ipr.GetProcess(ret.ProcessID);
                this.nameProcess = ret2.Name;
            }

            // Is there an active "live" easet for this subpr?
            listWS =
                engineWS.ListEntAssignmentSetBySubProcess
                    (null, "\"Status\" = ?", new string[] { "ACTIVE" }, "", idSubprocess);

            if (listWS.Length > 1)
            {
                throw new Exception("Internal error: more than one ACTIVE Ent Assignment Set for subprocess "
                                    + idSubprocess);
            }

            if (listWS.Length == 1)
            {
                idActiveEAset = listWS[0].ID;
            }



            // Is there a currently active ed workspace for this subprocess?

            listWS =
                engineWS.ListEntAssignmentSetBySubProcess
                    (null, "\"Status\" = ?", new string[] { "WORKSPACE" }, "", idSubprocess);

            if (listWS.Length > 1)
            {
                throw new Exception("Internal error: more than one workspace for subprocess "
                                    + idSubprocess);
            }

            if (listWS.Length == 1)
            {
                idWorkspace          = listWS[0].ID;
                commentWorkspace     = listWS[0].Commentary;
                idUserWorkspaceOwner = listWS[0].UserID;
                isWorkspaceOwner     = (idUser == listWS[0].UserID);
                if (isWorkspaceOwner)
                {
                    nameUserWorkspaceOwner = username;
                }
                else
                {
                    IUser         engineUser = new IUser(conn);
                    returnGetUser wsowner    = engineUser.GetUser(idUserWorkspaceOwner);
                    nameUserWorkspaceOwner =
                        wsowner.Name;
                }
            }
            else
            {
                idWorkspace            = -1;
                idUserWorkspaceOwner   = -1;
                isWorkspaceOwner       = false;
                nameUserWorkspaceOwner = "";
                commentWorkspace       = "";
            }
        }
Beispiel #9
0
        // Creates or Updates a business role object.
        // Alos, if necessary, creates new user objects for role ownership
        private void JQDLGsaproleProperties
            (System.Collections.Specialized.NameValueCollection pars, HttpResponse httpResponse)
        {
            ISAProle engineBR = new ISAProle(CONNdedicated);
            ISAProle engine   = engineBR;

            int idsaprole;



            if (pars["JQDLGbp_id"].Length == 0)
            {
                // WE ARE CREATING A NEW ROLE, NOT JUST UPDATING EXISTING

                int babyid = -1;

                // Make sure not already existing
                returnListSAProle[] chk =
                    engineBR.ListSAProle(null, "(\"Name\" = ?) and (\"System\" = ?) and (\"Platform\" = ?)",
                                         new string[] { pars["JQDLGbp_name"], pars["JQDLGbp_system"], pars["JQDLGbp_platform"] }, "");
                if (chk.Length > 0)
                {
                    // Already in existence!
                    returnListSAProle details = chk[0];

                    if (details.SubProcessID == session.idSubprocess)
                    {
                        // And this existing role is even in the same subprocess!

                        throw new Exception("This SAP role already exists and is registered with this very same subprocess.");
                    }
                    else
                    {
                        // Oh, belongs to a different subprocess.
                        IProcess    engineProcess    = new IProcess(engineBR.DbConnection);
                        ISubProcess engineSubProcess = new ISubProcess(engineBR.DbConnection);

                        returnGetSubProcess theSubProcess = engineSubProcess.GetSubProcess(details.SubProcessID);
                        returnGetProcess    theProcess    = engineProcess.GetProcess(theSubProcess.ProcessID);

                        throw new Exception
                                  ("This SAP role already exists, in a different subprocess: " + theProcess.Name + " / " + theSubProcess.Name);
                    }
                }



                try
                {
                    babyid =
                        engine.NewSAProle(
                            pars["JQDLGbp_name"],
                            session.idSubprocess, pars["JQDLGbp_system"], pars["JQDLGbp_platform"]);
                }
                catch (Exception eee)
                {
                    throw new Exception("Addition of new role failed: check for name already in use.");
                }
                idsaprole = babyid;
            }
            else
            {
                returnListSAProle[] chk =
                    engineBR.ListSAProle(null, "(\"id\" <> ?)  AND (\"Name\" = ?)",
                                         new string[] { pars["JQDLGbp_id"], pars["JQDLGbp_name"] }, "");
                if (chk.Length > 0)
                {
                    throw new Exception("Name '" + pars["JQDLGbp_name"] + "' is already in use for an existing SAP role.");
                }

                idsaprole = int.Parse(pars["JQDLGbp_id"]);
            }


            engineBR.SetSAProle(
                idsaprole,
                pars["JQDLGbp_name"],
                pars["JQDLGbp_description"], session.idSubprocess,
                pars["JQDLGbp_system"],
                pars["JQDLGbp_platform"],
                pars["JQDLGbp_roleactivity"],
                pars["JQDLGbp_roletype"], "");

            // ADDED to fix regression, on 09MAR2010:
            returnGetSAProle saprolePostAction = engine.GetSAProle(idsaprole);

            SAP_HELPERS.MaintainMatchingBusinessEntitlementForSAPRole(saprolePostAction, saprolePostAction);

            httpResponse.Write("OK");
        }
Beispiel #10
0
        public static void ImportDataTableAsNewTcodeAssignmentSet(
            DataTable dt, int IDuser, int IDsubpr, System.Data.Odbc.OdbcConnection conn)
        {
            IUser               Iuser  = new IUser(conn);
            ISubProcess         Isubpr = new ISubProcess(conn);
            ITcodeAssignmentSet Ieaset = new ITcodeAssignmentSet(conn);
            ITcodeAssignment    Iea    = new ITcodeAssignment(conn);
            ITcodeEntitlement   Ientit = new ITcodeEntitlement(conn);
            ITcodeDictionary    Idict  = new ITcodeDictionary(conn);
            ISAProle            Isr    = new ISAProle(conn);

            int IDneweas =
                Ieaset.NewTcodeAssignmentSet
                    (false, DateTime.Now, "Import from CSV", IDsubpr, IDuser);

            // These Get function are only useful for a read-only view of fields;
            // not for generating subordinate entities.
            returnGetTcodeAssignmentSet neweas = Ieaset.GetTcodeAssignmentSet(IDneweas);


            IEnumerator <System.Data.DataRow> x =
                (IEnumerator <System.Data.DataRow>)dt.Rows.GetEnumerator();


            while (x.MoveNext())
            {
                int IDsaprole;
                int IDtcode;

                if (x.Current[0].Equals(System.DBNull.Value))
                {
                    // Ignore any line with no value in the first field.
                    // Often the end of the csv file has just lots of blank rows.
                    continue;
                }

                // Make sure SAP role object exists; create if not.
                string saprole = (string)(x.Current["SAProle"]);
                RBSR_AUFW.DB.ISAProle.returnListSAProle[] xx = Isr.ListSAProle(null, "\"Name\" like ?",
                                                                               new string[] { saprole }, "");
                if (xx.Length < 1)
                {
                    // MUST ADD NEW ONE
                    IDsaprole =
                        Isr.NewSAProle(saprole, IDsubpr);
                }
                else
                {
                    IDsaprole = xx[0].ID;
                }



                // Make sure Tcode exists in the Tcode dictionary
                string tcodeshortname           = (string)(x.Current["TCODE Value"]);
                returnListTcodeDictionary[] xxx = Idict.ListTcodeDictionary
                                                      (null, "\"TcodeID\" like ?",
                                                      new string[] { tcodeshortname }, "");
                if (xxx.Length < 1)
                {
                    // MUST ADD NEW ONE
                    IDtcode =
                        Idict.NewTcodeDictionary(tcodeshortname,
                                                 x.Current["TCODE Description"] as string);
                }
                else
                {
                    IDtcode = xxx[0].ID;
                }


                int IDnewent = Ientit.NewTcodeEntitlement(
                    x.Current["Standard Activity"] as string,
                    x.Current["Type"] as string,
                    x.Current["System"] as string,
                    x.Current["Platform"] as string, IDtcode);


                Ientit.SetTcodeEntitlement(IDnewent,
                                           x.Current["Standard Activity"] as string,
                                           x.Current["Type"] as string,
                                           x.Current["System"] as string,
                                           x.Current["Platform"] as string,
                                           x.Current["AuthObj Name"] as string,
                                           x.Current["AuthObj Description"] as string,
                                           x.Current["Field-Level Security Value Description"] as string,
                                           x.Current["Field-Level Security Value"] as string,
                                           x.Current["Additional Comments"] as string,
                                           IDtcode);


                int IDnewentass = Iea.NewTcodeAssignment(IDneweas, IDsaprole, IDnewent);
            }
        }
Beispiel #11
0
        /*
         * The version 2 coalesces vectors that are identical
         * except for the business role.  Right now it uses a simplistic
         * algorithm that includes the commentary column (not a good thing)
         * and that doesn't look for variations that would be considered
         * not important (whitespaces?).
         */
        public static void ImportDataTableAsNewEntAssignmentSet_v2(
            DataTable dt, int IDuser, int IDsubpr, System.Data.Odbc.OdbcConnection conn)
        {
            IUser             Iuser  = new IUser(conn);
            ISubProcess       Isubpr = new ISubProcess(conn);
            IEntAssignmentSet Ieaset = new IEntAssignmentSet(conn);
            IEntAssignment    Iea    = new IEntAssignment(conn);
            IEntitlement      Ientit = new IEntitlement(conn);
            IBusRole          Ibr    = new IBusRole(conn);

            int IDneweas =
                Ieaset.NewEntAssignmentSet(false, DateTime.Now, "Import from CSV", IDsubpr, IDuser);

            // These Get function are only useful for a read-only view of fields;
            // not for generating subordinate entities.
            returnGetEntAssignmentSet neweas = Ieaset.GetEntAssignmentSet(IDneweas);

            IEnumerator <System.Data.DataRow> x =
                (IEnumerator <System.Data.DataRow>)dt.Rows.GetEnumerator();


            Hashtable signatures = new Hashtable();

            while (x.MoveNext())
            {
                int IDbusrole;

                if (x.Current[0].Equals(System.DBNull.Value))
                {
                    // Ignore any line with no value in the first field.
                    // Often the end of the csv file has just lots of blank rows.
                    continue;
                }

                // Make sure business role object exists; create if not.
                string busrole         = (string)(x.Current["BusRole"]);
                returnListBusRole[] xx = Ibr.ListBusRole(null, "\"Name\" like ?",
                                                         new string[] { busrole }, "");
                if (xx.Length < 1)
                {
                    // MUST ADD NEW ONE
                    IDbusrole =
                        Ibr.NewBusRole(busrole, x.Current["Business Role Description"] as string, IDsubpr);
                }
                else
                {
                    IDbusrole = xx[0].ID;
                }


                /* Create a "signature" for this entitlement vector so we can
                 * register it and also see if it's been seen before.
                 */
                string thisSignature =
                    x.Current["Standard Activity"] as string + "/\\" +
                    x.Current["Type"] as string + "/\\" +
                    x.Current["System"] as string + "/\\" +
                    x.Current["Platform"] as string + "/\\" +
                    x.Current["Entitlement Description"] as string + "/\\" +
                    x.Current["Entitlement Value"] as string + "/\\" +
                    "" + "/\\" +
                    x.Current["Authorization Object"] as string + "/\\" +
                    x.Current["Field-Level Security Name"] as string + "/\\" +
                    x.Current["Field-Level Security Value"] as string + "/\\" +
                    x.Current["4th Level Security Name"] as string + "/\\" +
                    x.Current["4th Level Security Value"] as string;

                if (signatures.ContainsKey(thisSignature))
                {
                    // Already seen before, so just add this bus.role
                    // to the list of busroles tied to this.
                    int IDnewent = (int)signatures[thisSignature];

                    int IDnewentass = Iea.NewEntAssignment
                                          (IDneweas, IDbusrole, IDnewent);
                }
                else
                {
                    int IDnewent = Ientit.NewEntitlement(
                        x.Current["Standard Activity"] as string,
                        x.Current["Type"] as string,
                        x.Current["System"] as string,
                        x.Current["Platform"] as string,
                        x.Current["Entitlement Description"] as string,
                        x.Current["Entitlement Value"] as string);

                    Ientit.SetEntitlement(IDnewent,
                                          x.Current["Standard Activity"] as string,
                                          x.Current["Type"] as string,
                                          x.Current["System"] as string,
                                          x.Current["Platform"] as string,
                                          x.Current["Entitlement Description"] as string,
                                          x.Current["Entitlement Value"] as string,
                                          "",
                                          x.Current["Authorization Object"] as string,
                                          x.Current["Field-Level Security Name"] as string,
                                          x.Current["Field-Level Security Value"] as string,
                                          x.Current["4th Level Security Name"] as string,
                                          x.Current["4th Level Security Value"] as string,
                                          x.Current["Additional Comments"] as string,
                                          x.Current["Manifest Value"] as string);

                    int IDnewentass = Iea.NewEntAssignment
                                          (IDneweas, IDbusrole, IDnewent);

                    signatures.Add(thisSignature, IDnewent);
                }
            }
        }
Beispiel #12
0
 public SubProcessBuilder(IBpmnModelInstance modelInstance, ISubProcess element)
     : base(modelInstance, element)
 {
 }
Beispiel #13
0
        public string RENDER()
        {
            int idproc = this.idPR;

            if (idproc < 0)
            {
                return("");
            }


            IProcess    engineProcess    = new IProcess(HELPERS.NewOdbcConn());
            ISubProcess engineSubProcess = new ISubProcess(HELPERS.NewOdbcConn());
            IBusRole    engineBR         = new IBusRole(HELPERS.NewOdbcConn());

            IEntAssignmentSet engineWS = new IEntAssignmentSet(HELPERS.NewOdbcConn());



            returnGetProcess detailProcess = engineProcess.GetProcess(idproc);

            StringBuilder BUFFER = new StringBuilder();


            /*
             * BUFFER.Append(
             *            "<tr><th colspan='2'>Process: " + detailProcess.Name + "</th></tr>");
             */

            returnListSubProcessByProcess[] subprocesses =
                engineSubProcess.ListSubProcessByProcess
                    (null,
                    "\"Status\" = ?", new string[] { "Active" }, "\"NAME\"", idproc);

            foreach (returnListSubProcessByProcess cursubpr in subprocesses)
            {
                int idActiveEAset = -1;

                returnListEntAssignmentSetBySubProcess[] listWS;

                listWS =
                    engineWS.ListEntAssignmentSetBySubProcess
                        (null, "\"Status\" = ?", new string[] { "ACTIVE" }, "", cursubpr.ID);

                if (listWS.Length > 1)
                {
                    throw new Exception("Internal error: more than one ACTIVE Ent Assignment Set for subprocess "
                                        + cursubpr.ID);
                }

                if (listWS.Length == 1)
                {
                    idActiveEAset = listWS[0].ID;
                }


                string sql = @"

SELECT
  BR.c_id, BR.c_u_Name, BR.c_u_Description,
  BR.c_u_RoleType as RoleTypeAbbrev, 
  (select Displayable from DICT_BusRoleType where Abbrev=c_u_RoleType) as RoleTypeDisplayable,

(
SELECT COUNT(DISTINCT ENT.c_u_Application)
   FROM t_RBSR_AUFW_u_EntAssignment EA
LEFT OUTER JOIN t_RBSR_AUFW_u_Entitlement ENT
   ON EA.c_r_Entitlement = ENT.c_id
WHERE
EA.c_r_BusRole = BR.c_id
AND
EA.c_r_EntAssignmentSet = " + idActiveEAset + @"
AND
EA.c_u_Status NOT IN ('X')
) as KOUNTAPPS,

USR.c_u_NameSurname, USR.c_u_NameFirst

FROM t_RBSR_AUFW_u_BusRole BR


LEFT OUTER JOIN 
t_RBSR_AUFW_u_BusRoleOwner BRPRIMOWN ON  BRPRIMOWN.c_r_BusRole=BR.c_id AND BRPRIMOWN.c_u_Rank = 'OWNprim'
LEFT OUTER JOIN 
t_RBSR_AUFW_u_User USR ON  BRPRIMOWN.c_u_EID = USR.c_u_EID


WHERE c_r_SubProcess=" + cursubpr.ID + " order by c_u_Name";


                BUFFER.Append("<tr><td><table class='subprocess'><caption>Subprocess: "
                              + cursubpr.Name + @"</caption>
                                                                        <thead>
                                                                        <tr>
                                                                                <th scope='col' width='25%'>Role Name</th>
                                                                                <th scope='col' width='25%'>Role Description</th>
                                                                                <th scope='col' width='20%'>Role Type</th>
                                                                                <th scope='col' width='30%'>Primary Owner</th>
                                                                        </tr>
                                                                </thead><tbody>");

                OdbcDataReader DR = HELPERS.RunSqlSelect(sql);

                while (DR.Read())
                {
                    int    idBRole   = DR.GetInt32(0);
                    string name      = DR.GetString(1);
                    string descr     = DR.GetString(2);
                    string roletype  = DR.GetString(4);
                    int    appcount  = DR.GetInt32(5);
                    string surname   = "";
                    string firstname = "";
                    try
                    {
                        surname   = HELPERS.SafeObjToString(DR.GetString(6));
                        firstname = HELPERS.SafeObjToString(DR.GetString(7));
                    }
                    catch (Exception) { }


                    BUFFER.Append("<tr><td><a href='DETAILbusrole.aspx?"
                                  + "idBR=" + idBRole
                                  + "&idSUBPR=" + cursubpr.ID
                                  + "&idPR=" + idproc
                                  + "'>"
                                  + name + "</a></td><td>" + descr
                                  + "</td><td>" + roletype + "</td><td>"
                                  + ((surname != "") ?  (surname.ToString() + ", " + firstname.ToString())   :   "")
                                  + "</td></tr>");
                }

                BUFFER.Append("</table></td></tr>\n");
            }



            returnGetSubProcess detailSubProcess;

            return(BUFFER.ToString());
        }