public void Init() { CommonNUnitFunctions.ResetDatabase(); TPetraServerConnector.Connect("../../etc/TestServer.config"); TDataBase db = DBAccess.Connect("AddressToolsTest"); PPartnerRow Partner1 = TCreateTestPartnerData.CreateNewFamilyPartner(MainDS, db); TestPartnerKey = Partner1.PartnerKey; //Guard assert: ensure database has been properly reset TDBTransaction ATransaction = new TDBTransaction(); DataTable ResultTable = null; string Query = string.Format("SELECT * FROM p_location WHERE p_site_key_n = {0} AND p_location_key_i = {1}", DomainManager.GSiteKey, LocationKey); db.ReadTransaction( ref ATransaction, delegate { ResultTable = ATransaction.DataBaseObj.SelectDT(Query, "CheckLocations", ATransaction); }); Assert.AreEqual(0, ResultTable.Rows.Count); }
public void ForeignCurrencySupplier_ExpectDocumentPostingPayingAndReversingWorking() { // // Arrange // decimal APAccountBalanceBefore; decimal BankAccountBefore; decimal RevalAccountBefore; TVerificationResultCollection VerificationResult; int PaymentNumber; List <int> DocumentIDs; AAPInfos APInfos; CommonNUnitFunctions.ResetDatabase(); TPetraServerConnector.Connect(); TDataBase db = DBAccess.Connect("ForeignCurrencySupplier_ExpectDocumentPostingPayingAndReversingWorking"); TDBTransaction transaction = db.BeginTransaction(IsolationLevel.Serializable); // Post and pay a document with a foreign currency supplier APInfos = PostAndPayForeignSupplierAPDocument("Test Reverse", out PaymentNumber, out DocumentIDs, out APAccountBalanceBefore, out BankAccountBefore, out RevalAccountBefore, db); transaction.Commit(); transaction = db.BeginTransaction(IsolationLevel.Serializable); // // Act: Immediately "un-pay" and "un-post" this invoice! // VerificationResult = ReversePayment(PaymentNumber, APInfos.PeriodEndDate, DocumentIDs, APInfos.ApDS, db); CommonNUnitFunctions.EnsureNullOrEmptyVerificationResult(VerificationResult); // Guard Assert transaction.Commit(); transaction = db.BeginTransaction(IsolationLevel.Serializable); // Save the current amount on the AP account decimal APAccountBalanceAfter = new TGet_GLM_Info(FLedgerNumber, APInfos.ApAccountCode, APInfos.CostCentreCode, db).YtdActual; decimal BankAccountAfter = new TGet_GLM_Info(FLedgerNumber, APInfos.BankAccount, APInfos.CostCentreCode, db).YtdForeign; decimal RevalAccountAfter = new TGet_GLM_Info(FLedgerNumber, APInfos.ForexGainsLossesAccount, APInfos.CostCentreCode, db).YtdActual; // // Primary Assert: Reversal OK? // // Now I can see whether anything is left over by all these // various transactions, that should have added up to 0. // Check the amount on the AP account Assert.AreEqual(APAccountBalanceBefore, APAccountBalanceAfter, "After paying then reversing, the AP account should be as before."); Assert.AreEqual(BankAccountBefore, BankAccountAfter, "After paying then reversing, the Bank account should be as before."); Assert.AreEqual( Math.Round(RevalAccountAfter, 2), Math.Round(RevalAccountBefore, 2), "After paying then reversing, the Forex Gains/Losses Account account should be as before."); transaction.Commit(); }
public void TestAnnualReceipt() { CommonNUnitFunctions.ResetDatabase(); // import a test gift batch TVerificationResultCollection VerificationResult; if (!ImportAndPostGiftBatch(FLedgerNumber, out VerificationResult)) { Assert.Fail("ImportAndPostGiftBatch failed: " + VerificationResult.BuildVerificationResultString()); } // TODO test reversed gifts string formletterTemplateFile = TAppSettingsManager.GetValue("ReceiptTemplate.file", "../../csharp/ICT/Testing/lib/MFinance/SampleData/AnnualReceiptTemplate.html"); Encoding encodingOfHTMLfile = TTextFile.GetFileEncoding(formletterTemplateFile); StreamReader sr = new StreamReader(formletterTemplateFile, encodingOfHTMLfile, false); string FileContent = sr.ReadToEnd(); sr.Close(); string formletterExpectedFile = TAppSettingsManager.GetValue("ReceiptExptected.file", "../../csharp/ICT/Testing/lib/MFinance/SampleData/AnnualReceiptExpected.html"); Catalog.Init("de-DE", "de-DE"); sr = new StreamReader(formletterExpectedFile, encodingOfHTMLfile, false); string ExpectedFormletterContent = sr.ReadToEnd(). Replace("#TODAY#", DateTime.Now.ToString("d. MMMM yyyy")). Replace("#THISYEAR#", DateTime.Today.Year.ToString()); sr.Close(); StreamWriter sw = new StreamWriter(formletterExpectedFile + ".updated", false, encodingOfHTMLfile); sw.WriteLine(ExpectedFormletterContent); sw.Close(); TLanguageCulture.SetLanguageAndCulture("de-DE", "de-DE"); //TODO: Calendar vs Financial Date Handling - Check if this should use financial year start/end and not assume calendar string receipts = TReceiptingWebConnector.CreateAnnualGiftReceipts(FLedgerNumber, new DateTime(DateTime.Today.Year, 1, 1), new DateTime(DateTime.Today.Year, 12, 31), FileContent); sw = new StreamWriter(formletterExpectedFile + ".new", false, encodingOfHTMLfile); sw.WriteLine(receipts); sw.WriteLine(); sw.Close(); Assert.IsTrue( TTextFile.SameContent(formletterExpectedFile + ".updated", formletterExpectedFile + ".new"), "receipt was not printed as expected, check " + formletterExpectedFile + ".new"); File.Delete(formletterExpectedFile + ".new"); File.Delete(formletterExpectedFile + ".updated"); }
/// <summary> /// print single gift receipt /// </summary> //[Test] public void TestSingleReceipt() { CommonNUnitFunctions.ResetDatabase(); TPetraServerConnector.Connect("../../etc/TestServer.config"); // import a test gift batch TVerificationResultCollection VerificationResult; if (!TGiftAnnualReceiptTest.ImportAndPostGiftBatch(FLedgerNumber, out VerificationResult)) { Assert.Fail("ImportAndPostGiftBatch failed: " + VerificationResult.BuildVerificationResultString()); } string formletterTemplateFile = TAppSettingsManager.GetValue("ReceiptTemplate.file", "../../csharp/ICT/Testing/lib/MFinance/SampleData/SingleGiftReceiptTemplate.html"); Encoding encodingOfHTMLfile = TTextFile.GetFileEncoding(formletterTemplateFile); StreamReader sr = new StreamReader(formletterTemplateFile, encodingOfHTMLfile, false); string FileContent = sr.ReadToEnd(); sr.Close(); string formletterExpectedFile = TAppSettingsManager.GetValue("ReceiptExpected.file", "../../csharp/ICT/Testing/lib/MFinance/SampleData/SingleGiftReceiptExpected.html"); //TODO: Calendar vs Financial Date Handling - Check if this should use financial year start/end and not assume calendar string receipts; string receiptsPDF; bool result = TReceiptingWebConnector.CreateAnnualGiftReceipts(FLedgerNumber, "Annual", new DateTime(DateTime.Today.Year, 1, 1), new DateTime(DateTime.Today.Year, 12, 31), FileContent, null, String.Empty, null, String.Empty, "de-DE", out receiptsPDF, out receipts); Assert.AreEqual(true, result, "receipt was empty"); StreamWriter sw = new StreamWriter(formletterExpectedFile + ".new", false, encodingOfHTMLfile); sw.WriteLine(receipts); sw.WriteLine(); sw.Close(); SortedList <string, string> ToReplace = new SortedList <string, string>(); ToReplace.Add("#TODAY#", DateTime.Now.ToString("d. MMMM yyyy")); ToReplace.Add("#THISYEAR#", DateTime.Today.Year.ToString()); Assert.IsTrue( TTextFile.SameContent(formletterExpectedFile, formletterExpectedFile + ".new", true, ToReplace, true), "receipt was not printed as expected, check " + formletterExpectedFile + ".new"); File.Delete(formletterExpectedFile + ".new"); }
public void SimpleDocument_ExpectPostingAndPayingWorking() { // // Arrange // decimal Amount = 399.0m; decimal APAccountBalanceBefore; decimal ABankAccountBefore; decimal AExpAccountBefore; TVerificationResultCollection VerificationResult; List <int> DocumentIDs; int PaymentNumber; AAPInfos APInfos; CommonNUnitFunctions.ResetDatabase(); TPetraServerConnector.Connect(); TDataBase db = DBAccess.Connect("SimpleDocument_ExpectPostingAndPayingWorking"); TDBTransaction transaction = db.BeginTransaction(IsolationLevel.Serializable); APInfos = PostSimpleAPDocument(Amount, "Test", "Detail Item", out APAccountBalanceBefore, out ABankAccountBefore, out AExpAccountBefore, out DocumentIDs, db); transaction.Commit(); transaction = db.BeginTransaction(IsolationLevel.Serializable); // // Act: Pay the AP document // VerificationResult = PayAPDocument(APInfos.ApDS.AApDocument[0].ApDocumentId, Amount, APInfos.BankAccount, APInfos.CurrencyCode, APInfos.PeriodEndDate, out PaymentNumber, null, db); CommonNUnitFunctions.EnsureNullOrEmptyVerificationResult(VerificationResult); // Guard Assert transaction.Commit(); // Save the current amount on the AP account decimal APAccountBalanceAfter = new TGet_GLM_Info(FLedgerNumber, APInfos.ApAccountCode, APInfos.CostCentreCode, db).YtdActual; decimal BankAccountAfter = new TGet_GLM_Info(FLedgerNumber, APInfos.BankAccount, APInfos.CostCentreCode, db).YtdActual; // // Primary Assert: Paying OK? // // Check the amount on the AP account Assert.AreEqual(0.0m, APAccountBalanceAfter - APAccountBalanceBefore, "after paying the invoice, the AP account should be cleared"); Assert.AreEqual((-1.0m) * Amount, BankAccountAfter - ABankAccountBefore, "after paying the invoice, the bank account should be credited"); }
public void TestPartnerBySpecialTypes() { CommonNUnitFunctions.ResetDatabase(); string testFile = "../../csharp/ICT/Testing/lib/MPartner/server/Reporting/TestData/PartnerBySpecialTypes.xml"; TParameterList SpecificParameters = new TParameterList(); SpecificParameters.Add("param_address_date_valid_on", new TVariant(new DateTime(DateTime.Today.Year, 1, 1))); SpecificParameters.Add("param_explicit_specialtypes", new TVariant("LEDGER")); TReportTestingTools.CalculateReport(testFile, SpecificParameters); TReportTestingTools.TestResult(testFile); }
public void TestSingleReceipt() { CommonNUnitFunctions.ResetDatabase(); // import a test gift batch TVerificationResultCollection VerificationResult; if (!TGiftAnnualReceiptTest.ImportAndPostGiftBatch(FLedgerNumber, out VerificationResult)) { Assert.Fail("ImportAndPostGiftBatch failed: " + VerificationResult.BuildVerificationResultString()); } string formletterTemplateFile = TAppSettingsManager.GetValue("ReceiptTemplate.file", "../../csharp/ICT/Testing/lib/MFinance/SampleData/SingleGiftReceiptTemplate.html"); Encoding encodingOfHTMLfile = TTextFile.GetFileEncoding(formletterTemplateFile); StreamReader sr = new StreamReader(formletterTemplateFile, encodingOfHTMLfile, false); string FileContent = sr.ReadToEnd(); sr.Close(); string formletterExpectedFile = TAppSettingsManager.GetValue("ReceiptExptected.file", "../../csharp/ICT/Testing/lib/MFinance/SampleData/SingleGiftReceiptExpected.html"); Catalog.Init("de-DE", "de-DE"); TLanguageCulture.SetLanguageAndCulture("de-DE", "de-DE"); string receipts = TReceiptingWebConnector.CreateAnnualGiftReceipts(FLedgerNumber, new DateTime(DateTime.Today.Year, 1, 1), new DateTime(DateTime.Today.Year, 12, 31), FileContent); StreamWriter sw = new StreamWriter(formletterExpectedFile + ".new", false, encodingOfHTMLfile); sw.WriteLine(receipts); sw.WriteLine(); sw.Close(); SortedList <string, string> ToReplace = new SortedList <string, string>(); ToReplace.Add("#TODAY#", DateTime.Now.ToString("d. MMMM yyyy")); ToReplace.Add("#THISYEAR#", DateTime.Today.Year.ToString()); Assert.IsTrue( TTextFile.SameContent(formletterExpectedFile, formletterExpectedFile + ".new", true, ToReplace, true), "receipt was not printed as expected, check " + formletterExpectedFile + ".new"); File.Delete(formletterExpectedFile + ".new"); }
public void ForeignCurrencySupplier_ExpectDocumentPostingAndPayingWorking() { // // Arrange // int PaymentNumber; List <int> DocumentIDs; decimal APAccountBalanceBefore; decimal BankAccountBefore; decimal RevalAccountBefore; CommonNUnitFunctions.ResetDatabase(); // Act and Assert: both encapsulated in the method that gets called! PostAndPayForeignSupplierAPDocument("Test", out PaymentNumber, out DocumentIDs, out APAccountBalanceBefore, out BankAccountBefore, out RevalAccountBefore); }
public void Init() { TPetraServerConnector.Connect("../../etc/TestServer.config"); CommonNUnitFunctions.ResetDatabase(); PPartnerRow Partner1 = TCreateTestPartnerData.CreateNewFamilyPartner(MainDS); TestPartnerKey = Partner1.PartnerKey; //Guard assert: ensure database has been properly reset TDBTransaction ATransaction = null; DataTable ResultTable = null; string Query = string.Format("SELECT * FROM p_location WHERE p_site_key_n = {0} AND p_location_key_i = {1}", DomainManager.GSiteKey, LocationKey); DBAccess.GDBAccessObj.GetNewOrExistingAutoReadTransaction(IsolationLevel.ReadCommitted, TEnforceIsolationLevel.eilMinimum, ref ATransaction, delegate { ResultTable = DBAccess.GetDBAccessObj(ATransaction).SelectDT(Query, "CheckLocations", ATransaction); }); Assert.AreEqual(0, ResultTable.Rows.Count); }
public void ForeignCurrencySupplier_ExpectDocumentPostingAndPayingWorking() { // // Arrange // int PaymentNumber; List <int> DocumentIDs; decimal APAccountBalanceBefore; decimal BankAccountBefore; decimal RevalAccountBefore; CommonNUnitFunctions.ResetDatabase(); TPetraServerConnector.Connect(); TDataBase db = DBAccess.Connect("ForeignCurrencySupplier_ExpectDocumentPostingPayingAndReversingWorking"); TDBTransaction transaction = db.BeginTransaction(IsolationLevel.Serializable); // Act and Assert: both encapsulated in the method that gets called! PostAndPayForeignSupplierAPDocument("Test", out PaymentNumber, out DocumentIDs, out APAccountBalanceBefore, out BankAccountBefore, out RevalAccountBefore, db); transaction.Commit(); }
public void TestExportGifts() { int LedgerNumber = FLedgerNumber; string CostCentre = "7300"; string AcctCode = "0200"; string MonthName = "January"; int PeriodNumber = 1; DateTime PeriodStartDate = new DateTime(DateTime.Today.Year, 1, 1); DateTime PeriodEndDate = new DateTime(DateTime.Today.Year, 1, 31); string Base = MFinanceConstants.CURRENCY_BASE; int IchNumber = 0; DataTable TableForExport = new DataTable(); bool NewTransaction = false; // otherwise period 1 might have been closed already CommonNUnitFunctions.ResetDatabase(); // need to create gifts first TStewardshipCalculationTest.ImportAndPostGiftBatch(PeriodEndDate); //Perform stewardship calculation TVerificationResultCollection VerificationResults; TStewardshipCalculationWebConnector.PerformStewardshipCalculation(FLedgerNumber, PeriodNumber, out VerificationResults); VerificationResults = new TVerificationResultCollection(); //Create DataTable to receive exported transactions TableForExport.Columns.Add("CostCentre", typeof(string)); TableForExport.Columns.Add("Account", typeof(string)); TableForExport.Columns.Add("LedgerMonth", typeof(string)); TableForExport.Columns.Add("ICHPeriod", typeof(string)); TableForExport.Columns.Add("Date", typeof(DateTime)); TableForExport.Columns.Add("IndividualDebitTotal", typeof(decimal)); TableForExport.Columns.Add("IndividualCreditTotal", typeof(decimal)); TGenHOSAFilesReportsWebConnector.ExportGifts(LedgerNumber, CostCentre, AcctCode, MonthName, PeriodNumber, PeriodStartDate, PeriodEndDate, Base, IchNumber, TableForExport, VerificationResults); TableForExport.AcceptChanges(); DataRow[] DR = TableForExport.Select(); CommonNUnitFunctions.EnsureNullOrOnlyNonCriticalVerificationResults(VerificationResults, "HOSA - Performing Export of gifts Failed!"); Assert.IsTrue((DR.Length > 0), "HOSA - Performing Export of gifts Failed to return any rows!"); if (NewTransaction) { DBAccess.GDBAccessObj.RollbackTransaction(); } }
public void T0_Consolidation() { // reset the database, so that there is no consolidated budget CommonNUnitFunctions.ResetDatabase(); string budgetTestFile = TAppSettingsManager.GetValue("GiftBatch.file", CommonNUnitFunctions.rootPath + "/csharp/ICT/Testing/lib/MFinance/SampleData/BudgetImport-All.csv"); int NumBudgetsUpdated; int NumFailedRows; TVerificationResultCollection VerificationResult; BudgetTDS ImportDS = new BudgetTDS(); string ImportString = File.ReadAllText(budgetTestFile); // import budget from CSV decimal RowsImported = TBudgetMaintainWebConnector.ImportBudgets( FLedgerNumber, 0, ImportString, budgetTestFile, new string[] { ",", "dmy", "American" }, ref ImportDS, out NumBudgetsUpdated, out NumFailedRows, out VerificationResult); Assert.AreNotEqual(0, RowsImported, "expect to import several rows"); CommonNUnitFunctions.EnsureNullOrOnlyNonCriticalVerificationResults(VerificationResult, "ImportBudgets has critical errors:"); BudgetTDSAccess.SubmitChanges(ImportDS); // check for value in budget table string sqlQueryBudget = String.Format( "SELECT {0} FROM PUB_{1}, PUB_{2} WHERE {1}.a_budget_sequence_i = {2}.a_budget_sequence_i AND a_period_number_i = 1 AND " + "a_ledger_number_i = {3} AND a_revision_i = 0 AND a_year_i = 0 AND a_account_code_c = '0300' AND a_cost_centre_code_c = '4300'", ABudgetPeriodTable.GetBudgetBaseDBName(), ABudgetTable.GetTableDBName(), ABudgetPeriodTable.GetTableDBName(), FLedgerNumber); decimal budgetValue = Convert.ToDecimal(DBAccess.GDBAccessObj.ExecuteScalar(sqlQueryBudget, IsolationLevel.ReadCommitted)); Assert.AreEqual(250m, budgetValue, "problem with importing budget from CSV"); // check for zero in glmperiod budget: that row does not even exist yet, so check that it does not exist string sqlQueryCheckEmptyConsolidatedBudget = String.Format( "SELECT COUNT(*) FROM PUB_{0}, PUB_{1} WHERE {0}.a_glm_sequence_i = {1}.a_glm_sequence_i AND a_period_number_i = 1 AND " + "a_ledger_number_i = {2} AND a_year_i = 0 AND a_account_code_c = '0300' AND a_cost_centre_code_c = '4300'", AGeneralLedgerMasterPeriodTable.GetTableDBName(), AGeneralLedgerMasterTable.GetTableDBName(), FLedgerNumber); Assert.AreEqual(0, DBAccess.GDBAccessObj.ExecuteScalar(sqlQueryCheckEmptyConsolidatedBudget, IsolationLevel.ReadCommitted), "budget should not be consolidated yet"); // consolidate the budget TBudgetConsolidateWebConnector.LoadBudgetForConsolidate(FLedgerNumber); TBudgetConsolidateWebConnector.ConsolidateBudgets(FLedgerNumber, true); // check for correct value in glmperiod budget string sqlQueryConsolidatedBudget = String.Format( "SELECT {0} FROM PUB_{1}, PUB_{2} WHERE {1}.a_glm_sequence_i = {2}.a_glm_sequence_i AND a_period_number_i = 1 AND " + "a_ledger_number_i = {3} AND a_year_i = 0 AND a_account_code_c = '0300' AND a_cost_centre_code_c = '4300'", AGeneralLedgerMasterPeriodTable.GetBudgetBaseDBName(), AGeneralLedgerMasterPeriodTable.GetTableDBName(), AGeneralLedgerMasterTable.GetTableDBName(), FLedgerNumber); decimal consolidatedBudgetValue = Convert.ToDecimal(DBAccess.GDBAccessObj.ExecuteScalar(sqlQueryConsolidatedBudget, IsolationLevel.ReadCommitted)); Assert.AreEqual(250m, consolidatedBudgetValue, "budget should now be consolidated"); // TODO: also check some summary account and cost centre for summed up budget values // check how reposting a budget works string sqlChangeBudget = String.Format("UPDATE PUB_{0} SET {1} = 44 WHERE a_period_number_i = 1 AND " + "EXISTS (SELECT * FROM PUB_{2} WHERE {0}.a_budget_sequence_i = {2}.a_budget_sequence_i AND a_ledger_number_i = {3} " + "AND a_year_i = 0 AND a_revision_i = 0 AND a_account_code_c = '0300' AND a_cost_centre_code_c = '4300')", ABudgetPeriodTable.GetTableDBName(), ABudgetPeriodTable.GetBudgetBaseDBName(), ABudgetTable.GetTableDBName(), FLedgerNumber); bool SubmissionOK = true; TDBTransaction Transaction = null; DBAccess.GDBAccessObj.BeginAutoTransaction(IsolationLevel.Serializable, ref Transaction, ref SubmissionOK, delegate { DBAccess.GDBAccessObj.ExecuteNonQuery(sqlChangeBudget, Transaction); }); // post all budgets again TBudgetConsolidateWebConnector.LoadBudgetForConsolidate(FLedgerNumber); TBudgetConsolidateWebConnector.ConsolidateBudgets(FLedgerNumber, true); consolidatedBudgetValue = Convert.ToDecimal(DBAccess.GDBAccessObj.ExecuteScalar(sqlQueryConsolidatedBudget, IsolationLevel.ReadCommitted)); Assert.AreEqual(44.0m, consolidatedBudgetValue, "budget should be consolidated with the new value"); // post only a modified budget (testing UnPostBudget) sqlChangeBudget = String.Format("UPDATE PUB_{0} SET {1} = 65 WHERE a_period_number_i = 1 AND " + "EXISTS (SELECT * FROM PUB_{2} WHERE {0}.a_budget_sequence_i = {2}.a_budget_sequence_i AND a_ledger_number_i = {3} " + "AND a_year_i = 0 AND a_revision_i = 0 AND a_account_code_c = '0300' AND a_cost_centre_code_c = '4300')", ABudgetPeriodTable.GetTableDBName(), ABudgetPeriodTable.GetBudgetBaseDBName(), ABudgetTable.GetTableDBName(), FLedgerNumber); string sqlMarkBudgetForConsolidation = String.Format("UPDATE PUB_{0} SET {1} = false WHERE " + "a_ledger_number_i = {2} " + "AND a_year_i = 0 AND a_revision_i = 0 AND a_account_code_c = '0300' AND a_cost_centre_code_c = '4300'", ABudgetTable.GetTableDBName(), ABudgetTable.GetBudgetStatusDBName(), FLedgerNumber); SubmissionOK = true; Transaction = null; DBAccess.GDBAccessObj.BeginAutoTransaction(IsolationLevel.Serializable, ref Transaction, ref SubmissionOK, delegate { DBAccess.GDBAccessObj.ExecuteNonQuery(sqlChangeBudget, Transaction); DBAccess.GDBAccessObj.ExecuteNonQuery(sqlMarkBudgetForConsolidation, Transaction); }); // post only modified budget again TBudgetConsolidateWebConnector.LoadBudgetForConsolidate(FLedgerNumber); TBudgetConsolidateWebConnector.ConsolidateBudgets(FLedgerNumber, false); consolidatedBudgetValue = Convert.ToDecimal(DBAccess.GDBAccessObj.ExecuteScalar(sqlQueryConsolidatedBudget, IsolationLevel.ReadCommitted)); Assert.AreEqual(65.0m, consolidatedBudgetValue, "budget should be consolidated with the new value, after UnPostBudget"); // TODO: test forwarding periods. what happens to next year values, when there is no next year glm record yet? }