示例#1
0
        /// <inheritdoc />
        public override IQueryResult Execute(string expr, IEntitiesSerializer serializer)
        {
            FacadeF.ParsingF.Eof(expr);

            var result = Accountant.RunGroupedQuery("T1101+T611102+T1501+T611106 G``cd");
            var resx   = Accountant.RunGroupedQuery("T1101+T1501``c");
            var sb     = new StringBuilder();

            foreach (
                var(grp, rte) in
                result.Items.Cast <ISubtotalContent>()
                .Join(
                    resx.Items.Cast <ISubtotalContent>(),
                    grp => grp.Content,
                    rsx => rsx.Content,
                    (grp, bal) => (Group: grp,
                                   Rate: GetRate(
                                       grp.Items.Cast <ISubtotalDate>().OrderBy(b => b.Date, new DateComparer()).ToList(),
                                       bal.Fund)))
                .OrderByDescending(kvp => kvp.Rate))
            {
                sb.AppendLine($"{grp.Content.CPadRight(30)} {$"{rte * 360:P2}".PadLeft(7)}");
            }

            return(new PlainText(sb.ToString()));
        }
示例#2
0
        /// <inheritdoc />
        public override IQueryResult Execute(string expr, IEntitiesSerializer serializer)
        {
            Template temp = null;

            if (ParsingF.Token(ref expr, true, t => (temp = GetTemplate(t)) != null) == null)
            {
                throw new ArgumentException("找不到模板", nameof(expr));
            }

            var regex    = new Regex(@"^[A-Za-z]{3}$");
            var currency =
                Parsing.Token(ref expr, false, regex.IsMatch)?.ToUpperInvariant()
                ?? BaseCurrency.Now;

            DateFilter the;

            if (string.IsNullOrWhiteSpace(expr))
            {
                the = DateRange(temp.Day);
            }
            else
            {
                the = ParsingF.Range(ref expr) ?? throw new ArgumentException("语法错误", nameof(expr));
                ParsingF.Eof(expr);
            }

            return(DoInquiry(the, temp, out _, currency, serializer));
        }
示例#3
0
 public InquiriesVisitor(Accountant accountant, DateFilter rng, string baseCurrency, IEntitiesSerializer serializer)
 {
     m_Accountant   = accountant;
     m_BaseCurrency = baseCurrency;
     m_Serializer   = serializer;
     m_Rng          = rng;
 }
示例#4
0
        /// <summary>
        ///     执行检查表达式
        /// </summary>
        /// <param name="distQuery">分期检索式</param>
        /// <param name="rng">日期过滤器</param>
        /// <param name="serializer">表示器</param>
        /// <returns>执行结果</returns>
        protected override IQueryResult ExecuteCheck(IQueryCompunded <IDistributedQueryAtom> distQuery, DateFilter rng,
                                                     IEntitiesSerializer serializer)
        {
            var sb = new StringBuilder();

            foreach (var a in Sort(Accountant.SelectAssets(distQuery)))
            {
                var sbi = new StringBuilder();
                foreach (var item in Accountant.Update(a, rng, false, true))
                {
                    sbi.AppendLine(ListAssetItem(item));
                }

                if (sbi.Length != 0)
                {
                    sb.AppendLine(ListAsset(a, serializer, null, false));
                    sb.AppendLine(sbi.ToString());
                }

                Accountant.Upsert(a);
            }

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

            return(new PlainSucceed());
        }
示例#5
0
        /// <summary>
        ///     执行查询
        /// </summary>
        /// <param name="rng">日期过滤器</param>
        /// <param name="inq">查询</param>
        /// <param name="val">金额</param>
        /// <param name="baseCurrency"></param>
        /// <param name="serializer"></param>
        /// <returns>执行结果</returns>
        public IQueryResult DoInquiry(DateFilter rng, BaseInquiry inq, out double val, string baseCurrency,
                                      IEntitiesSerializer serializer)
        {
            var visitor = new InquiriesVisitor(Accountant, rng, baseCurrency, serializer);

            val = inq.Accept(visitor);
            return(new PlainText(visitor.Result));
        }
