public bool GetBranchAccumMoney(long lGroup, ref long m_lRealAccMoney)
        {
            trace.Write(TraceLevel.Debug, "CM1GroupTree::GetBranchAccumMoney");
            bool fnResult = true;

            try
            {
                CM1Group group = GetGroupFromGrpId(lGroup);
                if (group == null)
                {
                    throw new InvalidOperationException("Could not obtain group of current operation");
                }

                long lGrpAccMoney = 0;
                m_lRealAccMoney = 0;

                while (group != null)
                {
                    lGrpAccMoney    = group.GetAccMoney();
                    m_lRealAccMoney = Math.Max(lGrpAccMoney, m_lRealAccMoney);
                    group           = GetGroupParent(group.GetGrpId());
                }

                trace.Write(TraceLevel.Info, $"Money accumulate for branch of group {lGroup}: {m_lRealAccMoney}");
            }
            catch (Exception error)
            {
                trace.Write(TraceLevel.Error, error.ToLogString());
                fnResult = false;
            }

            return(fnResult);
        }
        public bool GetBranchMinMoney(long groupId, ref long money, bool isComputeEx1 = false)
        {
            trace.Write(TraceLevel.Debug, "CM1GroupsTree::GetBranchMinMoney");
            bool fnResult = true;

            try
            {
                // Get group object of the group of the operation to evaluate
                CM1Group pGrp = GetGroupFromGrpId(groupId);

                if (pGrp == null)
                {
                    throw  new InvalidOperationException("Could not obtain group of current operation");
                }

                long lGrpAccMoney = 0;
                long lGrpMinMoney = 0;
                money = -1;

                while (pGrp != null)
                {
                    lGrpAccMoney = (isComputeEx1) ? pGrp.GetEfecAccMoney() : pGrp.GetAccMoney();
                    lGrpMinMoney = pGrp.GetMinMoney();

                    if (lGrpMinMoney == GlobalDefs.DEF_UNDEFINED_VALUE || lGrpMinMoney < lGrpAccMoney)
                    {
                        lGrpMinMoney = 0;
                    }
                    else
                    {
                        lGrpMinMoney -= lGrpAccMoney;
                    }

                    money = Math.Max(lGrpMinMoney, money);

                    pGrp = GetGroupParent(pGrp.GetGrpId());
                }
                trace.Write(TraceLevel.Info, $"Min. money for branch of group {groupId}: {money}");
            }
            catch (Exception error)
            {
                trace.Write(TraceLevel.Error, error.ToLogString());
                fnResult = false;
            }

            return(fnResult);
        }
        /// <summary>
        ///	Returns the maximum money that a user can spend in a branch without overflowing the maximum money constraint in any group
        /// </summary>
        /// <param name="tree"></param>
        /// <param name="groupId"></param>
        /// <param name="money"></param>
        /// <returns>bool</returns>
        public bool GetBranchMaxAvailableMoney(long groupId, ref long money, bool isComputeEx1 = false)
        {
            trace?.Write(TraceLevel.Debug, "CM1GroupTree::GetBranchMaxAvailableMoney");
            bool fnResult = true;

            try
            {
                CM1Group treeGroup = GetGroupFromGrpId(groupId);
                if (treeGroup == null)
                {
                    throw new ArgumentNullException(nameof(groupId), "Could not obtain group of current operation");
                }

                long lGrpAccMoney = 0;
                long lGrpMaxMoney = 0;

                money = 999999999;

                while (treeGroup != null)
                {
                    lGrpAccMoney = (isComputeEx1) ? treeGroup.GetRealAccMoney() : treeGroup.GetAccMoney();
                    lGrpMaxMoney = treeGroup.GetMaxMoney();

                    if (lGrpMaxMoney != GlobalDefs.DEF_UNDEFINED_VALUE)
                    {
                        money = Math.Min(lGrpMaxMoney - lGrpAccMoney, money);
                    }

                    treeGroup = GetGroupParent(treeGroup.GetGrpId());
                }

                trace?.Write(TraceLevel.Info, $"Money left for branch of group {groupId}: {money}");
            }
            catch (Exception error)
            {
                trace?.Write(TraceLevel.Error, error.ToLogString());
                fnResult = false;
            }

            return(fnResult);
        }
        public void TraceBranchM1ComputeEx1(long lGrpId)
        {
            trace.Write(TraceLevel.Debug, "CM1GroupsTree::TraceBranchM1ComputeEx1");
            try
            {
                trace.Write(TraceLevel.Debug, $"Tracing branch of group: {lGrpId}");
                trace.Write(TraceLevel.Debug, $"[  Group  | Type | NumChilds | NumConstraits | PruneFase | Money | Minutes ]");
                CM1Group pGrp = GetGroupFromGrpId(lGrpId);

                while (pGrp != null)
                {
                    // For each group have to be a node
                    CM1Node pNode = GetFirstNodeFromIds(pGrp.GetGrpId());

                    if (pNode != null)
                    {
                        trace.Write(TraceLevel.Debug, $"[ {pGrp.GetGrpId(),-7} | {pGrp.GetGrpTypeId(),-4} | {pNode.ChildsNum,9} | {pNode.CnstrNum,-13} | {pNode.PruneFase,-9} | {pGrp.GetAccMoney(),-5} | {pGrp.GetAccMinutes(),-7} ]");
                    }
                    pGrp = GetGroupParent(pGrp.GetGrpId());
                }
            }
            catch (Exception error)
            {
                trace.Write(TraceLevel.Error, error.ToLogString());
            }
        }