/// <summary>
        ///     根据表达式生成记账凭证
        /// </summary>
        /// <param name="expr">表达式</param>
        /// <returns>记账凭证</returns>
        private Voucher GenerateVoucher(ref string expr)
        {
            var time = Parsing.UniqueTime(ref expr) ?? ClientDateTime.Today;
            var abbr = Parsing.Token(ref expr);

            var template = Templates.Config.Templates.FirstOrDefault(t => t.Name == abbr) ??
                           throw new KeyNotFoundException($"找不到常见记账凭证{abbr}");

            var num = 1D;

            if (template.TemplateType is UtilTemplateType.Value or UtilTemplateType.Fill)
            {
                var valt = Parsing.Double(ref expr);
                var val  = valt ?? (template.Default ?? throw new ApplicationException($"常见记账凭证{template.Name}没有默认值"));

                if (template.TemplateType == UtilTemplateType.Value)
                {
                    num = val;
                }
                else
                {
                    var arr = Accountant.RunGroupedQuery($"{template.Query} [~{time:yyyyMMdd}] ``v").Fund;
                    num = arr - val;
                }
            }

            return(num.IsZero() ? null : MakeVoucher(template, num, time));
        }
Example #2
0
        public VoucherDetail ParseVoucherDetail(ref string expr)
        {
            var lst = new List<string>();

            Parsing.TrimStartComment(ref expr);
            var user = Parsing.Token(ref expr, false, t => t.StartsWith("U", StringComparison.Ordinal)).ParseUserSpec();
            var currency = Parsing.Token(ref expr, false, t => t.StartsWith("@", StringComparison.Ordinal))
                    ?.Substring(1)
                    .ToUpperInvariant()
                ?? BaseCurrency.Now;
            Parsing.TrimStartComment(ref expr);
            var title = Parsing.Title(ref expr);
            if (title == null)
                if (!AlternativeTitle(ref expr, lst, ref title))
                    return null;

            double? fund;

            while (true)
            {
                Parsing.TrimStartComment(ref expr);
                if ((fund = Parsing.Double(ref expr)) != null)
                    break;

                Parsing.TrimStartComment(ref expr);
                if (Parsing.Optional(ref expr, "null"))
                    break;
                if (Parsing.Optional(ref expr, "/"))
                    break;

                if (lst.Count > 2)
                    throw new ArgumentException("语法错误", nameof(expr));

                Parsing.TrimStartComment(ref expr);
                lst.Add(Parsing.Token(ref expr));
            }

            var content = lst.Count >= 1 ? lst[0] : null;
            var remark = lst.Count >= 2 ? lst[1] : null;

            if (content == "G()")
                content = Guid.NewGuid().ToString().ToUpperInvariant();

            if (remark == "G()")
                remark = Guid.NewGuid().ToString().ToUpperInvariant();

            return new VoucherDetail
                {
                    User = user,
                    Currency = currency,
                    Title = title.Title,
                    SubTitle = title.SubTitle,
                    Content = string.IsNullOrEmpty(content) ? null : content,
                    Fund = fund,
                    Remark = string.IsNullOrEmpty(remark) ? null : remark,
                };
        }
Example #3
0
        public IQueryResult Execute(string expr, IEntitiesSerializer serializer)
        {
            expr = expr.Rest();
            var rev  = true;
            var val  = Parsing.Double(ref expr);
            var curr = Parsing.Token(ref expr).ToUpperInvariant();

            if (!val.HasValue)
            {
                rev = false;
                val = Parsing.DoubleF(ref expr);
            }

            var date = Parsing.UniqueTime(ref expr) ?? ClientDateTime.Today;

            Parsing.Eof(expr);
            var res = rev ? ExchangeFactory.Instance.To(date, curr) : ExchangeFactory.Instance.From(date, curr);

            return(new PlainText((res * val.Value).ToString("R")));
        }
        /// <inheritdoc />
        public override IQueryResult Execute(string expr, IEntitiesSerializer serializer)
        {
            var  voucherID = Parsing.Token(ref expr);
            Guid?guid      = null;
            var  guidT     = Guid.Empty;

            // ReSharper disable once AccessToModifiedClosure
            if (Parsing.Token(ref expr, true, s => Guid.TryParse(s, out guidT)) != null)
            {
                guid = guidT;
            }
            var name  = Parsing.Token(ref expr);
            var lifeT = Parsing.Double(ref expr);

            Parsing.Eof(expr);

            var voucher = Accountant.SelectVoucher(voucherID);

            if (voucher == null)
            {
                throw new ApplicationException("找不到记账凭证");
            }

            var detail = voucher.Details.Single(
                vd => (vd.Title == 1601 || vd.Title == 1701) &&
                (!guid.HasValue || string.Equals(
                     vd.Content,
                     guid.ToString(),
                     StringComparison.OrdinalIgnoreCase)));

            var isFixed = detail.Title == 1601;
            var life    = (int?)lifeT ?? (isFixed ? 3 : 0);

            var asset = new Asset
            {
                StringID                    = detail.Content,
                Name                        = name,
                Date                        = voucher.Date,
                User                        = detail.User,
                Currency                    = detail.Currency,
                Value                       = detail.Fund,
                Salvage                     = life == 0 ? detail.Fund : isFixed ? detail.Fund * 0.05 : 0,
                Life                        = life,
                Title                       = detail.Title,
                Method                      = life == 0 ? DepreciationMethod.None : DepreciationMethod.StraightLine,
                DepreciationTitle           = isFixed ? 1602 : 1702,
                DepreciationExpenseTitle    = 6602,
                DepreciationExpenseSubTitle = isFixed ? 7 : 11,
                DevaluationTitle            = isFixed ? 1603 : 1703,
                DevaluationExpenseTitle     = 6701,
                DevaluationExpenseSubTitle  = isFixed ? 5 : 6,
                Schedule                    = new List <AssetItem>
                {
                    new AcquisitionItem
                    {
                        Date      = voucher.Date,
                        VoucherID = voucher.ID,
                        // ReSharper disable once PossibleInvalidOperationException
                        OrigValue = detail.Fund.Value,
                    },
                },
            };

            Accountant.Upsert(asset);
            // ReSharper disable once PossibleInvalidOperationException
            asset = Accountant.SelectAsset(asset.ID.Value);
            Accountant.Depreciate(asset);
            Accountant.Upsert(asset);

            return(new DirtyText(serializer.PresentAsset(asset).Wrap()));
        }
