Esempio n. 1
0
        public void Journal_AddXact_DoesNotAllowToAddTwoXactsWithTheSameUUIDButDifferentPostAmounts()
        {
            Account account1 = new Account();
            Account account2 = new Account();

            Journal journal = new Journal();

            Xact xact1 = new Xact();

            xact1.SetTag("UUID", Value.StringValue("val1"));
            xact1.AddPost(new Post()
            {
                Account = account1, Amount = new Amount(10)
            });
            xact1.AddPost(new Post()
            {
                Account = account2, Amount = new Amount(-10)
            });

            Xact xact2 = new Xact();

            xact2.SetTag("UUID", Value.StringValue("val1"));
            xact2.AddPost(new Post()
            {
                Account = account1, Amount = new Amount(5)
            });
            xact2.AddPost(new Post()
            {
                Account = account2, Amount = new Amount(-5)
            });

            journal.AddXact(xact1);
            Assert.Throws <RuntimeError>(() => journal.AddXact(xact2));
        }
Esempio n. 2
0
        public void Journal_AddXact_AllowsToAddDifferentUUID()
        {
            Account account1 = new Account();
            Account account2 = new Account();
            Journal journal  = new Journal();

            Xact xact1 = new Xact();

            xact1.SetTag("UUID", Value.StringValue("val1"));
            xact1.AddPost(new Post()
            {
                Account = account1, Amount = new Amount(10)
            });
            xact1.AddPost(new Post()
            {
                Account = account2, Amount = new Amount(-10)
            });

            Xact xact2 = new Xact();

            xact2.SetTag("UUID", Value.StringValue("val2"));
            xact2.AddPost(new Post()
            {
                Account = account1, Amount = new Amount(10)
            });
            xact2.AddPost(new Post()
            {
                Account = account2, Amount = new Amount(-10)
            });

            journal.AddXact(xact1);
            journal.AddXact(xact2);

            Assert.Equal(xact1, journal.ChecksumMapping["val1"]);
            Assert.Equal(xact2, journal.ChecksumMapping["val2"]);
        }
Esempio n. 3
0
        public void Journal_AddXact_DoesNotAllowToAddTwoXactsWithTheSameUUIDButDifferentNumberOfPosts()
        {
            Account account = new Account();
            Journal journal = new Journal();

            Xact xact1 = new Xact();

            xact1.SetTag("UUID", Value.StringValue("val1"));
            xact1.AddPost(new Post()
            {
                Account = account, Amount = new Amount(10)
            });
            xact1.AddPost(new Post()
            {
                Account = account, Amount = new Amount(-10)
            });

            Xact xact2 = new Xact();

            xact2.SetTag("UUID", Value.StringValue("val1"));
            xact2.AddPost(new Post()
            {
                Account = account, Amount = new Amount(10)
            });
            xact2.AddPost(new Post()
            {
                Account = account, Amount = new Amount(-5)
            });
            xact2.AddPost(new Post()
            {
                Account = account, Amount = new Amount(-5)
            });

            journal.AddXact(xact1);
            journal.AddXact(xact2);
        }