示例#6
0
        /// <inheritdoc />
        protected override IQueryResult ExecuteList(IQueryCompunded <IDistributedQueryAtom> distQuery, DateTime?dt,
                                                    bool showSchedule, IEntitiesSerializer serializer)
        {
            var sb = new StringBuilder();

            foreach (var a in Sort(Accountant.SelectAssets(distQuery)))
            {
                sb.Append(ListAsset(a, serializer, dt, showSchedule));
            }

            return(new PlainText(sb.ToString()));
        }
 /// <inheritdoc />
 public string PresentSubtotal(ISubtotalResult raw, ISubtotal par, IEntitiesSerializer serializer)
 {
     m_Par      = par;
     Ga         = par.GatherType;
     Cu         = par.EquivalentCurrency;
     Serializer = serializer;
     Sb         = new StringBuilder();
     Depth      = 0;
     Pre();
     raw?.Accept(this);
     Post();
     return(Sb.ToString());
 }
示例#8
0
        /// <inheritdoc />
        public override IQueryResult Execute(string expr, IEntitiesSerializer serializer)
        {
            var rst = new Dictionary <DateTime, double[]>();

            var n = Templates.Config.Accounts.Count;

            for (var i = 0; i < n; i++)
            {
                foreach (var(date, value) in GetItems(Templates.Config.Accounts[i], serializer))
                {
                    if (!rst.ContainsKey(date))
                    {
                        rst.Add(date, new double[n]);
                    }

                    rst[date][i] += value;
                }
            }

            var aggs = new double[n];

            var sb = new StringBuilder();

            sb.Append("Date    ");
            for (var i = 0; i < n; i++)
            {
                sb.Append($" {Templates.Config.Accounts[i].Currency.PadRight(15)} Sum            ");
            }

            sb.AppendLine(" All");

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

                var sum = 0D;
                for (var i = 0; i < n; i++)
                {
                    aggs[i] += kvp.Value[i];
                    sum     += aggs[i] * ExchangeFactory.Instance.From(
                        kvp.Key,
                        Templates.Config.Accounts[i].Currency);
                    sb.Append(kvp.Value[i].AsCurrency(Templates.Config.Accounts[i].Currency).PadLeft(15));
                    sb.Append(aggs[i].AsCurrency(Templates.Config.Accounts[i].Currency).PadLeft(15));
                }

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

            return(new PlainText(sb.ToString()));
        }
示例#9
0
        /// <inheritdoc />
        protected override IQueryResult ExecuteRecal(IQueryCompunded <IDistributedQueryAtom> distQuery,
                                                     IEntitiesSerializer serializer)
        {
            var lst = new List <Asset>();

            foreach (var a in Sort(Accountant.SelectAssets(distQuery)))
            {
                Accountant.Depreciate(a);
                Accountant.Upsert(a);
                lst.Add(a);
            }

            return(new DirtyText(serializer.PresentAssets(lst)));
        }
示例#10
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")));
        }
示例#11
0
        /// <inheritdoc />
        public override IQueryResult Execute(string expr, IEntitiesSerializer serializer)
        {
            var count = 0;

            while (!string.IsNullOrWhiteSpace(expr))
            {
                var voucher = GenerateVoucher(ref expr);
                if (voucher == null)
                {
                    continue;
                }

                if (Accountant.Upsert(voucher))
                {
                    count++;
                }
            }

            return(new NumberAffected(count));
        }
 /// <inheritdoc />
 public async IAsyncEnumerable <string> PresentSubtotal(ISubtotalResult raw, ISubtotal par,
                                                        IEntitiesSerializer serializer)
 {
     m_Par      = par;
     Ga         = par.GatherType;
     Cu         = par.EquivalentCurrency;
     Serializer = serializer;
     Depth      = 0;
     await foreach (var s in Pre())
     {
         yield return(s);
     }
     if (raw != null)
     {
         await foreach (var s in raw.Accept(this))
         {
             yield return(s);
         }
     }
     await foreach (var s in Post())
     {
         yield return(s);
     }
 }
示例#13
0
        /// <inheritdoc />
        protected override IQueryResult ExecuteUnregister(IQueryCompunded <IDistributedQueryAtom> distQuery,
                                                          DateFilter rng,
                                                          IQueryCompunded <IVoucherQueryAtom> query, IEntitiesSerializer serializer)
        {
            var sb = new StringBuilder();

            foreach (var a in Sort(Accountant.SelectAssets(distQuery)))
            {
                foreach (var item in a.Schedule.Where(item => item.Date.Within(rng)))
                {
                    if (query != null)
                    {
                        if (item.VoucherID == null)
                        {
                            continue;
                        }

                        var voucher = Accountant.SelectVoucher(item.VoucherID);
                        if (voucher != null)
                        {
                            if (!MatchHelper.IsMatch(query, voucher.IsMatch))
                            {
                                continue;
                            }
                        }
                    }

                    item.VoucherID = null;
                }

                sb.Append(ListAsset(a, serializer));
                Accountant.Upsert(a);
            }

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

            return(new PlainSucceed());
        }
