Esempio n. 1
0
        private int LoadTransaction( StreamReader reader, int lineNumber, Ledger ledger, Account account )
        {
            Transaction trans = new Transaction();
            try
            {
                LineItem item;
                decimal transAmount = 0;
                string lineItemCategory = null;
                string lineItemMemo = null;
                decimal lineItemAmount = 0;
                string transCategory = null;
                bool isCleared = false;
                string checkNumber = null;
                string investmentName = null;
                string investmentPrice = null;
                string investmentShares = null;
                string investmentCommission = null;

                while( !reader.EndOfStream )
                {
                    string line = reader.ReadLine();
                    if( line[0] == '^' ) break;

                    switch( line[0] )
                    {
                        case 'D':
                            // Date
                            // MM/DD'YYYY
                            // We handle a bunch of different separators
                            // TODO: Handle DD/MM/YYYY European form ??
                            Regex regex = new Regex( "D(\\d+)['.-/]\\s*(\\d+)['.-/]\\s*(\\d+)" );
                            if( !regex.IsMatch( line ) )
                                throw new StorageException( "Cannot parse date " + line );
                            Match match = regex.Match( line );
                            int month = Int32.Parse( match.Groups[1].Value );
                            int day = Int32.Parse( match.Groups[2].Value );
                            int year = Int32.Parse( match.Groups[3].Value );
                            // Handle two-digit dates which are assumed to be 1900s
                            if( year < 100 ) year += 1900;
                            trans.Date = new DateTime( year, month, day );
                            break;
                        case 'T':
                            // Transaction amount (presumably dollars).
                            // This is actually the amount that involves this account,
                            // not necessarily the total transaction amount.
                            // Transactions with splits may have a different total amount.
                            // Particularly paychecks.
                            // The transaction total is the sum of the credits.

                            #region Split transaction sample
                            // Split sample, as exported from MS Money:
                            //
                            // D5/23'2006
                            // CX
                            // MPaycheck + cash out
                            // T384.04							<-- (debit) not the total!
                            // PEmmanuel Church
                            // LWages & Salary:Gross Pay-Cyn
                            // SWages & Salary:Gross Pay-Cyn
                            // EGross Salary
                            // $625.33							<-- (credit)
                            // STaxes:Federal Income
                            // EFederal
                            // $-15.45							<-- (debit)
                            // STaxes:Social Security
                            // EFica
                            // $-38.77							<-- (debit)
                            // STaxes:Medicare Tax 20
                            // EMedicare
                            // $-9.07							<-- (debit)
                            // STaxes:State Income Ta
                            // EState
                            // $-18.00							<-- (debit)
                            // SGroceries
                            // ECash for groceries
                            // $-150.00							<-- (debit)
                            // SCash Withdrawal
                            // ECash
                            // $-50.00							<-- (debit)
                            // SPiano Business
                            // EStudents?
                            // $40.00							<-- (credit)
                            // ^
                            #endregion

                            transAmount = Decimal.Parse( line.Substring( 1 ) );
                            trans.Amount = Math.Abs( transAmount );
                            break;
                        case 'C':
                            // Cleared status
                            // CX = cleared
                            if( line[1] == 'X' ) isCleared = true;
                            break;
                        case 'N':
                            // Check number
                            // If investment account, this is the action: buy, sell, etc.
                            checkNumber = line.Substring( 1 );
                            break;
                        case 'P':
                            // Payee
                            trans.Description = line.Substring( 1 );
                            break;
                        case 'M':
                            // Memo
                            trans.Memo = line.Substring( 1 );
                            break;
                        case 'L':
                            // Category/Account
                            transCategory = line.Substring( 1 );
                            break;
                        case 'S':
                            // Split line item category (like L above)
                            // (If there are splits, it changes the meaning of the T amount.)
                            lineItemCategory = line.Substring( 1 );
                            lineItemMemo = null;
                            lineItemAmount = 0;
                            break;
                        case 'E':
                            // Split line item memo (like M above)
                            lineItemMemo = line.Substring( 1 );
                            break;
                        case '$':
                            // Split line item amount (like T above)
                            lineItemAmount = Decimal.Parse( line.Substring( 1 ) );
                            item = BuildLineItem( ledger, trans, lineItemCategory, lineItemMemo, lineItemAmount );
                            item.IsReconciled = isCleared;
                            trans.LineItems.Add( item );
                            break;

                        // Investment indicators

                        case 'Y':	// security name
                            investmentName = line.Substring( 1 );
                            break;
                        case 'I':	// price
                            investmentPrice = line.Substring( 1 );
                            break;
                        case 'Q':	// quantity (shares)
                            investmentShares = line.Substring( 1 );
                            break;
                        case 'O':	// commission
                            investmentCommission = line.Substring( 1 );
                            break;

                        default:
                            // Unrecognized - ignore
                            break;
                    }

                    lineNumber++;
                }	// while

                if( trans.LineItems.Count > 0 )
                {
                    // Transaction had splits.
                    // Add the transaction amount as the final split.
                    item = BuildLineItem( ledger, trans, transCategory, trans.Memo, -transAmount );
                    item.Number = checkNumber;
                    item.Account = account;
                    item.CategoryObject = null;
                    item.IsReconciled = isCleared;
                    trans.LineItems.Add( item );
                    // Adjust total transaction amount.
                    trans.Amount = trans.GetCreditLineItemSum();
                }
                else
                {
                    // No splits. Must create a matching debit and credit.
                    Account otherAccount;
                    Category otherCategory;
                    otherAccount = ParseAccount( ledger, transCategory, transAmount, out otherCategory );
                    if( transAmount < 0 )
                    {
                        // Withdrawal
                        item = trans.CreateLineItem( TransactionType.Credit, account, Math.Abs( transAmount ), null );
                        item.Number = checkNumber;
                        item.IsReconciled = isCleared;
                        trans.LineItems.Add( item );
                        item = trans.CreateLineItem( TransactionType.Debit, otherAccount, Math.Abs( transAmount ), otherCategory );
                        trans.LineItems.Add( item );
                    }
                    else
                    {
                        // Deposit
                        item = trans.CreateLineItem( TransactionType.Credit, otherAccount, Math.Abs( transAmount ), otherCategory );
                        trans.LineItems.Add( item );
                        item = trans.CreateLineItem( TransactionType.Debit, account, Math.Abs( transAmount ), null );
                        item.IsReconciled = isCleared;
                        trans.LineItems.Add( item );
                    }
                }

                trans.LineItems.Sort();
                trans.Validate();

                // Special case "Opening Balance" line:
                if( trans.Description == "Opening Balance" && account.GetLineItems().Count == 0 )
                {
                    // The account name is given in the category
                    account.Name = transCategory.Trim( '[', ']' );
                    account.StartingBalance = account.IsLiability ? -transAmount : transAmount;
                    account.StartingDate = trans.Date;
                }
                else
                {
                    trans.Id = ledger.GetNextTransactionId();
                    ledger.AddTransaction( trans );
                }
            }
            catch( Exception ex )
            {
                // Don't add broken transactions
                Console.WriteLine( "Error on line number " + lineNumber.ToString() );
                Console.WriteLine( ex.ToString() );
                throw;
            }

            return lineNumber;
        }
Esempio n. 2
0
        private LineItem BuildLineItem( Ledger ledger, Transaction trans, string text, string memo, decimal amount )
        {
            // Negative amounts are made into debits
            // Positive amounts are made into credits
            // This matches the form used in QIF splits

            LineItem lineItem = null;
            Account lineItemAccount;
            Category category;

            lineItemAccount = ParseAccount( ledger, text, amount, out category );
            if( amount < 0 )
                lineItem = trans.CreateLineItem( TransactionType.Debit, lineItemAccount, Math.Abs( amount ), category );
            else
                lineItem = trans.CreateLineItem( TransactionType.Credit, lineItemAccount, Math.Abs( amount ), category );

            if( text != null && text[0] == '[' )
                lineItem.CategoryObject = null;

            lineItem.Memo = memo;

            return lineItem;
        }