/// <summary> /// Add a transaction to the list and generate an appropriate sequence /// number for it. If the transaction takes place on the same day as /// a previous transaction, a new sequence number is created. /// Otherwise, the default sequence number of 0 is applied. /// </summary> /// <param name="otrans"></param> public void AddWithSequence( OnlineTransaction otrans ) { int sequence = 0; // Sequence numbers are generated for transactions that occur on // the same date to distinguish them. This assumes that the bank // is always going to list their transactions in the same order. string key = otrans.Date.ToString( "yyyyMMdd" ); if( keyCounts.ContainsKey( key ) ) sequence = keyCounts[key]++; else keyCounts.Add( key, 1 ); otrans.Sequence = sequence; this.Transactions.Add( otrans ); }
private static async Task SaveTransactionAsync(OnlineTransaction transaction, string json) { try { using (var con = new SqlConnection(connStr)) { await con.OpenAsync(); using (var cmd = new SqlCommand("insert into OnlineTransaction values (@Type,@No,@CreatedTimeUTC,@CustomerId,@Total,@ProcessedTimeUTC,@Processed,@Json,DEFAULT)", con)) { cmd.Parameters.AddWithValue("@Type", transaction.Type); cmd.Parameters.AddWithValue("@No", transaction.No); cmd.Parameters.AddWithValue("@CreatedTimeUTC", transaction.CreatedTimeUTC); cmd.Parameters.AddWithValue("@CustomerId", transaction.CustomerId); cmd.Parameters.AddWithValue("@Total", transaction.Total); if (transaction.ProcessedTimeUTC.HasValue) { cmd.Parameters.AddWithValue("@ProcessedTimeUTC", transaction.ProcessedTimeUTC.Value); } else { cmd.Parameters.AddWithValue("@ProcessedTimeUTC", DBNull.Value); } cmd.Parameters.AddWithValue("@Processed", transaction.Processed); if (string.IsNullOrEmpty(json)) { cmd.Parameters.AddWithValue("@Json", DBNull.Value); } else { cmd.Parameters.AddWithValue("@Json", json); } //int modified = (int)(await cmd.ExecuteScalarAsync()); await cmd.ExecuteNonQueryAsync(); //transaction.Id = modified; } } } catch (Exception e) { Debug.WriteLine(e.Message); throw; } //return transaction; }
public static async Task SendMessageAsync(string sb, string topicName, OnlineTransaction transaction) { var topicClient = new TopicClient(sb, topicName); // Serialize and send messages var json = EncodingService.EncodeJson(transaction); // Note: Simulate custom serialization var message = new Message(EncodingService.Base64Encode(json)); // Add custom properties // Note: To be used in filters // Note: Filtering by SO and Invoice message.UserProperties.Add("TransactionType", transaction.Type.ToString()); message.UserProperties.Add("Version", "1.0"); // Send message await topicClient.SendAsync(message); }
/// <summary> /// Examines the ledger to find a Transaction LineItem matching /// the given OnlineTransaction. /// </summary> /// <param name="otrans"></param> /// <returns></returns> public LineItem SearchForMatchingLineItem( OnlineTransaction otrans, bool includeReconciled ) { Account account = FindAccountBySource( otrans.OnlineSource ); if( account == null ) return null; List<LineItem> matches = new List<LineItem>(); foreach( LineItem item in account.GetLineItems() ) { // Never match a generated transaction if( (item.Transaction.Flags & TransactionFlags.Generated) != 0 || item.Transaction is MissingTransaction ) continue; if( !includeReconciled && item.IsReconciled ) continue; bool match = false; if( item.HasNumber && otrans.HasNumber ) { // Matching numbers, must be a match. // BUG FIX: Was previously not checking to // see if the amounts matched! // This meant that there was no verification // of check amounts. if( item.Number.Equals( otrans.Number ) && item.AdjustedAmount == otrans.Amount ) match = true; } else { if( item.AdjustedAmount == otrans.Amount ) match = true; } // If a line item already has a matching transaction, skip. if( item.IsPosted ) match = false; // Online transaction must be later than or same date as transaction if( otrans.Date < item.Transaction.Date ) match = false; // Add to list of matches if( match ) matches.Add( item ); } // Can never match a number to a non-number // eg. $10.00 CHECK #1465 // to $10.00 Overdraft protection // The reverse is not true, unfortunately. foreach( LineItem item in new List<LineItem>( matches ) ) { if( (otrans.HasNumber && !item.HasNumber) || (!otrans.HasNumber && item.HasNumber) ) matches.Remove( item ); } if( matches.Count == 1 ) { return matches[0]; } else if( matches.Count > 1 ) { // More than one potential match. /* // If one of the possibilities matches both numbers, // return that one. foreach( LineItem item in matches ) { if( otrans.HasNumber && item.HasNumber && otrans.Number == item.Number ) return item; } */ // If more than one match, return the one with the date // nearest to the online transaction. LineItem minItem = null; int minDays = Int32.MaxValue; foreach( LineItem item in matches ) { TimeSpan span = otrans.Date - item.Transaction.Date; if( span.Days < minDays ) { minDays = span.Days; minItem = item; } } // It is assumed that it cannot be a match if // the date is over 60 days off. if( minDays > 60 ) return null; return minItem; } // No matches return null; }
public bool IsOnlineDeposit( OnlineTransaction otrans ) { Account account = FindAccountBySource( otrans.OnlineSource ); if( account == null ) return false; return account.IsAsset && otrans.Amount > 0; }
/// <summary> /// Generate a "missing" transaction from an online transaction. /// </summary> /// <param name="otrans"></param> /// <returns></returns> public Transaction CreateTransaction( OnlineTransaction otrans ) { Account sourceAccount = FindAccountBySource( otrans.OnlineSource ); if( sourceAccount == null ) throw new AccountException( "The account source " + otrans.OnlineSource + " does not exist in the ledger." ); // Insert an auto-generated transaction for each // online transaction that is not in the ledger. MissingTransaction missingTrans = new MissingTransaction(); missingTrans.Id = GetNextTransactionId(); missingTrans.Date = otrans.Date; missingTrans.Description = otrans.IsPending ? otrans.Description + " (pending)" : otrans.Description; missingTrans.Amount = Math.Abs( otrans.Amount ); missingTrans.Flags |= TransactionFlags.Generated; missingTrans.CreateLineItems( this, sourceAccount, otrans.Amount ); LineItem[] lineitems = missingTrans.GetLineItems( sourceAccount ); if( lineitems.Length != 1 ) throw new TransactionException( "Only one LineItem should have matched the source account." ); lineitems[0].Number = otrans.Number; lineitems[0].OnlineTransaction = otrans; // Ensure identifiers are generated foreach( LineItem item in missingTrans.LineItems ) { item.Id = GetNextLineItemId(); if( item.OnlineTransaction != null ) { item.OnlineTransaction.MatchingId = item.Id; item.OnlineTransaction.LineItemId = item.Id; } } return missingTrans; }
public override IOnlineStatement Parse( OnlineAccount account, StreamReader reader ) { // Format of this data is HTML string html = reader.ReadToEnd(); OnlineStatement statement = new OnlineStatement(); Regex regex = new Regex( @"<td>\s*<a class=""blue noul m_link m_type""\s*onclick="".*?""\s*href=""/myaccount/.*?&historySequenceNumber=(\d+?)&.*?"">(\d\d/\d\d/\d\d\d\d)</a>\s*</td>\s*<td>\s*<div class=""s16 mb0 mr0"">\s*<div>\s*<a class=""blue m_link m_type"" onclick="".*?""\s*href=""/myaccount/.*?"">\s*<span class=""transaction_description"">\s*(.*?)\s*</span>\s*</a>\s*<div>\s*</div>\s*</td>\s*<td class=""right"">\s*<a class=""blue noul m_link m_type""\s*onclick="".*?""\s*href=""/myaccount/.*?"">(.*?)</a>\s*</td>\s*<td class=""right"">\s*<a class=""blue noul m_link m_type""\s*onclick="".*?""\s*href=""/myaccount/.*?"">(.*?)</a>\s*</td>\s*<td class=""right"">\s*<a class=""blue noul m_link m_type""\s*onclick="".*?""\s*href=""/myaccount/.*?"">(.*?)</a>\s*</td>", RegexOptions.Singleline ); foreach( Match match in regex.Matches( html ) ) { // 1 = "history sequence number" - hopefully a unique ID // 2 = date MM/YY/DDDD // 3 = description // 4 = debit (or ) // 5 = credit (or ) // 6 = balance OnlineTransaction record = new OnlineTransaction(); } //// Columns: //// 0 = bank id //// 1 = account number //// 2 = account type (CHECKING) //// 3 = balance //// 4 = start date (YYYY-MM-DD) //// 5 = end date (YYYY-MM-DD) //// 6 = transaction type (CREDIT or DEBIT) //// 7 = transaction date (YYYY-MM-DD) //// 8 = transaction amount //// 9 = transaction id //// 10 = transaction description //reader.ReadLine(); // Skip headers //DateTime lastDate = DateTime.MinValue; //int lastSequence = 0; //string line; //while( (line = reader.ReadLine()) != null ) //{ // string[] columns = line.Split( ',' ); // OnlineTransaction record = new OnlineTransaction(); // record.Amount = decimal.Parse( columns[8] ); // // Form BankId from account number and transaction id // record.BankId = columns[1] + "-" + columns[9]; // record.Date = DateTime.Parse( columns[7] ); // record.Description = columns[10]; // record.Number = null; // // Strip the "- Debit" suffix ING puts on the description // if( record.Description.EndsWith( " - Debit" ) ) // record.Description = record.Description.Substring( 0, record.Description.Length - 8 ); // if( record.Date > lastDate ) lastSequence = -1; // record.Sequence = ++lastSequence; // // Transactions are given to us in descending order. // // Reverse it so they are in ascending order // // by inserting at the top of the list each time. // statement.Transactions.Insert( 0, record ); //} // TODO: Parse balances return statement; }
/// <summary> /// Deserialize from an XML reader into an OnlineTransaction object. /// </summary> /// <param name="xmlReader">XmlReader to deserialize from.</param> /// <returns>An OnlineTransaction object.</returns> public OnlineTransaction DeserializeTransaction( XmlReader xmlReader, Version version ) { if( xmlReader.NodeType != XmlNodeType.Element || xmlReader.Name != "OnlineTransaction" ) throw new ApplicationException( "Needs an OnlineTransaction node to deserialize an online transaction object." ); OnlineTransaction otrans = new OnlineTransaction(); if( xmlReader.GetAttribute( "Id" ) != null ) otrans.Id = int.Parse( xmlReader.GetAttribute( "Id" ) ); if( xmlReader.GetAttribute( "LineItemId" ) != null ) otrans.MatchingId = int.Parse( xmlReader.GetAttribute( "LineItemId" ) ); if( xmlReader.GetAttribute( "Source" ) != null ) otrans.OnlineSource = xmlReader.GetAttribute( "Source" ); if( xmlReader.GetAttribute( "Pending" ) == true.ToString() ) otrans.IsPending = true; if( xmlReader.GetAttribute( "Ignore" ) == true.ToString() ) otrans.IsUnmatchable = true; while( xmlReader.Read() ) { switch( xmlReader.NodeType ) { case XmlNodeType.Element: switch( xmlReader.Name ) { case "Source": // Deprecated otrans.OnlineSource = xmlReader.ReadString(); break; case "Id": // Deprecated otrans.Id = Int32.Parse( xmlReader.ReadString() ); break; case "BankId": otrans.BankId = xmlReader.ReadString(); break; case "Number": otrans.Number = xmlReader.ReadString(); break; case "Date": otrans.Date = DateTime.Parse( xmlReader.ReadString() ); break; case "Sequence": otrans.Sequence = int.Parse( xmlReader.ReadString() ); break; case "Description": otrans.Description = xmlReader.ReadString(); break; case "Amount": otrans.Amount = Decimal.Parse( xmlReader.ReadString() ); break; default: break; } break; case XmlNodeType.EndElement: if( xmlReader.Name == "OnlineTransaction" ) return otrans; break; } } return otrans; }
private OnlineTransaction ReadSingleTransaction() { OnlineTransaction otrans = new OnlineTransaction(); otrans.OnlineSource = source; // <STMTTRN> // <TRNTYPE>DEBIT // <DTPOSTED>20070308120000 // <TRNAMT>-42.86 // <FITID>20070308120000-42.860000001 // <REFNUM>0000001 // <NAME>UKROP'S #0482 // </STMTTRN> // <STMTTRN> // <TRNTYPE>CHECK // <DTPOSTED>20070314120000 // <TRNAMT>-60 // <FITID>20070314120000-600000014 // <CHECKNUM>0001449 // <REFNUM>0000014 // <NAME>CHECK // </STMTTRN> StringBuilder sb = new StringBuilder(); while( !reader.EndOfStream ) { string s = reader.ReadLine(); sb.Append( s ); if( s == "</STMTTRN>" ) break; } Console.WriteLine( sb.ToString() ); Match match; match = Regex.Match( sb.ToString(), "<DTPOSTED>(\\d*?)<" ); if( match.Success ) { string dt = match.Groups[1].Value; otrans.Date = new DateTime( Int32.Parse( dt.Substring( 0, 4 ) ), Int32.Parse( dt.Substring( 4, 2 ) ), Int32.Parse( dt.Substring( 6, 2 ) ) ); } match = Regex.Match( sb.ToString(), "<TRNAMT>(.*?)<" ); if( match.Success ) otrans.Amount = Decimal.Parse( match.Groups[1].Value ); match = Regex.Match( sb.ToString(), "<CHECKNUM>(\\d*?)<" ); if( match.Success ) otrans.Number = match.Groups[1].Value.TrimStart( '0' ); match = Regex.Match( sb.ToString(), "<NAME>(.*?)<" ); if( match.Success ) otrans.Description = match.Groups[1].Value; return otrans; }
public override IOnlineStatement Parse( OnlineAccount account, StreamReader reader ) { string html = reader.ReadToEnd(); // Mortgage is a special case if( account.Name.StartsWith( "Mortgage" ) ) return this.ParseMortgagePage( html ); OnlineStatement statement = new OnlineStatement(); //string balance = this.browser.RegexCapture( @"Balance: \$[\d,.]+?</div>", html ); //statement.Balance = decimal.Parse( balance ); string regex; if( account.Name.StartsWith( "Checking" ) ) regex = @"<td\s?>\s+(\d\d/\d\d/\d\d\d\d|PENDING)</td>\s+<td>.*?</td>\s+<td><span id="".*?""><a class="""" ID="".*?"" href='.*?ss_tempTransaction=(PD94.*?)&.*?'>(.*?)\s*</a></span></td>\s+<td class=""currency""\s*?>\s+\$?([\d.,]*?)</td>\s+<td class=""currency""\s*?>\s+\$?([\d.,]*?)</td>\s+<td class=""currency""\s*?>\s+(\$?[\d.,]*?)</td>"; else if( account.Name.StartsWith( "Equity" ) ) regex = @"<td>(\d\d/\d\d/\d\d\d\d)</td>\s+<td>.*?</td>\s+<td><span id="".*?""><a class="""" ID="".*?"" href='.*?ss_tempTransaction=(PD94.*?)&.*?'>(.*?)\s*</a></span></td>\s+<td class=""currency"">\$?([\d.,]*?)</td>\s+<td class=""currency"">\$?([\d.,]*?)</td>"; else throw new OnlineServiceException( "Parsing the " + account.Name + " account is not supported at this time." ); MatchCollection matches = Regex.Matches( html, regex ); foreach( Match match in matches ) { if( match.Groups[1].Value != "PENDING" ) { OnlineTransaction otrans = new OnlineTransaction(); otrans.Date = DateTime.Parse( match.Groups[1].Value ); otrans.Description = this.Cleanse( match.Groups[3].Value ); // Parse check numbers if( account.Name.StartsWith( "Checking" ) && otrans.Description.StartsWith( "CHECK #" ) ) { otrans.Number = otrans.Description.Substring( 7 ).Trim(); } if( account.Name.StartsWith( "Equity" ) ) { // Parse out any 3+ digit number beginning with hash mark (#110) Match checkmatch = Regex.Match( otrans.Description, @"[^#]*?#(\d\d\d+)[^#]*?" ); if( checkmatch.Success ) otrans.Number = checkmatch.Groups[1].Value; } // Compute positive or negative amount based on position in debit or credit column. if( match.Groups[4].Value.Length > 0 ) otrans.Amount = -Decimal.Parse( match.Groups[4].Value ); else if( match.Groups[5].Value.Length > 0 ) otrans.Amount = Decimal.Parse( match.Groups[5].Value ); if( account.AccountType == OnlineAccountType.Liability ) otrans.Amount = -otrans.Amount; // Add to beginning of list to reverse the order from oldest to newest statement.Transactions.Insert( 0, otrans ); } } DateTime lastDate = DateTime.MinValue; int lastSequence = 0; foreach( OnlineTransaction otrans in statement.Transactions ) { // Calculate the Sequence if( otrans.Date > lastDate ) lastSequence = -1; otrans.Sequence = ++lastSequence; lastDate = otrans.Date; } return statement; }
private string CreateBankId( OnlineTransaction otrans, string uniqueKey ) { return string.Format( "{0:yyyy}{0:MM}{0:dd}-{1}-{2}", otrans.Date, Math.Abs( otrans.Amount ), uniqueKey.GetHashCode().ToString( "X" ) ); }
public IOnlineStatement ParseVisa( OnlineAccount account, StreamReader reader ) { // Format is HTML string html = reader.ReadToEnd(); OnlineStatement statement = new OnlineStatement(); // Rather complex regex expression... // This regex only matches purchases, not payments Regex regex = new Regex( @"<TR class="".*?"">\s+<TD vAlign=""middle"" height=""6"" width=""13%"">\s+<FONT color=""#000000"" size=""1"" face=""Arial"">(\d{1,2}/\d\d/\d\d)</FONT>\s+</TD><TD vAlign=""middle"" height=""6"" width=""13%"">\s+<FONT color=""#000000"" size=""1"" face=""Arial"">(\d{1,2}/\d\d/\d\d)</FONT>\s+</TD><TD vAlign=""middle"" height=""6"" width=""55%"">\s+<FONT color=""#000000"" size=""1"" face=""Arial"">(.*?)</FONT>\s+</TD><TD vAlign=""middle"" height=""6"" width=""12%"">\s+<FONT color=""#000000"" size=""1"" face=""Arial"">\s+\$([\d,.]+)</FONT>" ); MatchCollection matches = regex.Matches( html ); // Resulting list should be in order from oldest to newest. // Fortunately that is how the transactions are given to us. // TODO: Pick out payments and finance charges, too! foreach( Match match in matches ) { OnlineTransaction otrans = new OnlineTransaction(); try { // First column is the date otrans.Date = DateTime.Parse( Cleanse( match.Groups[2].Value ) ); otrans.Description = Cleanse( match.Groups[3].Value.Trim() ).Trim(); otrans.Amount = Decimal.Parse( Cleanse( match.Groups[4].Value ) ); otrans.BankId = this.CreateBankId( otrans, otrans.Description ); statement.Transactions.Add( otrans ); } catch( FormatException ex ) { // Cannot parse transaction - just skip it. this.LogWrite( OnlineServiceEventType.Warning, string.Format( "Skipping {0}, cannot parse: {1}", match.Groups[0], ex.Message ) ); } } // TODO: Parse balances return statement; }
public override IOnlineStatement Parse( OnlineAccount account, StreamReader reader ) { // Format is actually CSV, not HTML if( account.Name == "Visa" ) return this.ParseVisa( account, reader ); string text = reader.ReadToEnd(); OnlineStatement statement = new OnlineStatement(); // 1 = date // 2 = description // 3 = comments, with newlines // 4 = check number // 5 = debit "(" or credit "" // 6 = amount // 7 = balance string regexString = @"""(\d{1,2}/\d\d/\d\d\d\d)"",""(.*?)"",""(.*?)"",""(.*?)"",""(\(?)\$([\d,.-]*?)\)?"",""(.*?)"""; Regex regex = new Regex( regexString, RegexOptions.Singleline ); MatchCollection matches = regex.Matches( text ); // Resulting list should be in order from oldest to newest. // Fortunately that is how the transactions are given to us. DateTime lastDate = DateTime.MinValue; int lastSequence = 0; foreach( Match match in matches ) { OnlineTransaction otrans = new OnlineTransaction(); try { // First column is the date otrans.Date = DateTime.Parse( Cleanse( match.Groups[1].Value ) ); // HACK: Reject dates before 12/5 because that is when the new Vacu // site came online. if( otrans.Date < new DateTime( 2009, 12, 5 ) ) continue; if( match.Groups[2].Value.StartsWith( "DBT PURCHASE" ) || match.Groups[2].Value.StartsWith( "POS PURCHASE" ) ) // Leave off the "DBT"/"POS" information as it is somewhat useless. otrans.Description = Cleanse( match.Groups[3].Value ).Trim(); else otrans.Description = (Cleanse( match.Groups[2].Value ) + " " + Cleanse( match.Groups[3].Value )).Trim(); int i = otrans.Description.IndexOf( "CARD NBR:" ); if( i >= 0 ) otrans.Description = otrans.Description.Substring( 0, i ).Trim(); if( match.Groups[4].Value.Length > 0 ) otrans.Number = match.Groups[4].Value; otrans.Amount = Decimal.Parse( Cleanse( match.Groups[6].Value ) ); // Values displayed in parens are negative (debits). if( match.Groups[5].Value == "(" ) otrans.Amount = -otrans.Amount; // We use a hash of the running bank balance as a unique identifier otrans.BankId = this.CreateBankId( otrans, Cleanse( match.Groups[7].Value ) ); // Calculate the Sequence if( otrans.Date > lastDate ) lastSequence = -1; otrans.Sequence = ++lastSequence; lastDate = otrans.Date; statement.Transactions.Add( otrans ); } catch( FormatException ex ) { // Cannot parse transaction for some reason - just skip it. this.LogWrite( OnlineServiceEventType.Warning, string.Format( "Skipping {0}, cannot parse: {1}", match.Groups[0], ex.Message ) ); } } // TODO: Parse balances return statement; }
public bool Contains( OnlineTransaction record ) { foreach( OnlineTransaction otrans in this.Transactions ) { if( otrans == record ) return true; } return false; }
public async Task SaveTransactionAsync(OnlineTransaction onlineTransaction) { }
/// <summary> /// Serialize an OnlineTransaction object to an XML writer. /// </summary> /// <param name="xmlWriter">XmlWriter to serialize to.</param> public void SerializeTransaction( XmlWriter xmlWriter, OnlineTransaction otrans ) { xmlWriter.WriteStartElement( "OnlineTransaction" ); if( otrans.Id > 0 ) xmlWriter.WriteAttributeString( "Id", otrans.Id.ToString() ); if( otrans.MatchingId > 0 ) xmlWriter.WriteAttributeString( "LineItemId", otrans.MatchingId.ToString() ); if( otrans.OnlineSource != null && otrans.OnlineSource.Length > 0 ) xmlWriter.WriteAttributeString( "Source", otrans.OnlineSource ); if( otrans.IsPending ) xmlWriter.WriteAttributeString( "Pending", true.ToString() ); if( otrans.IsUnmatchable ) xmlWriter.WriteAttributeString( "Ignore", true.ToString() ); xmlWriter.WriteWhitespace( Environment.NewLine ); /* xmlWriter.WriteElementString( "Source", otrans.Source ); xmlWriter.WriteWhitespace( Environment.NewLine ); xmlWriter.WriteElementString( "Id", otrans.Id.ToString() ); xmlWriter.WriteWhitespace( Environment.NewLine ); */ if( otrans.BankId != null && otrans.BankId.Length > 0 ) { xmlWriter.WriteElementString( "BankId", otrans.BankId ); xmlWriter.WriteWhitespace( Environment.NewLine ); } if( otrans.Number != null && otrans.Number.Length > 0 ) { xmlWriter.WriteElementString( "Number", otrans.Number ); xmlWriter.WriteWhitespace( Environment.NewLine ); } xmlWriter.WriteElementString( "Date", otrans.Date.ToShortDateString() ); xmlWriter.WriteWhitespace( Environment.NewLine ); if( otrans.Sequence > 0 ) { xmlWriter.WriteElementString( "Sequence", otrans.Sequence.ToString() ); xmlWriter.WriteWhitespace( Environment.NewLine ); } xmlWriter.WriteElementString( "Description", otrans.Description ); xmlWriter.WriteWhitespace( Environment.NewLine ); xmlWriter.WriteElementString( "Amount", otrans.Amount.ToString() ); xmlWriter.WriteWhitespace( Environment.NewLine ); xmlWriter.WriteEndElement(); // </OnlineTransaction> }
/// <summary> /// Check to see if the given transaction is already stored. /// </summary> /// <param name="testTransaction">Transaction to test.</param> /// <returns>True if already in storage, False if not found.</returns> public bool Contains( OnlineTransaction testTransaction ) { return transactions.Contains( testTransaction ); }
/// <summary> /// Load transactions from an XML file. /// </summary> public void Load() { if( !File.Exists( filename ) ) return; StreamReader reader = File.OpenText( filename ); try { XmlTextReader xmlReader = new XmlTextReader( reader ); try { OnlineTransaction trans = null; string lastElementName = null; while( xmlReader.Read() ) { if( xmlReader.NodeType == XmlNodeType.Element ) { lastElementName = xmlReader.Name; if( lastElementName == "OnlineTransaction" ) { trans = new OnlineTransaction(); Transactions.Add( trans ); } } else if( xmlReader.NodeType == XmlNodeType.Text ) { switch( lastElementName ) { case "Id": trans.Id = Int32.Parse( xmlReader.Value ); //if( trans.Id > transactions.NextId ) // transactions.NextId = trans.Id + 1; break; case "BankId": trans.BankId = xmlReader.Value; break; case "Source": trans.OnlineSource = xmlReader.Value; break; case "Number": trans.Number = xmlReader.Value; break; case "Date": trans.Date = DateTime.Parse( xmlReader.Value ); break; case "Description": trans.Description = xmlReader.Value; break; case "Amount": trans.Amount = Decimal.Parse( xmlReader.Value ); break; } } } } finally { xmlReader.Close(); } } finally { reader.Close(); } }
public void Post([FromBody] OnlineTransaction value) { }