Пример #1
0
        public override void Flush()
        {
            if (Posts.Any())
            {
                foreach (Post post in Posts)
                {
                    if (post.Xact == null)
                    {
                        throw new InvalidOperationException("no xact");
                    }
                    foreach (Post rPost in post.Xact.Posts)
                    {
                        PostXData xdata = rPost.XData;
                        if (!xdata.Handled && (!xdata.Received
                            ? !(rPost.Flags.HasFlag(SupportsFlagsEnum.ITEM_GENERATED) || rPost.Flags.HasFlag(SupportsFlagsEnum.POST_VIRTUAL))
                            : AlsoMatching))
                        {
                            xdata.Handled = true;
                            base.Handle(rPost);
                        }
                    }
                }
            }

            base.Flush();
        }
Пример #2
0
        /// <summary>
        /// Ported from void calc_posts::operator()(post_t& post)
        /// </summary>
        public override void Handle(Post post)
        {
            PostXData xdata = post.XData;

            if (LastPost != null)
            {
                if (!LastPost.HasXData)
                {
                    throw new InvalidOperationException("no xdata");
                }

                if (CalcRunningTotal)
                {
                    xdata.Total = Value.Clone(LastPost.XData.Total);
                }
                xdata.Count = LastPost.XData.Count + 1;
            }
            else
            {
                xdata.Count = 1;
            }

            xdata.VisitedValue = post.AddToValue(xdata.VisitedValue, AmountExpr);
            xdata.Visited      = true;

            Account acct = post.ReportedAccount;

            acct.XData.Visited = true;

            if (CalcRunningTotal)
            {
                xdata.Total = Value.AddOrSetValue(xdata.Total, xdata.VisitedValue);
            }

            base.Handle(post);

            LastPost = post;
        }
Пример #3
0
        /// <summary>
        /// Ported from handle_value
        /// </summary>
        public static void HandleValue(Value value, Account account, Xact xact, Temporaries temps, PostHandler handler,
                                       Date date        = default(Date), bool actDateP = true, Value total = null, bool directAmount = false,
                                       bool markVisited = false, bool bidirLink        = true)
        {
            Post post = temps.CreatePost(xact, account, bidirLink);

            post.Flags |= SupportsFlagsEnum.ITEM_GENERATED;

            // If the account for this post is all virtual, then report the post as
            // such.  This allows subtotal reports to show "(Account)" for accounts
            // that contain only virtual posts.
            if (account != null && account.HasXData && account.XData.AutoVirtualize)
            {
                if (!account.XData.HasNonVirtuals)
                {
                    post.Flags |= SupportsFlagsEnum.POST_VIRTUAL;
                    if (!account.XData.HasUnbVirtuals)
                    {
                        post.Flags |= SupportsFlagsEnum.POST_MUST_BALANCE;
                    }
                }
            }

            PostXData xdata = post.XData;

            if (date.IsValid())
            {
                if (actDateP)
                {
                    xdata.Date = date;
                }
                else
                {
                    xdata.ValueDate = date;
                }
            }

            Value temp = Value.Clone(value);

            switch (value.Type)
            {
            case ValueTypeEnum.Boolean:
            case ValueTypeEnum.Integer:
                temp.InPlaceCast(ValueTypeEnum.Amount);
                post.Amount = temp.AsAmount;
                break;

            case ValueTypeEnum.Amount:
                post.Amount = temp.AsAmount;
                break;

            case ValueTypeEnum.Balance:
            case ValueTypeEnum.Sequence:
                xdata.CompoundValue = temp;
                xdata.Compound      = true;
                break;

            default:
                throw new InvalidOperationException();
            }

            if (!Value.IsNullOrEmpty(total))
            {
                xdata.Total = total;
            }

            if (directAmount)
            {
                xdata.DirectAmt = true;
            }

            Logger.Current.Debug("filters.changed_value.rounding", () => String.Format("post.amount = {0}", post.Amount));

            handler.Handle(post);

            if (markVisited)
            {
                post.XData.Visited         = true;
                post.Account.XData.Visited = true;
            }
        }
