public void SaveLedger( Ledger ledger ) { ledger.ValidateReferentialIntegrity(); // Ensure that identifiers match appropriately before saving. ValidateIdentifierLinks( ledger ); /* // TODO: Remove this after testing ledger.RecurringTransactions.Clear(); RecurringTransaction r = new RecurringTransaction(); r.StartingDate = new DateTime( 2007, 10, 15 ); r.EndingDate = DateTime.MaxValue; r.Date = new DateTime( 2007, 10, 15 ); r.Amount = 129.69M; r.Description = "Ameriprise Financial"; r.Memo = "Life insurance payment"; r.LineItems.Add( new LineItemCredit( ledger.GetAccount( "Suntrust" ), r.Amount ) ); r.LineItems.Add( new LineItemDebit( ledger.GetAccount( "Expenses" ), r.Amount ) ); r.AddMonths = 1; ledger.RecurringTransactions.Add( r ); */ StreamWriter writer = File.CreateText( filename ); try { XmlTextWriter xmlWriter = new XmlTextWriter( writer ); try { xmlWriter.WriteStartDocument(); xmlWriter.WriteWhitespace( Environment.NewLine ); xmlWriter.WriteStartElement( "Ledger" ); xmlWriter.WriteAttributeString( "xmlns", "http://www.uvteksoftware.com/xsd/UvMoneyLedger.xsd" ); xmlWriter.WriteAttributeString( "Version", "1.2" ); xmlWriter.WriteWhitespace( Environment.NewLine ); xmlWriter.WriteElementString( "MergeDate", ledger.MergeDate.ToString() ); xmlWriter.WriteWhitespace( Environment.NewLine ); // Write accounts xmlWriter.WriteWhitespace( Environment.NewLine ); xmlWriter.WriteStartElement( "Accounts" ); xmlWriter.WriteWhitespace( Environment.NewLine ); foreach( Account account in ledger.Accounts ) { SerializeAccount( xmlWriter, account ); xmlWriter.WriteWhitespace( Environment.NewLine ); } xmlWriter.WriteEndElement(); // </Accounts> xmlWriter.WriteWhitespace( Environment.NewLine ); // Write recurring transactions if( ledger.RecurringTransactions.Count > 0 ) { xmlWriter.WriteWhitespace( Environment.NewLine ); xmlWriter.WriteStartElement( "RecurringTransactions" ); xmlWriter.WriteWhitespace( Environment.NewLine ); foreach( RecurringTransaction retrans in ledger.RecurringTransactions ) { SerializeRecurringTransaction( xmlWriter, retrans ); xmlWriter.WriteWhitespace( Environment.NewLine ); } xmlWriter.WriteEndElement(); // </RecurringTransactions> xmlWriter.WriteWhitespace( Environment.NewLine ); } // Write transactions xmlWriter.WriteWhitespace( Environment.NewLine ); xmlWriter.WriteStartElement( "Transactions" ); xmlWriter.WriteWhitespace( Environment.NewLine ); foreach( Transaction trans in ledger.Transactions ) { // Do not serialize auto-generated transactions if( !( trans is MissingTransaction ) ) { trans.Validate(); SerializeTransaction( xmlWriter, trans ); xmlWriter.WriteWhitespace( Environment.NewLine ); } } xmlWriter.WriteWhitespace( Environment.NewLine ); xmlWriter.WriteComment( "Insert new transactions here." ); xmlWriter.WriteWhitespace( Environment.NewLine ); // Write out a transaction template StringBuilder sb = new StringBuilder(); sb.Append( Environment.NewLine ); sb.Append( "<Transaction>" ); sb.Append( Environment.NewLine ); sb.Append( "<Date></Date>" ); sb.Append( Environment.NewLine ); sb.Append( "<Number></Number>" ); sb.Append( Environment.NewLine ); sb.Append( "<Amount>0.00</Amount>" ); sb.Append( Environment.NewLine ); sb.Append( "<Description>Payee</Description>" ); sb.Append( Environment.NewLine ); sb.Append( "<Memo></Memo>" ); sb.Append( Environment.NewLine ); sb.Append( "<LineItems>" ); sb.Append( Environment.NewLine ); sb.Append( "<Credit Account=\"\" />" ); sb.Append( Environment.NewLine ); sb.Append( "<Debit Account=\"Expenses\" Category=\"\" />" ); sb.Append( Environment.NewLine ); sb.Append( "</LineItems>" ); sb.Append( Environment.NewLine ); sb.Append( "</Transaction>" ); sb.Append( Environment.NewLine ); xmlWriter.WriteComment( sb.ToString() ); xmlWriter.WriteWhitespace( Environment.NewLine ); xmlWriter.WriteWhitespace( Environment.NewLine ); xmlWriter.WriteEndElement(); // </Transactions> xmlWriter.WriteWhitespace( Environment.NewLine ); OnlineTransactionStorageXml ostorage = new OnlineTransactionStorageXml(); // Write online transactions that are missing from the ledger if( ledger.MissingTransactions.Count > 0 ) { xmlWriter.WriteStartElement( "MissingOnlineTransactions" ); xmlWriter.WriteWhitespace( Environment.NewLine ); foreach( OnlineTransaction otrans in ledger.MissingTransactions ) { ostorage.SerializeTransaction( xmlWriter, otrans ); xmlWriter.WriteWhitespace( Environment.NewLine ); } xmlWriter.WriteEndElement(); // </MissingOnlineTransactions> xmlWriter.WriteWhitespace( Environment.NewLine ); } xmlWriter.WriteEndElement(); // </Ledger> xmlWriter.WriteWhitespace( Environment.NewLine ); xmlWriter.WriteEndDocument(); } finally { xmlWriter.Close(); } } finally { writer.Close(); } }
public Ledger LoadLedger() { Ledger ledger = new Ledger(); FileInfo fi = new FileInfo( filename ); if( !fi.Exists ) return ledger; OnlineTransactionStorageXml ostorage = new OnlineTransactionStorageXml(); Version version = new Version( 1, 0 ); // I'm not precisely sure why I chose to parse the XML manually // instead of using XmlSerializer. // I guess I just didn't want to markup my classes with Xml tags. StreamReader reader = File.OpenText( filename ); try { XmlTextReader xmlReader = new XmlTextReader( reader ); try { while( xmlReader.Read() ) { switch( xmlReader.NodeType ) { case XmlNodeType.Element: switch( xmlReader.Name ) { case "MergeDate": ledger.MergeDate = DateTime.Parse( xmlReader.ReadString() ); break; case "Ledger": version = new Version( xmlReader.GetAttribute( "Version" ) ); break; case "Accounts": break; case "Account": Account account = DeserializeAccount( xmlReader, version ); account.Ledger = ledger; // Verify that we are not adding any duplicate Ids or Names Account testAccount = ledger.FindAccount( account.Id ); if( testAccount != null ) throw new ApplicationException( "There is already an account with Id " + account.Id ); testAccount = ledger.FindAccount( account.Name ); if( testAccount != null ) throw new ApplicationException( "There is already an account named " + account.Name ); // Passed validation, add the account ledger.Accounts.Add( account ); break; case "Transactions": break; case "Transaction": Transaction trans = DeserializeTransaction( xmlReader, version, ledger ); // Migrate from deprecated versions trans.Migrate( version ); // Validate the transaction trans.Validate(); if( trans.Id != 0 ) { // Ensure no other transactions with the same Id are in the ledger Transaction testTrans = ledger.GetTransaction( trans.Id ); if( testTrans != null ) throw new ApplicationException( "There is already a transaction with Id " + trans.Id ); } ledger.AddTransaction( trans ); break; case "MissingOnlineTransactions": break; case "OnlineTransaction": OnlineTransaction otrans = ostorage.DeserializeTransaction( xmlReader, version ); ledger.MissingTransactions.Add( otrans ); break; case "RecurringTransactions": break; case "RecurringTransaction": RecurringTransaction rtrans = DeserializeRecurringTransaction( xmlReader, version, ledger ); ledger.RecurringTransactions.Add( rtrans ); break; } break; } } } finally { xmlReader.Close(); } } finally { reader.Close(); } AssignTransactionIdentifiers( ledger ); AssignLineItemIdentifiers( ledger ); ValidateIdentifierLinks( ledger ); ledger.ValidateReferentialIntegrity(); // Set load date so we can determine if data in memory is stale ledger.LoadDate = DateTime.Now; return ledger; }