예제 #1
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()));
        }
예제 #2
0
        private void RunMark(IVoucherDetailQuery filt, CsvParser parsed, string marker, StringBuilder sb)
        {
            if (filt.IsDangerous())
            {
                throw new SecurityException("检测到弱检索式");
            }

            var marked    = 0;
            var remarked  = 0;
            var converted = 0;
            var res       = Accountant.SelectVouchers(filt.VoucherQuery).ToList();

            foreach (var b in parsed.Items)
            {
                bool Trial(bool date)
                {
                    var resx = date
                        ? res.Where(v => v.Date == b.Date)
                        : res.OrderBy(v => v.Date.HasValue
                            ? Math.Abs((v.Date.Value - b.Date).TotalDays)
                            : double.PositiveInfinity);
                    var voucher = resx
                                  .FirstOrDefault(v => v.Details.Any(d
                                                                     // ReSharper disable once PossibleInvalidOperationException
                                                                     => (d.Fund.Value - b.Fund).IsZero() && d.IsMatch(filt.DetailEmitFilter.DetailFilter)));

                    if (voucher == null)
                    {
                        return(false);
                    }

                    var o = voucher.Details.First(d
                                                  // ReSharper disable once PossibleInvalidOperationException
                                                  => (d.Fund.Value - b.Fund).IsZero() && d.IsMatch(filt.DetailEmitFilter.DetailFilter));

                    if (o.Remark == null)
                    {
                        marked++;
                    }
                    else if (o.Remark == marker)
                    {
                        remarked++;
                    }
                    else
                    {
                        converted++;
                    }

                    o.Remark = marker;
                    Accountant.Upsert(voucher);
                    return(true);
                }

                if (Trial(true) || Trial(false))
                {
                    continue;
                }

                sb.AppendLine(b.Raw);
            }

            sb.AppendLine($"{marked} marked");
            sb.AppendLine($"{remarked} remarked");
            sb.AppendLine($"{converted} converted");
        }