public void Test_YearEnd()
        {
            intLedgerNumber = CommonNUnitFunctions.CreateNewLedger();

            TLedgerInfo LedgerInfo = new TLedgerInfo(intLedgerNumber);
            Assert.AreEqual(0, LedgerInfo.CurrentFinancialYear, "Before YearEnd, we should be in year 0");

            TAccountPeriodInfo periodInfo = new TAccountPeriodInfo(intLedgerNumber, 1);
            Assert.AreEqual(new DateTime(DateTime.Now.Year,
                    1,
                    1), periodInfo.PeriodStartDate, "Calendar from base database should start with January 1st of this year");

            CommonNUnitFunctions.LoadTestDataBase("csharp\\ICT\\Testing\\lib\\MFinance\\GL\\test-sql\\gl-test-year-end.sql", intLedgerNumber);

            TCommonAccountingTool commonAccountingTool =
                new TCommonAccountingTool(intLedgerNumber, "NUNIT");
            commonAccountingTool.AddBaseCurrencyJournal();
            commonAccountingTool.JournalDescription = "Test Data accounts";
            string strAccountGift = "0200";
            string strAccountBank = "6200";
            string strAccountExpense = "4100";

            // Accounting of some gifts ...
            commonAccountingTool.AddBaseCurrencyTransaction(
                strAccountBank, "4301", "Gift Example", "Debit", MFinanceConstants.IS_DEBIT, 100);
            commonAccountingTool.AddBaseCurrencyTransaction(
                strAccountBank, "4302", "Gift Example", "Debit", MFinanceConstants.IS_DEBIT, 200);
            commonAccountingTool.AddBaseCurrencyTransaction(
                strAccountBank, "4303", "Gift Example", "Debit", MFinanceConstants.IS_DEBIT, 300);

            commonAccountingTool.AddBaseCurrencyTransaction(
                strAccountGift, "4301", "Gift Example", "Credit", MFinanceConstants.IS_CREDIT, 100);
            commonAccountingTool.AddBaseCurrencyTransaction(
                strAccountGift, "4302", "Gift Example", "Credit", MFinanceConstants.IS_CREDIT, 200);
            commonAccountingTool.AddBaseCurrencyTransaction(
                strAccountGift, "4303", "Gift Example", "Credit", MFinanceConstants.IS_CREDIT, 300);


            // Accounting of some expenses ...

            commonAccountingTool.AddBaseCurrencyTransaction(
                strAccountExpense, "4301", "Expense Example", "Debit", MFinanceConstants.IS_DEBIT, 150);
            commonAccountingTool.AddBaseCurrencyTransaction(
                strAccountExpense, "4302", "Expense Example", "Debit", MFinanceConstants.IS_DEBIT, 150);
            commonAccountingTool.AddBaseCurrencyTransaction(
                strAccountExpense, "4303", "Expense Example", "Debit", MFinanceConstants.IS_DEBIT, 200);

            commonAccountingTool.AddBaseCurrencyTransaction(
                strAccountBank, "4301", "Expense Example", "Credit", MFinanceConstants.IS_CREDIT, 150);
            commonAccountingTool.AddBaseCurrencyTransaction(
                strAccountBank, "4302", "Expense Example", "Credit", MFinanceConstants.IS_CREDIT, 150);
            commonAccountingTool.AddBaseCurrencyTransaction(
                strAccountBank, "4303", "Expense Example", "Credit", MFinanceConstants.IS_CREDIT, 200);

            commonAccountingTool.CloseSaveAndPost(); // returns true if posting seemed to work


            TVerificationResultCollection verificationResult = new TVerificationResultCollection();

            bool blnLoop = true;

            while (blnLoop)
            {
                if (LedgerInfo.ProvisionalYearEndFlag)
                {
                    blnLoop = false;
                }
                else
                {
                    TVerificationResultCollection VerificationResult;
                    TPeriodIntervalConnector.PeriodMonthEnd(intLedgerNumber, false, out VerificationResult);
                    CommonNUnitFunctions.EnsureNullOrOnlyNonCriticalVerificationResults(VerificationResult,
                        "Running MonthEnd gave critical error");
                }
            }

            // check before year end that income and expense accounts are not 0
            int intYear = 0;
            CheckGLMEntry(intLedgerNumber, intYear, strAccountBank,
                -50, 0, 50, 0, 100, 0);
            CheckGLMEntry(intLedgerNumber, intYear, strAccountExpense,
                150, 0, 150, 0, 200, 0);
            CheckGLMEntry(intLedgerNumber, intYear, strAccountGift,
                100, 0, 200, 0, 300, 0);

            // test that we cannot post to period 12 anymore, all periods are closed?
            LedgerInfo = new TLedgerInfo(intLedgerNumber);
            Assert.AreEqual(true, LedgerInfo.ProvisionalYearEndFlag, "Provisional YearEnd flag should be set");
            Assert.AreEqual(TYearEndProcessStatus.RESET_STATUS,
                (TYearEndProcessStatus)LedgerInfo.YearEndProcessStatus,
                "YearEnd process status should be still on RESET");

            //
            // Reallocation is never called explicitly like this - it's not really appropriate
            // because I'm about to call it again as part of YearEnd, below.
            // But a tweak in the reallocation code means that it should now cope with being called twice.

            TReallocation reallocation = new TReallocation(LedgerInfo);
            reallocation.VerificationResultCollection = verificationResult;
            reallocation.IsInInfoMode = false;
            reallocation.RunOperation();

            // check amounts after reallocation
            CheckGLMEntry(intLedgerNumber, intYear, strAccountBank,
                -50, 0, 50, 0, 100, 0);
            CheckGLMEntry(intLedgerNumber, intYear, strAccountExpense,
                0, -150, 0, -150, 0, -200);
            CheckGLMEntry(intLedgerNumber, intYear, strAccountGift,
                0, -100, 0, -200, 0, -300);

            // first run in info mode
            TPeriodIntervalConnector.PeriodYearEnd(intLedgerNumber, true, out verificationResult);
            CommonNUnitFunctions.EnsureNullOrOnlyNonCriticalVerificationResults(verificationResult,
                "YearEnd test should not have critical errors");

            // now run for real
            TPeriodIntervalConnector.PeriodYearEnd(intLedgerNumber, false, out verificationResult);
            CommonNUnitFunctions.EnsureNullOrOnlyNonCriticalVerificationResults(verificationResult,
                "YearEnd should not have critical errors");

            ++intYear;
            // check after year end that income and expense accounts are 0, bank account remains
            CheckGLMEntry(intLedgerNumber, intYear, strAccountBank,
                -50, 0, 50, 0, 100, 0);
            CheckGLMEntry(intLedgerNumber, intYear, strAccountExpense,
                0, 0, 0, 0, 0, 0);
            CheckGLMEntry(intLedgerNumber, intYear, strAccountGift,
                0, 0, 0, 0, 0, 0);

            // also check the glm period records
            CheckGLMPeriodEntry(intLedgerNumber, intYear, 1, strAccountBank,
                -50, 50, 100);
            CheckGLMPeriodEntry(intLedgerNumber, intYear, 1, strAccountExpense,
                0, 0, 0);
            CheckGLMPeriodEntry(intLedgerNumber, intYear, 1, strAccountGift,
                0, 0, 0);

            // 9700 is the account that the expenses and income from last year is moved to
            TGlmInfo glmInfo = new TGlmInfo(intLedgerNumber, intYear, "9700");
            glmInfo.Reset();
            Assert.IsTrue(glmInfo.MoveNext(), "9700 account not found");

            Assert.AreEqual(100, glmInfo.YtdActualBase);
            Assert.AreEqual(0, glmInfo.ClosingPeriodActualBase);

            LedgerInfo = new TLedgerInfo(intLedgerNumber);
            Assert.AreEqual(1, LedgerInfo.CurrentFinancialYear, "After YearEnd, we are in a new financial year");
            Assert.AreEqual(1, LedgerInfo.CurrentPeriod, "After YearEnd, we are in Period 1");
            Assert.AreEqual(false, LedgerInfo.ProvisionalYearEndFlag, "After YearEnd, ProvisionalYearEnd flag should not be set");
            Assert.AreEqual(TYearEndProcessStatus.RESET_STATUS,
                (TYearEndProcessStatus)LedgerInfo.YearEndProcessStatus,
                "after year end, year end process status should be RESET");

            periodInfo = new TAccountPeriodInfo(intLedgerNumber, 1);
            Assert.AreEqual(new DateTime(DateTime.Now.Year + 1,
                    1,
                    1), periodInfo.PeriodStartDate, "new Calendar should start with January 1st of next year");
        }
        void CheckGLMEntry(int ALedgerNumber, int AYear, string AAccount,
            decimal cc1Base, decimal cc1Closing,
            decimal cc2Base, decimal cc2Closing,
            decimal cc3Base, decimal cc3Closing)
        {
            TGlmInfo glmInfo = new TGlmInfo(ALedgerNumber, AYear, AAccount);

            glmInfo.Reset();
            int intCnt = 0;
            bool blnFnd1 = false;
            bool blnFnd2 = false;
            bool blnFnd3 = false;

            TCacheable cache = new Ict.Petra.Server.MFinance.Cacheable.TCacheable();
            Type dummy;
            ACostCentreTable costcentres = (ACostCentreTable)cache.GetCacheableTable(TCacheableFinanceTablesEnum.CostCentreList,
                string.Empty,
                false,
                ALedgerNumber,
                out dummy);

            while (glmInfo.MoveNext())
            {
//              TLogging.Log("glmInfo.CostCentreCode: " + glmInfo.CostCentreCode);

                if (glmInfo.CostCentreCode.Equals("4301"))
                {
                    Assert.AreEqual(cc1Base, glmInfo.YtdActualBase, "CheckGLMEntry (" + ALedgerNumber + ", " + AYear + ", 4301, " + AAccount + ")");
                    Assert.AreEqual(cc1Closing,
                        glmInfo.ClosingPeriodActualBase,
                        "CheckGLMEntry (" + ALedgerNumber + ", " + AYear + ", 4301, " + AAccount + ")");
                    blnFnd1 = true;
                }

                if (glmInfo.CostCentreCode.Equals("4302"))
                {
                    Assert.AreEqual(cc2Base, glmInfo.YtdActualBase, "CheckGLMEntry (" + ALedgerNumber + ", " + AYear + ", 4302, " + AAccount + ")");
                    Assert.AreEqual(cc2Closing,
                        glmInfo.ClosingPeriodActualBase,
                        "CheckGLMEntry (" + ALedgerNumber + ", " + AYear + ", 4302, " + AAccount + ")");
                    blnFnd2 = true;
                }

                if (glmInfo.CostCentreCode.Equals("4303"))
                {
                    Assert.AreEqual(cc3Base, glmInfo.YtdActualBase, "CheckGLMEntry (" + ALedgerNumber + ", " + AYear + ", 4303, " + AAccount + ")");
                    Assert.AreEqual(cc3Closing,
                        glmInfo.ClosingPeriodActualBase,
                        "CheckGLMEntry (" + ALedgerNumber + ", " + AYear + ", 4303, " + AAccount + ")");
                    blnFnd3 = true;
                }

                if (((ACostCentreRow)costcentres.Rows.Find(new object[] { ALedgerNumber, glmInfo.CostCentreCode })).PostingCostCentreFlag)
                {
                    ++intCnt;
                }
            }

            Assert.IsTrue(blnFnd1, "CheckGLMEntry (" + ALedgerNumber + ", " + AYear + ", 4301, " + AAccount + ")");
            Assert.IsTrue(blnFnd2, "CheckGLMEntry (" + ALedgerNumber + ", " + AYear + ", 4302, " + AAccount + ")");
            Assert.IsTrue(blnFnd3, "CheckGLMEntry (" + ALedgerNumber + ", " + AYear + ", 4303, " + AAccount + ")");

            Assert.AreEqual(3, intCnt, "CheckGLMEntry expects 3 posting cost centres ...");
        }
        void CheckGLMPeriodEntry(int ALedgerNumber, int AYear, int APeriodNr, string AAccount,
            decimal cc1Base,
            decimal cc2Base,
            decimal cc3Base)
        {
            TGlmInfo glmInfo = new TGlmInfo(ALedgerNumber, AYear, AAccount);

            glmInfo.Reset();
            int intCnt = 0;
            bool blnFnd1 = false;
            bool blnFnd2 = false;
            bool blnFnd3 = false;

            TCacheable cache = new Ict.Petra.Server.MFinance.Cacheable.TCacheable();
            Type dummy;
            ACostCentreTable costcentres = (ACostCentreTable)cache.GetCacheableTable(TCacheableFinanceTablesEnum.CostCentreList,
                string.Empty,
                false,
                ALedgerNumber,
                out dummy);

            while (glmInfo.MoveNext())
            {
//              TLogging.Log("glmInfo.CostCentreCode: " + glmInfo.CostCentreCode);

                TGlmpInfo glmpInfo = new TGlmpInfo(ALedgerNumber);
                glmpInfo.LoadBySequence(glmInfo.GlmSequence, APeriodNr);

                Assert.AreEqual(true,
                    glmpInfo.RowExists,
                    "we cannot find a glm period record for " + glmInfo.AccountCode + " / " + glmInfo.CostCentreCode);

                if (glmInfo.CostCentreCode.Equals("4301"))
                {
                    Assert.AreEqual(cc1Base, glmpInfo.ActualBase);
                    blnFnd1 = true;
                }

                if (glmInfo.CostCentreCode.Equals("4302"))
                {
                    Assert.AreEqual(cc2Base, glmpInfo.ActualBase);
                    blnFnd2 = true;
                }

                if (glmInfo.CostCentreCode.Equals("4303"))
                {
                    Assert.AreEqual(cc3Base, glmpInfo.ActualBase);
                    blnFnd3 = true;
                }

                if (((ACostCentreRow)costcentres.Rows.Find(new object[] { ALedgerNumber, glmInfo.CostCentreCode })).PostingCostCentreFlag)
                {
                    ++intCnt;
                }
            }

            Assert.AreEqual(3, intCnt, "3 posting cost centres ...");
            Assert.IsTrue(blnFnd1);
            Assert.IsTrue(blnFnd2);
            Assert.IsTrue(blnFnd3);
        }
        /// <summary>
        /// TReallocation.RunOperation
        /// </summary>
        public override Int32 RunOperation()
        {
            Int32 CountJobs = 0;

            if (FAccountList == null)
            {
                CalculateAccountInfo();
            }

            TCommonAccountingTool YearEndBatch = null;

            if (DoExecuteableCode)
            {
                YearEndBatch = new TCommonAccountingTool(FledgerInfo,
                    Catalog.GetString("Financial year end processing"));
                YearEndBatch.AddBaseCurrencyJournal();
                YearEndBatch.JournalDescription = Catalog.GetString("YearEnd revaluations");
                YearEndBatch.SubSystemCode = CommonAccountingSubSystemsEnum.GL;
            }

            // tCommonAccountingTool.DateEffective =""; Default is "End of actual period ..."
            // Loop with all account codes
            foreach (string strAccountCode in FAccountList)
            {
                FglmInfo = new TGlmInfo(FledgerInfo.LedgerNumber,
                    FledgerInfo.CurrentFinancialYear,
                    strAccountCode);

                while (FglmInfo.MoveNext())
                {
                    Int32 CostCentreRowIdx = FCostCentreTbl.DefaultView.Find(FglmInfo.CostCentreCode);
                    ACostCentreRow currentCostCentre = (ACostCentreRow)FCostCentreTbl.DefaultView[CostCentreRowIdx].Row;

                    if (currentCostCentre.PostingCostCentreFlag)
                    {
                        TGlmpInfo glmpInfo = new TGlmpInfo(-1, -1, FglmInfo.GlmSequence, FledgerInfo.NumberOfAccountingPeriods);

                        if (glmpInfo.ActualBase + FglmInfo.ClosingPeriodActualBase != 0)
                        {
                            if (DoExecuteableCode)
                            {
                                ReallocationLoop(glmpInfo, YearEndBatch, strAccountCode, FglmInfo.CostCentreCode);
                            }

                            CountJobs++;
                        }
                    }
                }
            }

            if (DoExecuteableCode)
            {
                YearEndBatch.CloseSaveAndPost(FverificationResults);
            }

            return CountJobs;
        }