• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

b1f6c1c4 / ProfessionalAccounting / 297

19 Feb 2023 04:15AM UTC coverage: 36.498% (+0.5%) from 35.998%
297

push

appveyor

b1f6c1c4
fix coupling bug

9985 of 27358 relevant lines covered (36.5%)

716.47 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

6.82
/AccountingServer.Shell/DistributedShell.cs
1
/* Copyright (C) 2020-2023 b1f6c1c4
2
 *
3
 * This file is part of ProfessionalAccounting.
4
 *
5
 * ProfessionalAccounting is free software: you can redistribute it and/or
6
 * modify it under the terms of the GNU Affero General Public License as
7
 * published by the Free Software Foundation, version 3.
8
 *
9
 * ProfessionalAccounting is distributed in the hope that it will be useful, but
10
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License
12
 * for more details.
13
 *
14
 * You should have received a copy of the GNU Affero General Public License
15
 * along with ProfessionalAccounting.  If not, see
16
 * <https://www.gnu.org/licenses/>.
17
 */
18

19
using System;
20
using System.Collections.Generic;
21
using System.Security;
22
using AccountingServer.Entities;
23
using AccountingServer.Entities.Util;
24
using AccountingServer.Shell.Util;
25
using static AccountingServer.BLL.Parsing.Facade;
26

27
namespace AccountingServer.Shell;
28