示例#14
0
        /// <inheritdoc />
        protected override IQueryResult ExecuteRegister(IQueryCompunded <IDistributedQueryAtom> distQuery,
                                                        DateFilter rng,
                                                        IQueryCompunded <IVoucherQueryAtom> query, IEntitiesSerializer serializer)
        {
            var sb = new StringBuilder();

            foreach (var a in Sort(Accountant.SelectAssets(distQuery)))
            {
                sb.Append(serializer.PresentVouchers(Accountant.RegisterVouchers(a, rng, query)));
                Accountant.Upsert(a);
            }

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

            return(new PlainSucceed());
        }
示例#15
0
 /// <inheritdoc />
 protected override IQueryResult ExecuteQuery(IQueryCompunded <IDistributedQueryAtom> distQuery,
                                              IEntitiesSerializer serializer)
 => new PlainText(serializer.PresentAssets(Sort(Accountant.SelectAssets(distQuery))));
 /// <summary>
 ///     执行检查表达式
 /// </summary>
 /// <param name="distQuery">分期检索式</param>
 /// <param name="rng">日期过滤器</param>
 /// <param name="serializer">表示器</param>
 /// <returns>执行结果</returns>
 protected abstract IQueryResult ExecuteCheck(IQueryCompunded <IDistributedQueryAtom> distQuery, DateFilter rng,
                                              IEntitiesSerializer serializer);
 /// <inheritdoc />
 public IAsyncEnumerable <string> PresentSubtotal(ISubtotalResult raw, ISubtotal par, IEntitiesSerializer serializer)
 {
     m_Par   = par;
     m_Depth = 0;
     return(AsyncEnumerable.Repeat((raw?.Accept(this)?.Value as JObject)?.ToString(), 1));
 }
示例#18
0
 /// <inheritdoc />
 public IQueryResult Execute(string expr, IEntitiesSerializer serializer)
 => m_Action(m_Initial == null ? expr : expr.Rest(), serializer);
示例#19
0
        /// <inheritdoc />
        public override IQueryResult Execute(string expr, IEntitiesSerializer serializer)
        {
            var csv = expr;

            expr = ParsingF.Line(ref csv);
            var parsed = new CsvParser(ParsingF.Optional(ref expr, "-"));

            var sb = new StringBuilder();

            if (ParsingF.Optional(ref expr, "mark"))
            {
                var filt = Regularize(ParsingF.DetailQuery(ref expr));
                ParsingF.Optional(ref expr, "as");
                var marker = ParsingF.Token(ref expr);
                ParsingF.Eof(expr);
                if (string.IsNullOrWhiteSpace(marker))
                {
                    throw new FormatException("格式错误");
                }

                parsed.Parse(csv);
                sb.AppendLine($"{parsed.Items.Count} parsed");
                RunMark(filt, parsed, marker, sb);
            }
            else if (ParsingF.Optional(ref expr, "unmark"))
            {
                var filt = Regularize(ParsingF.DetailQuery(ref expr));
                ParsingF.Eof(expr);
                RunUnmark(filt, sb);
            }
            else if (ParsingF.Optional(ref expr, "check"))
            {
                var filt = Regularize(ParsingF.DetailQuery(ref expr));
                ParsingF.Eof(expr);
                parsed.Parse(csv);
                sb.AppendLine($"{parsed.Items.Count} parsed");
                RunCheck(filt, parsed, sb);
            }
            else
            {
                ParsingF.Optional(ref expr, "auto");
                var filt = Regularize(ParsingF.DetailQuery(ref expr));
                ParsingF.Optional(ref expr, "as");
                var marker = ParsingF.Token(ref expr);
                ParsingF.Eof(expr);
                if (string.IsNullOrWhiteSpace(marker))
                {
                    throw new FormatException("格式错误");
                }

                parsed.Parse(csv);
                sb.AppendLine($"{parsed.Items.Count} parsed");
                var markerFilt = new StmtVoucherDetailQuery(
                    filt.VoucherQuery,
                    new IntersectQueries <IDetailQueryAtom>(
                        filt.DetailEmitFilter.DetailFilter,
                        new StmtDetailQuery(marker)));
                var nullFilt = new StmtVoucherDetailQuery(
                    filt.VoucherQuery,
                    new IntersectQueries <IDetailQueryAtom>(
                        filt.DetailEmitFilter.DetailFilter,
                        new StmtDetailQuery("")));
                var nmFilt = new StmtVoucherDetailQuery(
                    filt.VoucherQuery,
                    new IntersectQueries <IDetailQueryAtom>(
                        filt.DetailEmitFilter.DetailFilter,
                        new UnionQueries <IDetailQueryAtom>(
                            new StmtDetailQuery(""),
                            new StmtDetailQuery(marker))));
                RunUnmark(markerFilt, sb);
                RunMark(nullFilt, parsed, marker, sb);
                RunCheck(nmFilt, parsed, sb);
            }

            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()));
        }