Esempio n. 4
0
        public Xact ReadXact(bool richData)
        {
            string line     = NextLine(Context.Reader);
            string origLine = line;

            if (String.IsNullOrEmpty(line) || !Index.Any())
            {
                return(null);
            }
            Context.LineNum++;

            Xact xact = new Xact();
            Post post = new Post();

            xact.State = ItemStateEnum.Cleared;

            xact.Pos = new ItemPosition()
            {
                PathName = Context.PathName,
                BegPos   = (int)Context.Reader.Position,
                BegLine  = Context.LineNum,
                Sequence = Context.Sequence++
            };

            post.Xact = xact;

            post.Pos = new ItemPosition()
            {
                PathName = Context.PathName,
                BegPos   = (int)Context.Reader.Position,
                BegLine  = Context.LineNum,
                Sequence = Context.Sequence++
            };

            post.State   = ItemStateEnum.Cleared;
            post.Account = null;

            int    n     = 0;
            Amount amt   = null;
            string total = null;
            string field;

            while (!String.IsNullOrEmpty(line) && n < Index.Count)
            {
                field = ReadField(ref line);

                switch (Index[n])
                {
                case CsvHeadersEnum.FIELD_DATE:
                    xact.Date = TimesCommon.Current.ParseDate(field);
                    break;

                case CsvHeadersEnum.FIELD_DATE_AUX:
                    if (!String.IsNullOrEmpty(field))
                    {
                        xact.DateAux = TimesCommon.Current.ParseDate(field);
                    }
                    break;

                case CsvHeadersEnum.FIELD_CODE:
                    if (!String.IsNullOrEmpty(field))
                    {
                        xact.Code = field;
                    }
                    break;

                case CsvHeadersEnum.FIELD_PAYEE:
                {
                    bool found = false;
                    foreach (Tuple <Mask, string> value in Context.Journal.PayeeAliasMappings)
                    {
                        Logger.Current.Debug("csv.mappings", () => String.Format("Looking for payee mapping: {0}", value.Item1));
                        if (value.Item1.Match(field))
                        {
                            xact.Payee = value.Item2;
                            found      = true;
                            break;
                        }
                    }
                    if (!found)
                    {
                        xact.Payee = field;
                    }
                    break;
                }

                case CsvHeadersEnum.FIELD_AMOUNT:
                {
                    amt = new Amount();
                    amt.Parse(ref field, AmountParseFlagsEnum.PARSE_NO_REDUCE);
                    if (!amt.HasCommodity && CommodityPool.Current.DefaultCommodity != null)
                    {
                        amt.SetCommodity(CommodityPool.Current.DefaultCommodity);
                    }
                    post.Amount = amt;
                    break;
                }

                case CsvHeadersEnum.FIELD_COST:
                {
                    amt = new Amount();
                    amt.Parse(ref field, AmountParseFlagsEnum.PARSE_NO_REDUCE);
                    if (!amt.HasCommodity && CommodityPool.Current.DefaultCommodity != null)
                    {
                        amt.SetCommodity(CommodityPool.Current.DefaultCommodity);
                    }
                    post.Cost = amt;
                    break;
                }

                case CsvHeadersEnum.FIELD_TOTAL:
                    total = field;
                    break;

                case CsvHeadersEnum.FIELD_NOTE:
                    if (!String.IsNullOrEmpty(field))
                    {
                        xact.Note = field;
                    }
                    break;

                case CsvHeadersEnum.FIELD_UNKNOWN:
                    if (!String.IsNullOrEmpty(Names[n]) && !String.IsNullOrEmpty(field))
                    {
                        xact.SetTag(Names[n], Value.StringValue(field));
                    }
                    break;

                default:
                    throw new InvalidOperationException();
                }
                n++;
            }

            if (richData)
            {
                xact.SetTag("Imported", Value.StringValue(TimesCommon.Current.FormatDate(TimesCommon.Current.CurrentDate, FormatTypeEnum.FMT_WRITTEN).ToString()));
                xact.SetTag("CSV", Value.StringValue(origLine));
            }

            // Translate the account name, if we have enough information to do so

            foreach (Tuple <Mask, Account> value in Context.Journal.PayeesForUnknownAccounts)
            {
                if (value.Item1.Match(xact.Payee))
                {
                    post.Account = value.Item2;
                    break;
                }
            }

            xact.AddPost(post);

            // Create the "balancing post", which refers to the account for this data

            post      = new Post();
            post.Xact = xact;

            post.Pos = new ItemPosition()
            {
                PathName = Context.PathName,
                BegPos   = (int)Context.Reader.Position,
                BegLine  = Context.LineNum,
                Sequence = Context.Sequence++
            };

            post.State   = ItemStateEnum.Cleared;
            post.Account = Context.Master;

            if (amt != null && !amt.IsEmpty)
            {
                post.Amount = amt.Negated();
            }

            if (!String.IsNullOrEmpty(total))
            {
                amt = new Amount();
                amt.Parse(ref total, AmountParseFlagsEnum.PARSE_NO_REDUCE);
                if (!amt.HasCommodity && CommodityPool.Current.DefaultCommodity != null)
                {
                    amt.SetCommodity(CommodityPool.Current.DefaultCommodity);
                }
                post.AssignedAmount = amt;
            }

            xact.AddPost(post);
            return(xact);
        }