/// <inheritdoc />
    public async IAsyncEnumerable <string> Execute(string expr, Session session)
    {
        expr = expr.Rest();
        DateFilter rng;
        IAsyncEnumerable <string> iae;

        switch (expr.Initial())
        {
        case "lst":
            expr = expr.Rest();
            rng  = Parsing.Range(ref expr, session.Client) ?? DateFilter.Unconstrained;
            Parsing.Eof(expr);
            iae = ListHistory(rng).ToAsyncEnumerable();
            break;

        case "rst":
            expr = expr.Rest();
            rng  = Parsing.Range(ref expr, session.Client) ?? DateFilter.Unconstrained;
            Parsing.Eof(expr);
            iae = PerformAction(session, rng, true);
            break;

        default:
            rng = Parsing.Range(ref expr, session.Client) ?? DateFilter.Unconstrained;
            Parsing.Eof(expr);
            iae = PerformAction(session, await AutomaticRange(session, rng), false);
            break;
        }

        await foreach (var e in iae)
        {
            yield return(e);
        }
    }
Example #2
0
    public override async IAsyncEnumerable<string> Execute(string expr, Session session)
    {
        var len = expr.Length;
        var aux = Parsing.PureDetailQuery(ref expr, session.Client);
        if (len == expr.Length)
            aux = null;
        var rng = Parsing.Range(ref expr, session.Client) ?? DateFilter.Unconstrained;
        Parsing.Eof(expr);

        foreach (var configCouple in Templates.Config.Couples)
        await foreach (var ret in AnalyzeCouple(session, configCouple, rng, aux))
            yield return ret;
    }
