/// <summary> /// 解析记账凭证表达式 /// </summary> /// <param name="expr">表达式</param> /// <returns>记账凭证</returns> private Voucher GetVoucher(ref string expr) { Parsing.TrimStartComment(ref expr); var id = Parsing.Quoted(ref expr, '^'); Parsing.TrimStartComment(ref expr); DateTime? date = ClientDateTime.Today; try { date = ParsingF.UniqueTime(ref expr); } catch (Exception) { // ignore } Parsing.TrimStartComment(ref expr); var remark = Parsing.Quoted(ref expr, '%'); Parsing.TrimStartComment(ref expr); var typeT = VoucherType.Ordinary; var type = Parsing.Token(ref expr, false, t => TryParse(t, out typeT)) != null ? (VoucherType?)typeT : null; Parsing.TrimStartComment(ref expr); var lst = new List<VoucherDetail>(); VoucherDetail d; while ((d = ParseVoucherDetail(ref expr)) != null) lst.Add(d); return new Voucher { ID = id, Remark = remark, Type = type, Date = date, Details = lst }; }
/// <summary> /// 解析记账凭证表达式 /// </summary> /// <param name="expr">表达式</param> /// <returns>记账凭证</returns> private Voucher GetVoucher(ref string expr) { Parsing.TrimStartComment(ref expr); DateTime?date = ClientDateTime.Today; try { date = ParsingF.UniqueTime(ref expr); } catch (Exception) { // ignore } var currency = Parsing.Token(ref expr, false, s => s.StartsWith("@", StringComparison.Ordinal)) ?.Substring(1) .ToUpperInvariant() ?? BaseCurrency.Now; var lst = new List <Item>(); List <Item> ds; while ((ds = ParseItem(currency, ref expr))?.Any() == true) { lst.AddRange(ds); } var d = (double?)0D; var t = (double?)0D; var reg = new Regex(@"(?<dt>[dt])(?<num>[0-9]+(?:\.[0-9]{1,2})?|null)"); while (true) { var res = Parsing.Token(ref expr, false, reg.IsMatch); if (res == null) { break; } var m = reg.Match(res); var num = m.Groups["num"].Value == "null" ? (double?)null : Convert.ToDouble(m.Groups["num"].Value); if (m.Groups["dt"].Value == "d") { d += num; } else // if (m.Groups["dt"].Value == "t") { t += num; } } if (!d.HasValue && !t.HasValue) { throw new ApplicationException("不定项过多"); } var resLst = new List <VoucherDetail>(); VoucherDetail vd; var exprS = new AbbrSerializer(); while ((vd = exprS.ParseVoucherDetail(ref expr)) != null) { resLst.Add(vd); } // Don't use Enumerable.Sum, it ignores null values var actualVals = resLst.Aggregate((double?)0D, (s, dd) => s + dd.Fund); if (!d.HasValue || !t.HasValue) { if (!actualVals.HasValue) { throw new ApplicationException("不定项过多"); } var sum = lst.Sum(item => item.Fund - item.DiscountFund); if (!d.HasValue) { d = sum + t + actualVals; } else // if (!t.HasValue) { t = -(sum - d + actualVals); } } // ReSharper disable PossibleInvalidOperationException var total = lst.Sum(it => it.Fund.Value); foreach (var item in lst) { item.DiscountFund += d.Value / total * item.Fund.Value; item.Fund += t.Value / total * item.Fund; } // ReSharper restore PossibleInvalidOperationException foreach (var item in lst) { if (!item.UseActualFund) { continue; } item.Fund -= item.DiscountFund; item.DiscountFund = 0D; } var totalD = lst.Sum(it => it.DiscountFund); foreach (var grp in lst.GroupBy( it => new VoucherDetail { Currency = it.Currency, Title = it.Title, SubTitle = it.SubTitle, Content = it.Content, Remark = it.Remark }, new DetailEqualityComparer())) { // ReSharper disable once PossibleInvalidOperationException grp.Key.Fund = grp.Sum(it => it.Fund.Value); resLst.Add(grp.Key); } if (!totalD.IsZero()) { resLst.Add( new VoucherDetail { Currency = currency, Title = 6603, Fund = -totalD }); } return(new Voucher { Type = VoucherType.Ordinary, Date = date, Details = resLst }); }