示例#21
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();
        }
示例#22
0
 /// <inheritdoc />
 public string PresentSubtotal(ISubtotalResult raw, ISubtotal par, IEntitiesSerializer serializer)
 {
     m_Par   = par;
     m_Depth = 0;
     return((raw?.Accept(this)?.Value as JObject)?.ToString());
 }
示例#23
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());
        }
        /// <inheritdoc />
        public override IQueryResult Execute(string expr, IEntitiesSerializer serializer)
        {
            var content = Parsing.Token(ref expr);

            return(ParsingF.Optional(ref expr, "q") ? Query(content, ref expr) : Create(content, ref expr, serializer));
        }
        private IQueryResult Create(string content, ref string expr, IEntitiesSerializer serializer)
        {
            var currency     = Parsing.Token(ref expr, false);
            var baseCurrency = Parsing.Token(ref expr, false);

            var lst = new List <Voucher>();

            while (!string.IsNullOrWhiteSpace(expr))
            {
                var date = Parsing.UniqueTime(ref expr);
                if (!date.HasValue)
                {
                    var dayF = ParsingF.DoubleF(ref expr);
                    var day  = (int)dayF;
                    // ReSharper disable once CompareOfFloatsByEqualityOperator
                    if (day != dayF)
                    {
                        throw new ApplicationException("非整数日期");
                    }

                    date = ClientDateTime.Today.Day < day
                        ? ClientDateTime.Today.AddMonths(-1).AddDays(day - ClientDateTime.Today.Day)
                        : ClientDateTime.Today.AddDays(day - ClientDateTime.Today.Day);
                }

                var from    = ParsingF.DoubleF(ref expr);
                var to      = ParsingF.DoubleF(ref expr);
                var voucher = new Voucher
                {
                    Date    = date.Value,
                    Details = new List <VoucherDetail>
                    {
                        new VoucherDetail
                        {
                            Currency = baseCurrency,
                            Title    = 2241,
                            SubTitle = 01,
                            Content  = content,
                            Fund     = -to
                        },
                        new VoucherDetail
                        {
                            Currency = baseCurrency,
                            Title    = 3999,
                            Fund     = to
                        },
                        new VoucherDetail
                        {
                            Currency = currency,
                            Title    = 3999,
                            Fund     = -from
                        },
                        from >= 0
                                    ? new VoucherDetail
                        {
                            Currency = currency,
                            Title    = 2241,
                            SubTitle = 01,
                            Content  = content,
                            Fund     = from
                        }
                                    : new VoucherDetail
                        {
                            Currency = currency,
                            Title    = 6603,
                            Fund     = from
                        }
                    }
                };
                Accountant.Upsert(voucher);
                lst.Add(voucher);
            }

            if (lst.Any())
            {
                return(new DirtyText(serializer.PresentVouchers(lst)));
            }

            return(new PlainSucceed());
        }