Example #3
0
    protected DistributedShell()
    {
        var resetComposer =
            new ShellComposer
        {
            new ShellComponent(
                "soft",
                (expr, session) =>
            {
                var dist = Parsing.DistributedQuery(ref expr, session.Client);
                var rng  = Parsing.Range(ref expr, session.Client) ?? DateFilter.Unconstrained;
                Parsing.Eof(expr);
                return(ExecuteResetSoft(dist, rng, session));
            }),
            new ShellComponent(
                "mixed",
                (expr, session) =>
            {
                var dist = Parsing.DistributedQuery(ref expr, session.Client);
                var rng  = Parsing.Range(ref expr, session.Client) ?? DateFilter.Unconstrained;
                Parsing.Eof(expr);
                return(ExecuteResetMixed(dist, rng, session));
            }),
            new ShellComponent(
                "hard",
                (expr, session) =>
            {
                var dist     = Parsing.DistributedQuery(ref expr, session.Client);
                var vouchers = Parsing.OptColVouchers(ref expr, session.Client);
                Parsing.Eof(expr);
                return(ExecuteResetHard(dist, vouchers, session));
            }),
        };

        m_Composer =
            new ShellComposer
        {
            new ShellComponent(
                "all",
                (expr, session) =>
            {
                var safe = Parsing.Token(ref expr, false, static t => t == "unsafe") == null;
                var dist = Parsing.DistributedQuery(ref expr, session.Client);
                Parsing.Eof(expr);
                if (dist.IsDangerous() && safe)
                {
                    throw new SecurityException("检测到弱检索式");
                }

                return(ExecuteList(dist, null, false, session));
            }),
        /// <inheritdoc />
        public Voucher ParseVoucher(string expr)
        {
            if (!expr.StartsWith(TheToken, StringComparison.Ordinal))
                throw new FormatException("格式错误");

            expr = expr.Substring(TheToken.Length);
            var v = GetVoucher(ref expr);
            Parsing.TrimStartComment(ref expr);
            if (Parsing.Token(ref expr, false) != "}")
                throw new FormatException("格式错误");

            Parsing.Eof(expr);
            return v;
        }
Example #5
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")));
        }
Example #6
0
    /// <inheritdoc />
    public override async IAsyncEnumerable <string> Execute(string expr, Session session)
    {
        var voucherID = Parsing.Token(ref expr);
        var guids     = new List <string>();
        var guidT     = Guid.Empty;

        // ReSharper disable once AccessToModifiedClosure
        while (Parsing.Token(ref expr, true, s => Guid.TryParse(s, out guidT)) != null)
        {
            guids.Add(guidT.ToString());
        }
        Parsing.Eof(expr);

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

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

        foreach (var detail in voucher.Details.Where(static vd => vd.Title is 1601 or 1701)
Example #7
0
    /// <inheritdoc />
    public override async IAsyncEnumerable<string> Execute(string expr, Session session)
    {
        var remark = Parsing.Token(ref expr);
        var rate = Parsing.DoubleF(ref expr) / 10000D;
        var all = Parsing.Optional(ref expr, "all");
        var endDate = !all ? Parsing.UniqueTime(ref expr, session.Client) : null;
        Parsing.Eof(expr);

        var loans = (await session.Accountant.RunGroupedQueryAsync($"({MajorFilter()})-\"\" ``rtcC")).Items
            .Cast<ISubtotalRemark>()
            .ToList();
        var rmkObj =
            loans.Single(
                b =>
                    b.Remark?.StartsWith(remark, StringComparison.InvariantCultureIgnoreCase) == true &&
                    !b.Remark.EndsWith("-利息", StringComparison.Ordinal));
        var titleObj = rmkObj.Items.Cast<ISubtotalTitle>().Single();
        var cntObj = titleObj.Items.Cast<ISubtotalContent>().Single();
        var title = titleObj.Title!.Value;
        var content = cntObj.Content;
        var rmk = rmkObj.Remark;
        var currency = cntObj.Items.Cast<ISubtotalCurrency>().Single().Currency;
        var info = new LoanInfo
            {
                Currency = currency,
                Title = title,
                Content = content,
                Remark = rmk,
                Rate = rate,
            };

        await using var vir = session.Accountant.Virtualize();
        if (!all && !endDate.HasValue ||
            endDate.HasValue)
        {
            var lastD = (await session.Accountant.RunVoucherQueryAsync(info.QueryInterest())
                    .OrderByDescending(static v => v.Date, new DateComparer())
        /// <inheritdoc />
        public Voucher ParseVoucher(string expr)
        {
            if (!expr.StartsWith(TheToken, StringComparison.Ordinal))
            {
                throw new FormatException("格式错误");
            }

            expr = expr.Substring(TheToken.Length);
            if (ParsingF.Token(ref expr, false, s => s == "!") == null)
            {
                throw new NotImplementedException();
            }

            var v = GetVoucher(ref expr);

            Parsing.TrimStartComment(ref expr);
            if (Parsing.Token(ref expr, false) != "}")
            {
                throw new FormatException("格式错误");
            }

            Parsing.Eof(expr);
            return(v);
        }
Example #9
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 IQueryResult Execute(string expr, IEntitiesSerializer serializer)
        {
            var content = Parsing.Token(ref expr);
            var avg     = Parsing.DoubleF(ref expr);

            Parsing.Eof(expr);

            var tdy     = ClientDateTime.Today;
            var ldom    = AccountantHelper.LastDayOfMonth(tdy.Year, tdy.Month);
            var srng    = new DateFilter(new DateTime(tdy.Year, tdy.Month, 1, 0, 0, 0, DateTimeKind.Utc), tdy);
            var balance = Accountant.RunGroupedQuery(
                $"T1002 {content.Quotation('\'')} [~{tdy.AsDate()}]`vD{srng.AsDateRange()}");

            var bal = 0D;
            var btd = 0D;

            foreach (var b in balance.Items.Cast <ISubtotalDate>())
            {
                if (b.Date == tdy)
                {
                    btd += b.Fund;
                }
                else
                {
                    bal += b.Fund;
                }
            }

            var targ = ldom.Day * avg;

            var sb = new StringBuilder();

            sb.AppendLine($"Target: {targ.AsCurrency()}");
            sb.AppendLine($"Balance until yesterday: {bal.AsCurrency()}");
            if ((bal - targ).IsNonNegative())
            {
                sb.AppendLine("Achieved.");
                sb.AppendLine();

                sb.AppendLine(
                    (btd - avg).IsNonNegative()
                        ? $"Plan A: Credit {(btd - avg).AsCurrency()}, Balance {avg.AsCurrency()}"
                        : $"Plan A: Debit {(avg - btd).AsCurrency()}, Balance {avg.AsCurrency()}");
                sb.AppendLine("Plan B: No Action");
            }
            else
            {
                var res = targ - bal;
                var rsd = ldom.Day - tdy.Day + 1;
                sb.AppendLine($"Deficiency: {res.AsCurrency()}");
                var avx = res / rsd;
                if ((rsd * avg - res).IsNonNegative())
                {
                    sb.AppendLine($"Average deficiency: {avx.AsCurrency()} <= {avg.AsCurrency()}");
                    sb.AppendLine();

                    sb.AppendLine(
                        (btd - avx).IsNonNegative()
                            ? $"Plan A: Credit {(btd - avx).AsCurrency()}, Balance {avx.AsCurrency()}"
                            : $"Plan A: Debit {(avx - btd).AsCurrency()}, Balance {avx.AsCurrency()}");
                    sb.AppendLine(
                        (btd - avg).IsNonNegative()
                            ? $"Plan B: Credit {(btd - avg).AsCurrency()}, Balance {avg.AsCurrency()}"
                            : $"Plan B: Debit {(avg - btd).AsCurrency()}, Balance {avg.AsCurrency()}");
                }
                else
                {
                    sb.AppendLine($"Average deficiency: {avx.AsCurrency()} > {avg.AsCurrency()}");
                    sb.AppendLine();

                    sb.AppendLine(
                        (btd - avx).IsNonNegative()
                            ? $"Plan: Credit {(btd - avx).AsCurrency()}, Balance {avx.AsCurrency()}"
                            : $"Plan: Debit {(avx - btd).AsCurrency()}, Balance {avx.AsCurrency()}");
                }
            }

            return(new PlainText(sb.ToString()));
        }
Example #11
0
        /// <inheritdoc />
        public override IQueryResult Execute(string expr, IEntitiesSerializer serializer)
        {
            var remark = Parsing.Token(ref expr);
            var rate = Parsing.DoubleF(ref expr) / 10000D;
            var all = Parsing.Optional(ref expr, "all");
            var endDate = !all ? Parsing.UniqueTime(ref expr) : null;
            Parsing.Eof(expr);

            var loans = Accountant.RunGroupedQuery($"({MajorFilter()})-\"\" ``rtcC").Items
                .Cast<ISubtotalRemark>()
                .ToList();
            var rmkObj =
                loans.Single(
                    b =>
                        b.Remark?.StartsWith(remark, StringComparison.InvariantCultureIgnoreCase) == true &&
                        !b.Remark.EndsWith("-利息", StringComparison.Ordinal));
            var titleObj = rmkObj.Items.Cast<ISubtotalTitle>().Single();
            var cntObj = titleObj.Items.Cast<ISubtotalContent>().Single();
            // ReSharper disable once PossibleInvalidOperationException
            var title = titleObj.Title.Value;
            var content = cntObj.Content;
            var rmk = rmkObj.Remark;
            var currency = cntObj.Items.Cast<ISubtotalCurrency>().Single().Currency;
            var info = new LoanInfo
                {
                    Currency = currency,
                    Title = title,
                    Content = content,
                    Remark = rmk,
                    Rate = rate
                };

            if (!all && !endDate.HasValue ||
                endDate.HasValue)
            {
                // ReSharper disable once PossibleInvalidOperationException
                var lastD = Accountant.RunVoucherQuery(info.QueryInterest(this))
                        .OrderByDescending(v => v.Date, new DateComparer())
                        .FirstOrDefault()
                        ?.Date ??
                    Accountant.RunVoucherQuery(info.QueryCapital(this))
                        .OrderBy(v => v.Date, new DateComparer())
                        .First()
                        .Date.Value;
                var capQuery = $"{info.QueryCapital(this)} [~{lastD.AsDate()}]``v";
                var intQuery = $"{info.QueryInterest(this)} [~{lastD.AsDate()}]``v";
                var capitalIntegral = Accountant.RunGroupedQuery(capQuery).Fund;
                var interestIntegral = Accountant.RunGroupedQuery(intQuery).Fund;
                Regularize(
                    info,
                    ref capitalIntegral,
                    ref interestIntegral,
                    lastD,
                    endDate ?? ClientDateTime.Today);
            }
            else
            {
                var capitalIntegral = 0D;
                var interestIntegral = 0D;
                Regularize(
                    info,
                    ref capitalIntegral,
                    ref interestIntegral,
                    null,
                    ClientDateTime.Today);
            }

            return new DirtySucceed();
        }
    /// <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))
 /// <inheritdoc />
 public virtual VoucherDetail ParseVoucherDetail(string expr)
 {
     var res = ParseVoucherDetail(ref expr);
     Parsing.Eof(expr);
     return res;
 }
Example #14
0
        /// <inheritdoc />
        public override IQueryResult Execute(string expr, IEntitiesSerializer serializer)
        {
            var voucherID = Parsing.Token(ref expr);
            var guids     = new List <string>();
            var guidT     = Guid.Empty;

            // ReSharper disable once AccessToModifiedClosure
            while (Parsing.Token(ref expr, true, s => Guid.TryParse(s, out guidT)) != null)
            {
                guids.Add(guidT.ToString());
            }
            Parsing.Eof(expr);

            var voucher = Accountant.SelectVoucher(voucherID);

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

            var sb = new StringBuilder();

            foreach (var detail in voucher.Details.Where(vd => vd.Title is 1601 or 1701))
            {
                if (guids.Count != 0 &&
                    !guids.Contains(detail.Content))
                {
                    continue;
                }

                var asset = Accountant.SelectAsset(Guid.Parse(detail.Content));
                foreach (var item in asset.Schedule)
                {
                    if (item is DispositionItem)
                    {
                        throw new InvalidOperationException("已经处置");
                    }

                    if (item.Date < voucher.Date)
                    {
                        if (item.VoucherID == null)
                        {
                            throw new InvalidOperationException("尚未注册");
                        }
                    }
                    else
                    {
                        if (item.VoucherID != null)
                        {
                            throw new InvalidOperationException("注册过多");
                        }
                    }
                }

                var id = asset.Schedule.FindIndex(it => it.Date >= voucher.Date);
                if (id != -1)
                {
                    asset.Schedule.RemoveRange(id, asset.Schedule.Count - id);
                }

                asset.Schedule.Add(new DispositionItem {
                    Date = voucher.Date, VoucherID = voucher.ID
                });
                sb.Append(serializer.PresentAsset(asset).Wrap());
                Accountant.Upsert(asset);
            }

            if (sb.Length > 0)
            {
                return(new DirtyText(sb.ToString()));
            }

            return(new PlainSucceed());
        }
        protected DistributedShell(Accountant helper)
        {
            Accountant = helper;
            var resetComopser =
                new ShellComposer
            {
                new ShellComponent(
                    "soft",
                    (expr, serializer) =>
                {
                    var dist = Parsing.DistributedQuery(ref expr);
                    var rng  = Parsing.Range(ref expr) ?? DateFilter.Unconstrained;
                    Parsing.Eof(expr);
                    return(ExecuteResetSoft(dist, rng));
                }),
                new ShellComponent(
                    "mixed",
                    (expr, serializer) =>
                {
                    var dist = Parsing.DistributedQuery(ref expr);
                    var rng  = Parsing.Range(ref expr) ?? DateFilter.Unconstrained;
                    Parsing.Eof(expr);
                    return(ExcuteResetMixed(dist, rng));
                }),
                new ShellComponent(
                    "hard",
                    (expr, serializer) =>
                {
                    var dist     = Parsing.DistributedQuery(ref expr);
                    var vouchers = Parsing.OptColVouchers(ref expr);
                    Parsing.Eof(expr);
                    return(ExecuteResetHard(dist, vouchers));
                })
            };

            m_Composer =
                new ShellComposer
            {
                new ShellComponent(
                    "all",
                    (expr, serializer) =>
                {
                    var safe = Parsing.Token(ref expr, false, t => t == "unsafe") == null;
                    var dist = Parsing.DistributedQuery(ref expr);
                    Parsing.Eof(expr);
                    if (dist.IsDangerous() && safe)
                    {
                        throw new SecurityException("检测到弱检索式");
                    }

                    return(ExecuteList(dist, null, false, serializer));
                }),
                new ShellComponent(
                    "li",
                    (expr, serializer) =>
                {
                    var safe = Parsing.Token(ref expr, false, t => t == "unsafe") == null;
                    var dt   = Parsing.UniqueTime(ref expr) ?? ClientDateTime.Today;
                    var dist = Parsing.DistributedQuery(ref expr);
                    Parsing.Eof(expr);
                    if (dist.IsDangerous() && safe)
                    {
                        throw new SecurityException("检测到弱检索式");
                    }

                    return(ExecuteList(dist, dt, true, serializer));
                }),
                new ShellComponent(
                    "q",
                    (expr, serializer) =>
                {
                    var safe = Parsing.Token(ref expr, false, t => t == "unsafe") == null;
                    var dist = Parsing.DistributedQuery(ref expr);
                    Parsing.Eof(expr);
                    if (dist.IsDangerous() && safe)
                    {
                        throw new SecurityException("检测到弱检索式");
                    }

                    return(ExecuteQuery(dist, serializer));
                }),
                new ShellComponent(
                    "reg",
                    (expr, serializer) =>
                {
                    var dist     = Parsing.DistributedQuery(ref expr);
                    var rng      = Parsing.Range(ref expr) ?? DateFilter.Unconstrained;
                    var vouchers = Parsing.OptColVouchers(ref expr);
                    Parsing.Eof(expr);
                    return(ExecuteRegister(dist, rng, vouchers, serializer));
                }),
                new ShellComponent(
                    "unreg",
                    (expr, serializer) =>
                {
                    var dist     = Parsing.DistributedQuery(ref expr);
                    var rng      = Parsing.Range(ref expr) ?? DateFilter.Unconstrained;
                    var vouchers = Parsing.OptColVouchers(ref expr);
                    Parsing.Eof(expr);
                    return(ExecuteUnregister(dist, rng, vouchers, serializer));
                }),
                new ShellComponent(
                    "recal",
                    (expr, serializer) =>
                {
                    var dist = Parsing.DistributedQuery(ref expr);
                    Parsing.Eof(expr);
                    return(ExecuteRecal(dist, serializer));
                }),
                new ShellComponent("rst", (expr, serializer) => resetComopser.Execute(expr, serializer)),
                new ShellComponent(
                    "ap",
                    (expr, serializer) =>
                {
                    var collapse = Parsing.Optional(ref expr, "col");
                    var dist     = Parsing.DistributedQuery(ref expr);
                    var rng      = Parsing.Range(ref expr) ?? DateFilter.Unconstrained;
                    Parsing.Eof(expr);
                    return(ExecuteApply(dist, rng, collapse));
                }),
                new ShellComponent(
                    "chk",
                    (expr, serializer) =>
                {
                    var dist = Parsing.DistributedQuery(ref expr);
                    Parsing.Eof(expr);
                    return(ExecuteCheck(dist, new DateFilter(null, ClientDateTime.Today), serializer));
                }),
                new ShellComponent(
                    null,
                    (expr, serializer) =>
                {
                    var dt   = Parsing.UniqueTime(ref expr) ?? ClientDateTime.Today;
                    var dist = Parsing.DistributedQuery(ref expr);
                    Parsing.Eof(expr);
                    return(ExecuteList(dist, dt, false, serializer));
                })
            };
        }
        /// <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 #17
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());
    }