/// <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)); }
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, }; }
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())); }
/// <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))
/// <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()); }