示例#26
0
        private IEnumerable <(DateTime Date, double Value)> GetItems(CashAccount account, IEntitiesSerializer serializer, DateTime until)
        {
            var user = $"U{account.User.AsUser()}";
            var curr = $"@{account.Currency}";

            if (account.Reimburse != null)
            {
                var rb  = new Composite.Composite(Accountant);
                var tmp = Composite.Composite.GetTemplate(account.Reimburse);
                var rng = Composite.Composite.DateRange(tmp.Day);
                rb.DoInquiry(rng, tmp, out var rbVal, BaseCurrency.Now, serializer);
                // ReSharper disable once PossibleInvalidOperationException
                var rbF = rng.EndDate.Value;
                yield return(rbF, rbVal);
            }

            foreach (var debt in account.Items)
            {
                switch (debt)
                {
                case OnceItem oi:
                    yield return(oi.Date, oi.Fund);

                    break;

                case OnceQueryItem oqi:
                    yield return(oqi.Date, Accountant.RunGroupedQuery($"{user} {curr}*({oqi.Query})``v").Fund);

                    break;

                case MonthlyItem mn:
                    for (var d = NextDate(mn.Day); d <= until; d = NextDate(mn.Day, d))
                    {
                        if (mn.Since != default(DateTime) && d < mn.Since)
                        {
                            continue;
                        }
                        if (mn.Till != default(DateTime) && d > mn.Till)
                        {
                            continue;
                        }

                        yield return(d, mn.Fund);
                    }

                    break;

                case SimpleCreditCard cc:
                    var rng = $"[{ClientDateTime.Today.AddMonths(-3).AsDate()}~]";
                    var mv  = $"{{({user}*{cc.Query})+{user} T3999+{user} T6603 A {rng}}}";
                    var mos = new Dictionary <DateTime, double>();
                    foreach (var grpC in Accountant.RunGroupedQuery($"{{{user}*({cc.Query})*({user} <+(-{user} {curr})) {rng}}}+{mv}:{user}*({cc.Query})`Cd")
                             .Items
                             .Cast <ISubtotalCurrency>())
                    {
                        foreach (var b in grpC.Items.Cast <ISubtotalDate>())
                        {
                            var mo  = NextDate(cc.RepaymentDay, NextDate(cc.BillDay, b.Date.Value), true);
                            var cob = Accountant.From(mo, grpC.Currency)
                                      * Accountant.To(mo, account.Currency)
                                      * b.Fund;
                            if (mos.ContainsKey(mo))
                            {
                                mos[mo] += cob;
                            }
                            else
                            {
                                mos[mo] = cob;
                            }
                        }
                    }

                    foreach (var b in Accountant.RunGroupedQuery($"{{{user}*({cc.Query})*({user} {curr}>) {rng}}}-{mv}:{user}*({cc.Query})`d")
                             .Items
                             .Cast <ISubtotalDate>())
                    {
                        var mo = NextDate(cc.RepaymentDay, b.Date.Value, true);
                        if (mos.ContainsKey(mo))
                        {
                            mos[mo] += b.Fund;
                        }
                        else
                        {
                            mos[mo] = b.Fund;
                        }
                    }

                    for (var d = ClientDateTime.Today; d <= until; d = NextDate(cc.BillDay, d))
                    {
                        var mo  = NextDate(cc.RepaymentDay, NextDate(cc.BillDay, d), true);
                        var cob = -(NextDate(cc.BillDay, d) - d).TotalDays * cc.MonthlyFee / (365.2425 / 12);
                        if (mos.ContainsKey(mo))
                        {
                            mos[mo] += cob;
                        }
                        else
                        {
                            mos[mo] = cob;
                        }
                    }

                    foreach (var kvp in mos)
                    {
                        yield return(kvp.Key, kvp.Value);
                    }

                    break;

                case ComplexCreditCard cc:
                    var stmt = -Accountant.RunGroupedQuery($"({cc.Query})*({user} {curr})-{user} \"\"``v").Fund;
                    var pmt  = Accountant.RunGroupedQuery($"({cc.Query})*({user} {curr} \"\" >)``v").Fund;
                    var nxt  = -Accountant.RunGroupedQuery($"({cc.Query})*({user} {curr} \"\" <)``v").Fund;
                    if (pmt < stmt)
                    {
                        if (NextDate(cc.BillDay, NextDate(cc.RepaymentDay)) == NextDate(cc.BillDay))
                        {
                            yield return(NextDate(cc.RepaymentDay), pmt - stmt);
                        }
                        else
                        {
                            nxt += stmt - pmt;     // Not paid in full
                        }
                    }
                    else
                    {
                        nxt -= pmt - stmt;     // Paid too much
                    }
                    for (var d = ClientDateTime.Today; d <= until; d = NextDate(cc.BillDay, d))
                    {
                        nxt += (NextDate(cc.BillDay, d) - d).TotalDays * cc.MonthlyFee / (365.2425 / 12);
                        if (cc.MaximumUtility >= 0 && cc.MaximumUtility < nxt)
                        {
                            yield return(NextDate(cc.BillDay, d), cc.MaximumUtility - nxt);

                            nxt = cc.MaximumUtility;
                        }

                        yield return(NextDate(cc.RepaymentDay, d).AddMonths(1), -nxt);

                        nxt = 0;
                    }

                    break;

                default:
                    throw new InvalidOperationException();
                }
            }
        }
示例#27
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()));
        }
示例#28
0
 /// <inheritdoc />
 public IQueryResult Execute(string expr, IEntitiesSerializer serializer)
 => FirstExecutable(expr).Execute(expr, 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()));
        }
示例#30
0
        private IEnumerable <(DateTime Date, double Value)> GetItems(CashAccount account, IEntitiesSerializer serializer)
        {
            var curr = $"@{account.Currency}";
            var init = Accountant.RunGroupedQuery($"{curr}*({account.QuickAsset}) [~.]``v").Fund;

            yield return(ClientDateTime.Today, init);

            if (account.Reimburse != null)
            {
                var rb  = new Composite.Composite(Accountant);
                var tmp = Composite.Composite.GetTemplate(account.Reimburse);
                var rng = Composite.Composite.DateRange(tmp.Day);
                rb.DoInquiry(rng, tmp, out var rbVal, BaseCurrency.Now, serializer);
                // ReSharper disable once PossibleInvalidOperationException
                var rbF = rng.EndDate.Value;
                yield return(rbF, rbVal);
            }

            foreach (var debt in account.Items)
            {
                switch (debt)
                {
                case FixedItem fi:
                    yield return(fi.Day, fi.Fund);

                    break;

                case SimpleItem sd:
                    yield return(sd.Day, Accountant.RunGroupedQuery($"{curr}*({sd.Query})``v").Fund);

                    break;

                case CreditCard cd:
                    foreach (var grpC in Accountant.RunGroupedQuery(
                                 $"{{{{({cd.Query})*(<+(-{curr}))}}+{{({cd.Query})+T3999+T6603 A}}}}*{{[{ClientDateTime.Today.AddMonths(-3).AsDate()}~]}}:{cd.Query}`Cd")
                             .Items
                             .Cast <ISubtotalCurrency>())
                    {
                        foreach (var b in grpC.Items.Cast <ISubtotalDate>())
                        {
                            // ReSharper disable once PossibleInvalidOperationException
                            var d  = b.Date.Value;
                            var mo = new DateTime(d.Year, d.Month, 1, 0, 0, 0, DateTimeKind.Utc);
                            if (d.Day >= cd.BillDay)
                            {
                                mo = mo.AddMonths(1);
                            }
                            if (cd.RepaymentDay <= cd.BillDay)
                            {
                                mo = mo.AddMonths(1);
                            }
                            mo = mo.AddDays(cd.RepaymentDay - 1);
                            if (mo <= ClientDateTime.Today)
                            {
                                continue;
                            }

                            var cob = ExchangeFactory.Instance.From(mo, grpC.Currency)
                                      * ExchangeFactory.Instance.To(mo, account.Currency)
                                      * b.Fund;
                            yield return(mo, cob);
                        }
                    }

                    foreach (var b in Accountant.RunGroupedQuery(
                                 $"{{({cd.Query})*({curr}>) [{ClientDateTime.Today.AddMonths(-3).AsDate()}~]}}-{{({cd.Query})+T3999+T6603 A}}:{cd.Query}`d")
                             .Items
                             .Cast <ISubtotalDate>())
                    {
                        // ReSharper disable once PossibleInvalidOperationException
                        var d  = b.Date.Value;
                        var mo = new DateTime(d.Year, d.Month, 1, 0, 0, 0, DateTimeKind.Utc);
                        if (d.Day > cd.RepaymentDay)
                        {
                            mo = mo.AddMonths(1);
                        }
                        mo = mo.AddDays(cd.RepaymentDay - 1);
                        if (mo <= ClientDateTime.Today)
                        {
                            continue;
                        }

                        yield return(mo, b.Fund);
                    }

                    break;

                default:
                    throw new InvalidOperationException();
                }
            }
        }