Пример #4
0
        /// <summary>
        /// Ported from changed_value_posts::output_intermediate_prices
        /// </summary>
        public void OutputIntermediatePrices(Post post, Date current)
        {
            // To fix BZ#199, examine the balance of last_post and determine whether the
            // price of that amount changed after its date and before the new post's
            // date.  If so, generate an output_revaluation for that price change.
            // Mostly this is only going to occur if the user has a series of pricing
            // entries, since a posting-based revaluation would be seen here as a post.

            Value displayTotal = Value.Clone(LastTotal);

            if (displayTotal.Type == ValueTypeEnum.Sequence)
            {
                Xact xact = Temps.CreateXact();
                xact.Payee = "Commodities revalued";
                xact.Date  = current.IsValid() ? current : post.ValueDate;

                Post temp = Temps.CopyPost(post, xact);
                temp.Flags |= SupportsFlagsEnum.ITEM_GENERATED;

                PostXData xdata = temp.XData;
                if (current.IsValid())
                {
                    xdata.Date = current;
                }

                Logger.Current.Debug("filters.revalued", () => String.Format("intermediate last_total = {0}", LastTotal));

                switch (LastTotal.Type)
                {
                case ValueTypeEnum.Boolean:
                case ValueTypeEnum.Integer:
                    LastTotal.InPlaceCast(ValueTypeEnum.Amount);
                    temp.Amount = LastTotal.AsAmount;
                    break;

                case ValueTypeEnum.Amount:
                    temp.Amount = LastTotal.AsAmount;
                    break;

                case ValueTypeEnum.Balance:
                case ValueTypeEnum.Sequence:
                    xdata.CompoundValue = LastTotal;
                    xdata.Compound      = true;
                    break;

                default:
                    throw new InvalidOperationException();
                }

                BindScope innerScope = new BindScope(Report, temp);
                displayTotal = DisplayTotalExpr.Calc(innerScope);

                Logger.Current.Debug("filters.revalued", () => String.Format("intermediate display_total = {0}", displayTotal));
            }

            switch (displayTotal.Type)
            {
            case ValueTypeEnum.Void:
            case ValueTypeEnum.Integer:
            case ValueTypeEnum.Sequence:
                break;

            case ValueTypeEnum.Amount:
            case ValueTypeEnum.Balance:
            {
                if (displayTotal.Type == ValueTypeEnum.Amount)
                {
                    displayTotal.InPlaceCast(ValueTypeEnum.Balance);
                }

                IDictionary <DateTime, Amount> allPrices = new SortedDictionary <DateTime, Amount>();

                foreach (KeyValuePair <Commodity, Amount> amtComm in displayTotal.AsBalance.Amounts)
                {
                    amtComm.Key.MapPrices((d, a) => allPrices[d] = a, current, post.ValueDate, true);
                }

                // Choose the last price from each day as the price to use
                IDictionary <Date, bool> pricingDates = new SortedDictionary <Date, bool>();

                foreach (KeyValuePair <DateTime, Amount> price in allPrices.Reverse())
                {
                    // This insert will fail if a later price has already been inserted
                    // for that date.
                    var priceDate = (Date)price.Key.Date;
                    Logger.Current.Debug("filters.revalued", () => String.Format("re-inserting {0} at {1}", price.Value, priceDate));
                    pricingDates[priceDate] = true;
                }

                // Go through the time-sorted prices list, outputting a revaluation for
                // each price difference.
                foreach (KeyValuePair <Date, bool> price in pricingDates)
                {
                    OutputRevaluation(post, price.Key);
                    LastTotal = RepricedTotal;
                }
                break;
            }

            default:
                throw new InvalidOperationException();
            }
        }