29
/// <summary>
30
///     分期表达式解释器
31
/// </summary>
32
internal abstract class DistributedShell : IShellComponent
33
{
34
    /// <summary>
35
    ///     复合表达式解释器
36
    /// </summary>
37
    private readonly IShellComponent m_Composer;
38

39
    protected DistributedShell()
20✔
40
    {
20✔
41
        var resetComposer =
20✔
42
            new ShellComposer
43
                {
44
                    new ShellComponent(
45
                        "soft",
46
                        (expr, session) =>
47
                            {
×
48
                                var dist = Parsing.DistributedQuery(ref expr, session.Client);
×
49
                                var rng = Parsing.Range(ref expr, session.Client) ?? DateFilter.Unconstrained;
×
50
                                Parsing.Eof(expr);
×
51
                                return ExecuteResetSoft(dist, rng, session);
×
52
                            }),
×
53
                    new ShellComponent(
54
                        "mixed",
55
                        (expr, session) =>
56
                            {
×
57
                                var dist = Parsing.DistributedQuery(ref expr, session.Client);
×
58
                                var rng = Parsing.Range(ref expr, session.Client) ?? DateFilter.Unconstrained;
×
59
                                Parsing.Eof(expr);
×
60
                                return ExecuteResetMixed(dist, rng, session);
×
61
                            }),
×
62
                    new ShellComponent(
63
                        "hard",
64
                        (expr, session) =>
65
                            {
×
66
                                var dist = Parsing.DistributedQuery(ref expr, session.Client);
×
67
                                var vouchers = Parsing.OptColVouchers(ref expr, session.Client);
×
68
                                Parsing.Eof(expr);
×
69
                                return ExecuteResetHard(dist, vouchers, session);
×
70
                            }),
×
71
                };
72
        m_Composer =
20✔
73
            new ShellComposer
74
                {
75
                    new ShellComponent(
76
                        "all",
77
                        (expr, session) =>
78
                            {
×
79
                                var safe = Parsing.Token(ref expr, false, static t => t == "unsafe") == null;
×
80
                                var dist = Parsing.DistributedQuery(ref expr, session.Client);
×
81
                                Parsing.Eof(expr);
×
82
                                if (dist.IsDangerous() && safe)
×
83
                                    throw new SecurityException("检测到弱检索式");
×
84

85
                                return ExecuteList(dist, null, false, session);
×
86
                            }),
×
87
                    new ShellComponent(
88
                        "li",
89
                        (expr, session) =>
90
                            {
×
91
                                var safe = Parsing.Token(ref expr, false, static t => t == "unsafe") == null;
×
92
                                var dt = Parsing.UniqueTime(ref expr, session.Client) ?? session.Client.Today;
×
93
                                var dist = Parsing.DistributedQuery(ref expr, session.Client);
×
94
                                Parsing.Eof(expr);
×
95
                                if (dist.IsDangerous() && safe)
×
96
                                    throw new SecurityException("检测到弱检索式");
×
97

98
                                return ExecuteList(dist, dt, true, session);
×
99
                            }),
×
100
                    new ShellComponent(
101
                        "q",
102
                        (expr, session) =>
103
                            {
×
104
                                var safe = Parsing.Token(ref expr, false, static t => t == "unsafe") == null;
×
105
                                var dist = Parsing.DistributedQuery(ref expr, session.Client);
×
106
                                Parsing.Eof(expr);
×
107
                                if (dist.IsDangerous() && safe)
×
108
                                    throw new SecurityException("检测到弱检索式");
×
109

110
                                return ExecuteQuery(dist, session);
×
111
                            }),
×
112
                    new ShellComponent(
113
                        "reg",
114
                        (expr, session) =>
115
                            {
×
116
                                var dist = Parsing.DistributedQuery(ref expr, session.Client);
×
117
                                var rng = Parsing.Range(ref expr, session.Client) ?? DateFilter.Unconstrained;
×
118
                                var vouchers = Parsing.OptColVouchers(ref expr, session.Client);
×
119
                                Parsing.Eof(expr);
×
120
                                return ExecuteRegister(dist, rng, vouchers, session);
×
121
                            }),
×
122
                    new ShellComponent(
123
                        "unreg",
124
                        (expr, session) =>
125
                            {
×
126
                                var dist = Parsing.DistributedQuery(ref expr, session.Client);
×
127
                                var rng = Parsing.Range(ref expr, session.Client) ?? DateFilter.Unconstrained;
×
128
                                var vouchers = Parsing.OptColVouchers(ref expr, session.Client);
×
129
                                Parsing.Eof(expr);
×
130
                                return ExecuteUnregister(dist, rng, vouchers, session);
×
131
                            }),
×
132
                    new ShellComponent(
133
                        "recal",
134
                        (expr, session) =>
135
                            {
×
136
                                var dist = Parsing.DistributedQuery(ref expr, session.Client);
×
137
                                Parsing.Eof(expr);
×
138
                                return ExecuteRecal(dist, session);
×
139
                            }),
×
140
                    new ShellComponent("rst", (expr, session) => resetComposer.Execute(expr, session)),
×
141
                    new ShellComponent(
142
                        "ap",
143
                        (expr, session) =>
144
                            {
×
145
                                var collapse = Parsing.Optional(ref expr, "col");
×
146
                                var dist = Parsing.DistributedQuery(ref expr, session.Client);
×
147
                                var rng = Parsing.Range(ref expr, session.Client) ?? DateFilter.Unconstrained;
×
148
                                Parsing.Eof(expr);
×
149
                                return ExecuteApply(dist, rng, collapse, session);
×
150
                            }),
×
151
                    new ShellComponent(
152
                        "chk",
153
                        (expr, session) =>
154
                            {
×
155
                                var dist = Parsing.DistributedQuery(ref expr, session.Client);
×
156
                                Parsing.Eof(expr);
×
157
                                return ExecuteCheck(dist, new(null, session.Client.Today), session);
×
158
                            }),
×
159
                    new ShellComponent(
160
                        null,
161
                        (expr, session) =>
162
                            {
×
163
                                var dt = Parsing.UniqueTime(ref expr, session.Client) ?? session.Client.Today;
×
164
                                var dist = Parsing.DistributedQuery(ref expr, session.Client);
×
165
                                Parsing.Eof(expr);
×
166
                                return ExecuteList(dist, dt, false, session);
×
167
                            }),
×
168
                };
169
    }
20✔
170

171
    /// <summary>
172
    ///     首字母
173
    /// </summary>
174
    protected abstract string Initial { get; }
175

176
    /// <inheritdoc />
177
    public IAsyncEnumerable<string> Execute(string expr, Session session)
178
        => m_Composer.Execute(expr.Rest(), session);
×
179

180
    /// <inheritdoc />
181
    public bool IsExecutable(string expr) => expr.Initial() == Initial;
12✔
182

183
    /// <summary>
184
    ///     执行列表表达式
185
    /// </summary>
186
    /// <param name="distQuery">分期检索式</param>
187
    /// <param name="dt">计算账面价值的时间</param>
188
    /// <param name="showSchedule">是否显示折旧计算表</param>
189
    /// <param name="session">客户端会话</param>
190
    /// <returns>执行结果</returns>
191
    protected abstract IAsyncEnumerable<string> ExecuteList(IQueryCompounded<IDistributedQueryAtom> distQuery,
192
        DateTime? dt, bool showSchedule, Session session);
193

194
    /// <summary>
195
    ///     执行查询表达式
196
    /// </summary>
197
    /// <param name="distQuery">分期检索式</param>
198
    /// <param name="session">客户端会话</param>
199
    /// <returns>执行结果</returns>
200
    protected abstract IAsyncEnumerable<string> ExecuteQuery(IQueryCompounded<IDistributedQueryAtom> distQuery,
201
        Session session);
202

203
    /// <summary>
204
    ///     执行注册表达式
205
    /// </summary>
206
    /// <param name="distQuery">分期检索式</param>
207
    /// <param name="rng">日期过滤器</param>
208
    /// <param name="query">记账凭证检索式</param>
209
    /// <param name="session">客户端会话</param>
210
    /// <returns>执行结果</returns>
211
    protected abstract IAsyncEnumerable<string> ExecuteRegister(IQueryCompounded<IDistributedQueryAtom> distQuery,
212
        DateFilter rng, IQueryCompounded<IVoucherQueryAtom> query, Session session);
213

214
    /// <summary>
215
    ///     执行解除注册表达式
216
    /// </summary>
217
    /// <param name="distQuery">分期检索式</param>
218
    /// <param name="rng">日期过滤器</param>
219
    /// <param name="query">记账凭证检索式</param>
220
    /// <param name="session">客户端会话</param>
221
    /// <returns>执行结果</returns>
222
    protected abstract IAsyncEnumerable<string> ExecuteUnregister(IQueryCompounded<IDistributedQueryAtom> distQuery,
223
        DateFilter rng, IQueryCompounded<IVoucherQueryAtom> query, Session session);
224

225
    /// <summary>
226
    ///     执行重新计算表达式
227
    /// </summary>
228
    /// <param name="distQuery">分期检索式</param>
229
    /// <param name="session">客户端会话</param>
230
    /// <returns>执行结果</returns>
231
    protected abstract IAsyncEnumerable<string> ExecuteRecal(IQueryCompounded<IDistributedQueryAtom> distQuery,
232
        Session session);
233

234
    /// <summary>
235
    ///     执行软重置表达式
236
    /// </summary>
237
    /// <param name="distQuery">分期检索式</param>
238
    /// <param name="rng">日期过滤器</param>
239
    /// <param name="session">客户端会话</param>
240
    /// <returns>执行结果</returns>
241
    protected abstract IAsyncEnumerable<string> ExecuteResetSoft(IQueryCompounded<IDistributedQueryAtom> distQuery,
242
        DateFilter rng, Session session);
243

244
    /// <summary>
245
    ///     执行混合重置表达式
246
    /// </summary>
247
    /// <param name="distQuery">分期检索式</param>
248
    /// <param name="rng">日期过滤器</param>
249
    /// <param name="session">客户端会话</param>
250
    /// <returns>执行结果</returns>
251
    protected abstract IAsyncEnumerable<string> ExecuteResetMixed(IQueryCompounded<IDistributedQueryAtom> distQuery,
252
        DateFilter rng, Session session);
253

254
    /// <summary>
255
    ///     执行硬重置表达式
256
    /// </summary>
257
    /// <param name="distQuery">分期检索式</param>
258
    /// <param name="query">记账凭证检索式</param>
259
    /// <param name="session">客户端会话</param>
260
    /// <returns>执行结果</returns>
261
    protected abstract IAsyncEnumerable<string> ExecuteResetHard(IQueryCompounded<IDistributedQueryAtom> distQuery,
262
        IQueryCompounded<IVoucherQueryAtom> query, Session session);
263

264
    /// <summary>
265
    ///     执行应用表达式
266
    /// </summary>
267
    /// <param name="distQuery">分期检索式</param>
268
    /// <param name="rng">日期过滤器</param>
269
    /// <param name="isCollapsed">是否压缩</param>
270
    /// <param name="session">客户端会话</param>
271
    /// <returns>执行结果</returns>
272
    protected abstract IAsyncEnumerable<string> ExecuteApply(IQueryCompounded<IDistributedQueryAtom> distQuery,
273
        DateFilter rng, bool isCollapsed, Session session);
274

275
    /// <summary>
276
    ///     执行检查表达式
277
    /// </summary>
278
    /// <param name="distQuery">分期检索式</param>
279
    /// <param name="rng">日期过滤器</param>
280
    /// <param name="session">客户端会话</param>
281
    /// <returns>执行结果</returns>
282
    protected abstract IAsyncEnumerable<string> ExecuteCheck(IQueryCompounded<IDistributedQueryAtom> distQuery,
283
        DateFilter rng, Session session);
284
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc