Inheritance: IDataTransferable
 void GroupCurrencyUpdate (UUID groupID, GroupBalance gb, bool full)
 {
     if (full)
         GD.Update (_GROUPREALM,
             new Dictionary<string, object> {
             { "GroupFee", gb.GroupFee },
             { "LandFee", gb.LandFee },
             { "ObjectFee", gb.ObjectFee },
             { "ParcelDirectoryFee", gb.ParcelDirectoryFee },
             { "TotalTierCredits", gb.TotalTierCredits },
             { "TotalTierDebit", gb.TotalTierDebit },
             { "Balance", gb.Balance }
         },
             null,
             new QueryFilter {
             andFilters = new Dictionary<string, object> {
                 { "GroupID", groupID }
             }
         },
             null,
             null
         );
     else
         GD.Update (_GROUPREALM,
             new Dictionary<string, object> {
             { "TotalTierCredits", gb.TotalTierCredits },
             { "TotalTierDebit", gb.TotalTierDebit }
         },
             null,
             new QueryFilter {
             andFilters = new Dictionary<string, object> {
                 { "GroupID", groupID }
             }
         },
             null,
             null);
 }
        public bool GroupCurrencyTransfer(UUID groupID, UUID userId, bool payUser, string toObjectName, UUID fromObjectID,
            string fromObjectName, int amount, string description, TransactionType type, UUID transactionID)
        {
            GroupBalance gb = new GroupBalance {
                StartingDate = DateTime.UtcNow
            };

            // Not sure if a group will receive a system payment but..
            UserCurrency fromCurrency = userId == UUID.Zero ? null : GetUserCurrency(userId);

            // Groups (legacy) should not receive stipends
            if (type == TransactionType.StipendPayment) 
                return false;

            if (fromCurrency != null)
            {
                // Normal users cannot have a credit balance.. check to see whether they have enough money
                if ((int)fromCurrency.Amount - amount < 0)
                    return false; // Not enough money
            }

            // is thiis a payment to the group or to the user?
            if (payUser)
                amount = -1 * amount;

            uint fromBalance = 0;
            if (fromCurrency != null) {
                // user payment
                fromCurrency.Amount -= (uint)amount;
                UserCurrencyUpdate (fromCurrency, true);
                fromBalance = fromCurrency.Amount;
            }

            // track specific group fees
            switch (type)
            {
            case TransactionType.GroupJoin:
                gb.GroupFee += amount;
                break;
            case TransactionType.LandAuction:
                gb.LandFee += amount;
                break;
            case TransactionType.ParcelDirFee:
                gb.ParcelDirectoryFee += amount;
                break;
            }

            if (payUser)
                gb.TotalTierDebit -= amount;          // not sure if this the correct place yet? Are these currency or land credits?
            else
                gb.TotalTierCredits += amount;        // .. or this?

            // update the group balance
            gb.Balance += amount;                
            GroupCurrencyUpdate(groupID, gb, true);

            //Must send out notifications to the users involved so that they get the updates
            if (m_userInfoService == null)
            {
                m_userInfoService = m_registry.RequestModuleInterface<IAgentInfoService>();
                m_userAccountService = m_registry.RequestModuleInterface<IUserAccountService> ();
            }
            if (m_userInfoService != null)
            {
                UserInfo agentInfo = userId == UUID.Zero ? null : m_userInfoService.GetUserInfo(userId.ToString());
                UserAccount agentAccount = m_userAccountService.GetUserAccount(null, userId);
                var groupService = Framework.Utilities.DataManager.RequestPlugin<IGroupsServiceConnector> ();
                var groupInfo = groupService.GetGroupRecord (userId, groupID, null);
                var groupName = "Unknown";

                if (groupInfo != null)
                    groupName = groupInfo.GroupName;

                if (m_config.SaveTransactionLogs)
                    AddGroupTransactionRecord(
                        (transactionID == UUID.Zero ? UUID.Random() : transactionID), 
                        description,
                        groupID,
                        groupName, 
                        userId,
                        (agentAccount == null ? "System" : agentAccount.Name),
                        amount,
                        type,
                        gb.TotalTierCredits,        // assume this it the 'total credit for the group but it may be land tier credit??
                        (int) fromBalance,          // this will be zero if this isa system <> group transaction
                        toObjectName,
                        fromObjectName,
                        (agentInfo == null ? UUID.Zero : agentInfo.CurrentRegionID)
                    );

                if (agentInfo != null && agentInfo.IsOnline)
                {
                    SendUpdateMoneyBalanceToClient(userId, transactionID, agentInfo.CurrentRegionURI, fromBalance,
                    "You paid " + groupName + " " +InWorldCurrency + amount);
                }
            }
            return true;
        }
        static GroupBalance ParseGroupBalance(List<string> queryResults)
        {
            GroupBalance gb = new GroupBalance ();
           /* ColDef("GroupID", ColumnTypes.String36),
            ColDef("Balance", ColumnTypes.Integer30),
            ColDef("GroupFee", ColumnTypes.Integer30),
            ColDef("LandFee", ColumnTypes.Integer30),
            ColDef("ObjectFee", ColumnTypes.Integer30),
            ColDef("ParcelDirectoryFee", ColumnTypes.Integer30),
            ColDef("TierCredits", ColumnTypes.Integer30),
            ColDef("TierDebits", ColumnTypes.Integer30),
            */

            int.TryParse (queryResults [1], out gb.Balance);
            int.TryParse (queryResults [2], out gb.GroupFee);
            int.TryParse (queryResults [3], out gb.LandFee);
            int.TryParse (queryResults [4], out gb.ObjectFee);
            int.TryParse (queryResults [5], out gb.ParcelDirectoryFee);
            int.TryParse (queryResults [6], out gb.TotalTierCredits);
            int.TryParse (queryResults [7], out gb.TotalTierDebit);

            gb.StartingDate = DateTime.UtcNow;

            return gb;
        }
        public GroupBalance GetGroupBalance(UUID groupID)
        {
            object remoteValue = DoRemoteByURL("CurrencyServerURI", groupID);
            if (remoteValue != null || m_doRemoteOnly)
                return (GroupBalance) remoteValue;

            GroupBalance gb = new GroupBalance {
                GroupFee = 0,
                LandFee = 0,
                ObjectFee = 0,
                ParcelDirectoryFee = 0,
                TotalTierCredits = 0,
                TotalTierDebit = 0,
                Balance = 0,
                StartingDate = DateTime.UtcNow
            };
            Dictionary<string, object> where = new Dictionary<string, object> (1);
            where ["GroupID"] = groupID;

            List<string> queryResults = GD.Query (new [] { "*" }, _GROUPREALM,
                new QueryFilter { andFilters = where }, null, null, null);

            if (queryResults.Count == 0)
            {
                GroupCurrencyCreate(groupID);
                return gb;
            }

            return ParseGroupBalance(queryResults);
        }