Beispiel #1
0
        public override void Clear()
        {
            DisplayAmountExpr.MarkUncomplited();
            DisplayTotalExpr.MarkUncomplited();

            LastDisplayTotal = new Value();

            Temps.Clear();
            base.Clear();

            CreateAccounts();
        }
Beispiel #2
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();
            }
        }
Beispiel #3
0
        public bool OutputRounding(Post post)
        {
            BindScope boundScope      = new BindScope(Report, post);
            Value     newDisplayTotal = new Value();

            if (ShowRounding)
            {
                newDisplayTotal = DisplayTotalExpr.Calc(boundScope).StripAnnotations(Report.WhatToKeep());
                Logger.Current.Debug("filters.changed_value.rounding", () => String.Format("rounding.new_display_total     = {0}", newDisplayTotal));
            }

            // Allow the posting to be displayed if:
            //  1. Its display_amount would display as non-zero, or
            //  2. The --empty option was specified, or
            //  3. a) The account of the posting is <Revalued>, and
            //     b) the revalued option is specified, and
            //     c) the --no-rounding option is not specified.

            if (post.Account == RevaluedAccount)
            {
                if (ShowRounding)
                {
                    LastDisplayTotal = newDisplayTotal;
                }
                return(true);
            }

            Value repricedAmount = DisplayAmountExpr.Calc(boundScope).StripAnnotations(Report.WhatToKeep());

            if (!Value.IsNullOrEmptyOrFalse(repricedAmount))
            {
                if (!Value.IsNullOrEmpty(LastDisplayTotal))
                {
                    Logger.Current.Debug("filters.changed_value.rounding", () => String.Format("rounding.repriced_amount       = {0}", repricedAmount));

                    Value preciseDisplayTotal = newDisplayTotal.Truncated() - repricedAmount.Truncated();

                    Logger.Current.Debug("filters.changed_value.rounding", () => String.Format("rounding.precise_display_total = {0}", preciseDisplayTotal));
                    Logger.Current.Debug("filters.changed_value.rounding", () => String.Format("rounding.last_display_total    = {0}", LastDisplayTotal));

                    Value diff = preciseDisplayTotal - LastDisplayTotal;
                    if (!Value.IsNullOrEmptyOrFalse(diff))
                    {
                        Logger.Current.Debug("filters.changed_value.rounding", () => String.Format("rounding.diff                  = {0}", diff));

                        FiltersCommon.HandleValue(
                            /* value=         */ diff,
                            /* account=       */ RoundingAccount,
                            /* xact=          */ post.Xact,
                            /* temps=         */ Temps,
                            /* handler=       */ (PostHandler)Handler,
                            /* date=          */ default(Date),
                            /* act_date_p=    */ true,
                            /* total=         */ preciseDisplayTotal,
                            /* direct_amount= */ true,
                            /* mark_visited=  */ false,
                            /* bidir_link=    */ false);
                    }
                }
                if (ShowRounding)
                {
                    LastDisplayTotal = newDisplayTotal;
                }
                return(true);
            }
            else
            {
                return(Report.EmptyHandler.Handled);
            }
        }