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

b1f6c1c4 / ProfessionalAccounting / 315

13 Apr 2024 08:29AM UTC coverage: 0.0%. Remained the same
315

push

appveyor

b1f6c1c4
rich style

0 of 23101 relevant lines covered (0.0%)

0.0 hits per line

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

0.0
/AccountingServer.Shell/Serializer/ExprSerializer.cs
1
/* Copyright (C) 2020-2024 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.Text;
22
using System.Text.RegularExpressions;
23
using AccountingServer.BLL;
24
using AccountingServer.BLL.Util;
25
using AccountingServer.Entities;
26
using AccountingServer.Shell.Util;
27
using static AccountingServer.BLL.Parsing.Facade;
28
using static AccountingServer.BLL.Parsing.FacadeF;
29

30
namespace AccountingServer.Shell.Serializer;
31

32
/// <summary>
33
///     实体表达式
34
/// </summary>
35
public class ExprSerializer : IClientDependable, IEntitySerializer
36
{
37
    private const string TheToken = "new Voucher {";
38

39
    public Client Client { private get; set; }
40

41
    /// <inheritdoc />
42
    public string PresentVoucher(Voucher voucher)
43
        => PresentVoucher(voucher, null);
×
44

45
    /// <inheritdoc />
46
    public string PresentVoucher(Voucher voucher, string inject)
47
    {
×
48
        var sb = new StringBuilder();
×
49
        sb.Append(TheToken);
×
50
        if (voucher == null)
×
51
        {
×
52
            sb.Append("\n");
×
53
            sb.Append("\n");
×
54
        }
×
55
        else
56
        {
×
57
            sb.Append($"{voucher.ID?.Quotation('^')}\n");
×
58
            if (voucher.Date.HasValue || inject == null)
×
59
                sb.Append($"{voucher.Date.AsDate()}\n");
×
60
            if (voucher.Remark != null)
×
61
                sb.Append($"{voucher.Remark.Quotation('%')}\n");
×
62
            if (voucher.Type.HasValue &&
×
63
                voucher.Type != VoucherType.Ordinary)
64
                sb.Append($"{voucher.Type}\n");
×
65

66
            if (inject != null)
×
67
                sb.Append($"{inject}\n");
×
68

69
            foreach (var d in voucher.Details)
×
70
                sb.Append(PresentVoucherDetail(d));
×
71
        }
×
72

73
        sb.Append('}');
×
74
        return sb.ToString();
×
75
    }
×
76

77
    /// <inheritdoc />
78
    public string PresentVoucherDetail(VoucherDetail detail)
79
    {
×
80
        var sb = new StringBuilder();
×
81
        var t = TitleManager.GetTitleName(detail.Title);
×
82
        sb.Append(
×
83
            detail.SubTitle.HasValue
84
                ? $"// {t}-{TitleManager.GetTitleName(detail.Title, detail.SubTitle)}\n"
85
                : $"// {t}\n");
86
        if (detail.User != Client.User)
×
87
            sb.Append($"{detail.User.AsUser()} ");
×
88
        if (detail.Currency != BaseCurrency.Now)
×
89
            sb.Append($"{detail.Currency.AsCurrency()} ");
×
90
        sb.Append($"{detail.Title.AsTitle()}{detail.SubTitle.AsSubTitle()} ");
×
91
        if (detail.Content == null &&
×
92
            detail.Remark != null)
93
            sb.Append("''");
×
94
        else
95
            sb.Append(detail.Content?.Quotation('\''));
×
96
        sb.Append($" {detail.Remark?.Quotation('\"')} {detail.Fund}\n");
×
97
        return sb.ToString();
×
98
    }
×
99

100
    /// <inheritdoc />
101
    public string PresentVoucherDetail(VoucherDetailR detail)
102
        => $"{detail.Voucher.Date.AsDate()} {PresentVoucherDetail((VoucherDetail)detail)}";
×
103

104
    /// <inheritdoc />
105
    public Voucher ParseVoucher(string expr)
106
    {
×
107
        if (!expr.StartsWith(TheToken, StringComparison.Ordinal))
×
108
            throw new FormatException("格式错误");
×
109

110
        expr = expr[TheToken.Length..];
×
111
        var v = GetVoucher(ref expr);
×
112
        Parsing.TrimStartComment(ref expr);
×
113
        if (Parsing.Token(ref expr, false) != "}")
×
114
            throw new FormatException("格式错误" + expr);
×
115

116
        Parsing.Eof(expr);
×
117
        return v;
×
118
    }
×
119

120
    /// <inheritdoc />
121
    public virtual VoucherDetail ParseVoucherDetail(string expr)
122
    {
×
123
        var res = ParseVoucherDetail(ref expr);
×
124
        Parsing.Eof(expr);
×
125
        return res;
×
126
    }
×
127

128
    public string PresentAsset(Asset asset) => throw new NotImplementedException();
×
129
    public Asset ParseAsset(string str) => throw new NotImplementedException();
×
130
    public string PresentAmort(Amortization amort) => throw new NotImplementedException();
×
131
    public Amortization ParseAmort(string str) => throw new NotImplementedException();
×
132

133
    /// <summary>
134
    ///     解析记账凭证表达式
135
    /// </summary>
136
    /// <param name="expr">表达式</param>
137
    /// <returns>记账凭证</returns>
138
    private Voucher GetVoucher(ref string expr)
139
    {
×
140
        Parsing.TrimStartComment(ref expr);
×
141
        var id = Parsing.Quoted(ref expr, '^');
×
142
        Parsing.TrimStartComment(ref expr);
×
143
        DateTime? date = Client.Today;
×
144
        try
145
        {
×
146
            date = ParsingF.UniqueTime(ref expr, Client);
×
147
        }
×
148
        catch (Exception)
×
149
        {
×
150
            // ignore
151
        }
×
152

153
        Parsing.TrimStartComment(ref expr);
×
154
        var remark = Parsing.Quoted(ref expr, '%');
×
155
        Parsing.TrimStartComment(ref expr);
×
156
        var typeT = VoucherType.Ordinary;
×
157
        var type = Parsing.Token(ref expr, false, t => TryParse(t, out typeT)) != null ? (VoucherType?)typeT : null;
×
158
        Parsing.TrimStartComment(ref expr);
×
159

160
        var lst = new List<VoucherDetail>();
×
161
        VoucherDetail d;
162
        while ((d = ParseVoucherDetail(ref expr)) != null)
×
163
            lst.Add(d);
×
164

165
        return new()
×
166
            {
167
                ID = id,
168
                Remark = remark,
169
                Type = type,
170
                Date = date,
171
                Details = lst,
172
            };
173
    }
×
174

175
    /// <summary>
176
    ///     解析记账凭证类别表达式
177
    /// </summary>
178
    /// <param name="s">表达式</param>
179
    /// <param name="typeT">记账凭证类别</param>
180
    /// <returns>是否解析成功</returns>
181
    private static bool TryParse(string s, out VoucherType typeT)
182
    {
×
183
        // Don't use Enum.TryParse here:
184
        // Enum.TryParse("1001", out _) gives true
185
        switch (s)
×
186
        {
187
            case "Ordinary":
188
                typeT = VoucherType.Ordinary;
×
189
                return true;
×
190
            case "Carry":
191
                typeT = VoucherType.Carry;
×
192
                return true;
×
193
            case "AnnualCarry":
194
                typeT = VoucherType.AnnualCarry;
×
195
                return true;
×
196
            case "Depreciation":
197
                typeT = VoucherType.Depreciation;
×
198
                return true;
×
199
            case "Devalue":
200
                typeT = VoucherType.Devalue;
×
201
                return true;
×
202
            case "Amortization":
203
                typeT = VoucherType.Amortization;
×
204
                return true;
×
205
            case "Uncertain":
206
                typeT = VoucherType.Uncertain;
×
207
                return true;
×
208
            default:
209
                typeT = VoucherType.General;
×
210
                return false;
×
211
        }
212
    }
×
213

214
    private Regex m_SimpleCurrency = new(@"^@[a-zA-Z]+$");
×
215

216
    public VoucherDetail ParseVoucherDetail(ref string expr)
217
    {
×
218
        var lst = new List<string>();
×
219

220
        Parsing.TrimStartComment(ref expr);
×
221
        var user = Parsing.Token(ref expr, false, static t => t.StartsWith("U", StringComparison.Ordinal))
×
222
            .ParseUserSpec(Client);
223
        var currency = BaseCurrency.Now;
×
224
        if (Parsing.Token(ref expr, false, m_SimpleCurrency.IsMatch) is var t && t != null)
×
225
            currency = t.ParseCurrency();
×
226
        else if (expr[0] == '@')
×
227
        {
×
228
            expr = expr[1..];
×
229
            currency = Parsing.Quoted(ref expr, '#') + '#';
×
230
        }
×
231
        Parsing.TrimStartComment(ref expr);
×
232
        var title = Parsing.Title(ref expr);
×
233
        if (title == null)
×
234
            if (!AlternativeTitle(ref expr, lst, ref title))
×
235
                return null;
×
236

237
        double? fund;
238

239
        while (true)
×
240
        {
×
241
            Parsing.TrimStartComment(ref expr);
×
242
            if ((fund = Parsing.Double(ref expr)) != null)
×
243
                break;
×
244

245
            Parsing.TrimStartComment(ref expr);
×
246
            if (Parsing.Optional(ref expr, "null"))
×
247
                break;
×
248
            if (Parsing.Optional(ref expr, "/"))
×
249
                break;
×
250

251
            if (lst.Count > 2)
×
252
                throw new ArgumentException("语法错误", nameof(expr));
×
253

254
            Parsing.TrimStartComment(ref expr);
×
255
            lst.Add(Parsing.Token(ref expr));
×
256
        }
×
257

258
        var content = lst.Count >= 1 ? lst[0] : null;
×
259
        var remark = lst.Count >= 2 ? lst[1] : null;
×
260

261
        if (content == "G()")
×
262
            content = Guid.NewGuid().ToString().ToUpperInvariant();
×
263

264
        if (remark == "G()")
×
265
            remark = Guid.NewGuid().ToString().ToUpperInvariant();
×
266

267
        return new()
×
268
            {
269
                User = user,
270
                Currency = currency,
271
                Title = title.Title,
272
                SubTitle = title.SubTitle,
273
                Content = string.IsNullOrEmpty(content) ? null : content,
274
                Fund = fund,
275
                Remark = string.IsNullOrEmpty(remark) ? null : remark,
276
            };
277
    }
×
278

279
    protected virtual bool AlternativeTitle(ref string expr, ICollection<string> lst, ref ITitle title) => false;
×
280
}
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

© 2025 Coveralls, Inc