Example #5
0
        /// <inheritdoc />
        public override IQueryResult Execute(string expr, IEntitiesSerializer serializer)
        {
            var extraMonths = (int)(Parsing.Double(ref expr) ?? 6);
            var prefix      = Parsing.Token(ref expr);

            Parsing.Eof(expr);

            var accts = Templates.Config.Accounts.Where(a => string.IsNullOrWhiteSpace(a.User) || ClientUser.Name == a.User).ToList();
            var n     = accts.Count;
            var until = ClientDateTime.Today.AddMonths(extraMonths);

            var aggs = new double[n];
            var rst  = new Dictionary <DateTime, double[, ]>();

            for (var i = 0; i < n; i++)
            {
                aggs[i] = Accountant.RunGroupedQuery($"U{accts[i].User.AsUser()} @{accts[i].Currency}*({accts[i].QuickAsset}) [~.]``v").Fund;

                foreach (var(date, value) in GetItems(accts[i], serializer, until))
                {
                    if (date <= ClientDateTime.Today)
                    {
                        continue;
                    }
                    if (date > until)
                    {
                        continue;
                    }
                    if (value.IsZero())
                    {
                        continue;
                    }

                    if (!rst.ContainsKey(date))
                    {
                        rst.Add(date, new double[n, 2]);
                    }

                    if (value >= 0)
                    {
                        rst[date][i, 0] += value;
                    }
                    else
                    {
                        rst[date][i, 1] += value;
                    }
                }
            }

            var sb = new StringBuilder();

            sb.Append(prefix);
            sb.Append("Date    ");
            for (var i = 0; i < n; i++)
            {
                var c = accts[i].Currency;
                sb.Append($"++++ {c} ++++".PadLeft(15));
                sb.Append($"---- {c} ----".PadLeft(15));
                sb.Append($"#### {c} ####".PadLeft(15));
            }

            sb.AppendLine("@@@@ All @@@@".PadLeft(15));

            {
                sb.Append(prefix);
                sb.Append("Today   ");

                var sum = 0D;
                for (var i = 0; i < n; i++)
                {
                    sum += aggs[i] * Accountant.From(
                        ClientDateTime.Today,
                        accts[i].Currency);

                    sb.Append("".PadLeft(15));
                    sb.Append("".PadLeft(15));
                    sb.Append(aggs[i].AsCurrency(accts[i].Currency).PadLeft(15));
                }

                sb.AppendLine(sum.AsCurrency(BaseCurrency.Now).PadLeft(15));
            }

            foreach (var kvp in rst.OrderBy(kvp => kvp.Key))
            {
                sb.Append(prefix);
                sb.Append($"{kvp.Key.AsDate()}");

                var sum = 0D;
                for (var i = 0; i < n; i++)
                {
                    aggs[i] += kvp.Value[i, 0] + kvp.Value[i, 1];

                    sum += aggs[i] * Accountant.From(
                        kvp.Key,
                        accts[i].Currency);

                    if (!kvp.Value[i, 0].IsZero())
                    {
                        sb.Append(kvp.Value[i, 0].AsCurrency(accts[i].Currency).PadLeft(15));
                    }
                    else
                    {
                        sb.Append("".PadLeft(15));
                    }

                    if (!kvp.Value[i, 1].IsZero())
                    {
                        sb.Append(kvp.Value[i, 1].AsCurrency(accts[i].Currency).PadLeft(15));
                    }
                    else
                    {
                        sb.Append("".PadLeft(15));
                    }

                    sb.Append(aggs[i].AsCurrency(accts[i].Currency).PadLeft(15));
                }

                sb.AppendLine(sum.AsCurrency(BaseCurrency.Now).PadLeft(15));
            }

            return(new PlainText(sb.ToString()));
        }
    /// <inheritdoc />
    public override async IAsyncEnumerable <string> Execute(string expr, Session session)
    {
        var extraMonths = (int)(Parsing.Double(ref expr) ?? 6);
        var prefix      = Parsing.Token(ref expr);

        Parsing.Eof(expr);

        var accts = Templates.Config.Accounts
                    .Where(a => string.IsNullOrWhiteSpace(a.User) || session.Client.User == a.User).ToList();
        var n     = accts.Count;
        var until = session.Client.Today.AddMonths(extraMonths);

        var aggs = new double[n];
        var rst  = new Dictionary <DateTime, double[, ]>();

        for (var i = 0; i < n; i++)
        {
            aggs[i] = (await session.Accountant.RunGroupedQueryAsync(
                           $"U{accts[i].User.AsUser()} @{accts[i].Currency}*({accts[i].QuickAsset}) [~.]``v")).Fund;

            foreach (var(date, value) in GetItems(accts[i], session, until).ToEnumerable())
            {
                if (date <= session.Client.Today)
                {
                    continue;
                }
                if (date > until)
                {
                    continue;
                }
                if (value.IsZero())
                {
                    continue;
                }

                if (!rst.ContainsKey(date))
                {
                    rst.Add(date, new double[n, 2]);
                }

                if (value >= 0)
                {
                    rst[date][i, 0] += value;
                }
                else
                {
                    rst[date][i, 1] += value;
                }
            }
        }

        var sb = new StringBuilder();

        sb.Append(prefix);
        sb.Append("Date    ");
        for (var i = 0; i < n; i++)
        {
            var c = accts[i].Currency;
            sb.Append($"++++ {c} ++++".PadLeft(15));
            sb.Append($"---- {c} ----".PadLeft(15));
            sb.Append($"#### {c} ####".PadLeft(15));
        }

        sb.AppendLine("@@@@ All @@@@".PadLeft(15));
        yield return(sb.ToString());

        sb.Clear();

        {
            sb.Append(prefix);
            sb.Append("Today   ");

            var sum = 0D;
            for (var i = 0; i < n; i++)
            {
                sum += aggs[i] *
                       await session.Accountant.Query(session.Client.Today, accts[i].Currency, BaseCurrency.Now);

                sb.Append("".PadLeft(15));
                sb.Append("".PadLeft(15));
                sb.Append(aggs[i].AsCurrency(accts[i].Currency).PadLeft(15));
            }

            sb.AppendLine(sum.AsCurrency(BaseCurrency.Now).PadLeft(15));
            yield return(sb.ToString());

            sb.Clear();
        }

        foreach (var kvp in rst.OrderBy(static kvp => kvp.Key))
Example #7
0
    /// <inheritdoc />
    public override async IAsyncEnumerable <string> Execute(string expr, Session session)
    {
        var  voucherID = Parsing.Token(ref expr);
        Guid?guid      = null;
        var  guidT     = Guid.Empty;

        // ReSharper disable once AccessToModifiedClosure
        if (Parsing.Token(ref expr, true, s => Guid.TryParse(s, out guidT)) != null)
        {
            guid = guidT;
        }
        var name  = Parsing.Token(ref expr);
        var lifeT = Parsing.Double(ref expr);

        Parsing.Eof(expr);

        var voucher = await session.Accountant.SelectVoucherAsync(voucherID);

        if (voucher == null)
        {
            throw new ApplicationException("找不到记账凭证");
        }

        var detail = voucher.Details.Single(
            vd => vd.Title is 1601 or 1701 &&
            (!guid.HasValue || string.Equals(
                 vd.Content,
                 guid.ToString(),
                 StringComparison.OrdinalIgnoreCase)));

        var isFixed = detail.Title == 1601;
        var life    = (int?)lifeT ?? (isFixed ? 3 : 0);

        var asset = new Asset
        {
            StringID                    = detail.Content,
            Name                        = name,
            Date                        = voucher.Date,
            User                        = detail.User,
            Currency                    = detail.Currency,
            Value                       = detail.Fund,
            Salvage                     = life == 0 ? detail.Fund : isFixed ? detail.Fund * 0.05 : 0,
            Life                        = life,
            Title                       = detail.Title,
            Method                      = life == 0 ? DepreciationMethod.None : DepreciationMethod.StraightLine,
            DepreciationTitle           = isFixed ? 1602 : 1702,
            DepreciationExpenseTitle    = 6602,
            DepreciationExpenseSubTitle = isFixed ? 7 : 11,
            DevaluationTitle            = isFixed ? 1603 : 1703,
            DevaluationExpenseTitle     = 6701,
            DevaluationExpenseSubTitle  = isFixed ? 5 : 6,
            Schedule                    = new()
            {
                new AcquisitionItem
                {
                    Date = voucher.Date, VoucherID = voucher.ID, OrigValue = detail.Fund !.Value,
                },
            },
        };

        await session.Accountant.UpsertAsync(asset);

        asset = await session.Accountant.SelectAssetAsync(asset.ID !.Value);

        Accountant.Depreciate(asset);
        await session.Accountant.UpsertAsync(asset);

        yield return(session.Serializer.PresentAsset(asset).Wrap());
    }