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