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

b1f6c1c4 / ProfessionalAccounting / 307

25 Sep 2023 04:48AM UTC coverage: 56.975% (-1.3%) from 58.254%
307

push

appveyor

b1f6c1c4
raw subtotal more controllable

5947 of 10438 relevant lines covered (56.97%)

125.9 hits per line

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

72.34
/AccountingServer.Shell/Serializer/CsvSerializer.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.Linq;
22
using System.Text;
23
using AccountingServer.BLL.Util;
24
using AccountingServer.Entities;
25
using AccountingServer.Shell.Util;
26
using static AccountingServer.BLL.Parsing.Facade;
27

28
namespace AccountingServer.Shell.Serializer;
29

30
/// <summary>
31
///     Csv表达式
32
/// </summary>
33
public class CsvSerializer : IEntitiesSerializer
34
{
35
    private readonly string m_Sep = "\t";
4✔
36
    private readonly List<ColumnSpec> m_Specs = new();
4✔
37

38
    public CsvSerializer(string spec)
4✔
39
    {
4✔
40
        {
4✔
41
            var sep = Parsing.Quoted(ref spec, '\'');
4✔
42
            if (sep != null)
4✔
43
                m_Sep = sep;
×
44
        }
4✔
45

46
        if (string.IsNullOrWhiteSpace(spec))
4✔
47
        {
2✔
48
            m_Specs.Add(ColumnSpec.VoucherID);
2✔
49
            m_Specs.Add(ColumnSpec.VoucherDate);
2✔
50
            m_Specs.Add(ColumnSpec.User);
2✔
51
            m_Specs.Add(ColumnSpec.Currency);
2✔
52
            m_Specs.Add(ColumnSpec.Title);
2✔
53
            m_Specs.Add(ColumnSpec.TitleComment);
2✔
54
            m_Specs.Add(ColumnSpec.SubTitle);
2✔
55
            m_Specs.Add(ColumnSpec.SubTitleComment);
2✔
56
            m_Specs.Add(ColumnSpec.Content);
2✔
57
            m_Specs.Add(ColumnSpec.Remark);
2✔
58
            m_Specs.Add(ColumnSpec.Fund);
2✔
59
            return;
2✔
60
        }
61

62
        while (!string.IsNullOrWhiteSpace(spec))
26✔
63
        {
24✔
64
            var sep = Parsing.Quoted(ref spec, '\'');
24✔
65
            if (sep != null)
24✔
66
            {
×
67
                m_Sep = sep;
×
68
                continue;
×
69
            }
70

71
            var s = Parsing.Token(ref spec, false);
24✔
72
            switch (s)
24✔
73
            {
74
                case "id":
75
                    m_Specs.Add(ColumnSpec.VoucherID);
2✔
76
                    break;
2✔
77
                case "d":
78
                case "date":
79
                    m_Specs.Add(ColumnSpec.VoucherDate);
2✔
80
                    break;
2✔
81
                case "type":
82
                    m_Specs.Add(ColumnSpec.VoucherType);
2✔
83
                    break;
2✔
84
                case "U":
85
                case "user":
86
                    m_Specs.Add(ColumnSpec.User);
2✔
87
                    break;
2✔
88
                case "C":
89
                case "currency":
90
                    m_Specs.Add(ColumnSpec.Currency);
2✔
91
                    break;
2✔
92
                case "t":
93
                case "title":
94
                    m_Specs.Add(ColumnSpec.Title);
2✔
95
                    break;
2✔
96
                case "t'":
97
                    m_Specs.Add(ColumnSpec.TitleComment);
2✔
98
                    break;
2✔
99
                case "s":
100
                case "subtitle":
101
                    m_Specs.Add(ColumnSpec.SubTitle);
2✔
102
                    break;
2✔
103
                case "s'":
104
                    m_Specs.Add(ColumnSpec.SubTitleComment);
2✔
105
                    break;
2✔
106
                case "c":
107
                case "content":
108
                    m_Specs.Add(ColumnSpec.Content);
2✔
109
                    break;
2✔
110
                case "r":
111
                case "remark":
112
                    m_Specs.Add(ColumnSpec.Remark);
2✔
113
                    break;
2✔
114
                case "v":
115
                case "fund":
116
                    m_Specs.Add(ColumnSpec.Fund);
2✔
117
                    break;
2✔
118
            }
119
        }
24✔
120
    }
4✔
121

122
    private IList<ColumnSpec> DetailSpec => m_Specs.Where(static s => !s.HasFlag(ColumnSpec.Voucher)).ToList();
×
123

124
    /// <inheritdoc />
125
    public string PresentVoucher(Voucher voucher)
126
    {
2✔
127
        var sb = new StringBuilder();
2✔
128
        sb.Append(PresentHeader(m_Specs));
2✔
129
        if (voucher == null)
2✔
130
            return "";
×
131
        foreach (var d in voucher.Details)
4✔
132
            sb.Append(Present(new(voucher, d), m_Specs));
2✔
133
        return sb.ToString();
2✔
134
    }
2✔
135

136
    /// <inheritdoc />
137
    public string PresentVoucher(Voucher voucher, string inject) => throw new NotImplementedException();
×
138

139
    /// <inheritdoc />
140
    public string PresentVoucherDetail(VoucherDetail detail)
141
    {
×
142
        var sb = new StringBuilder();
×
143
        sb.Append(PresentHeader(DetailSpec));
×
144
        sb.Append(Present(new(null, detail), DetailSpec));
×
145
        return sb.ToString();
×
146
    }
×
147

148
    /// <inheritdoc />
149
    public string PresentVoucherDetail(VoucherDetailR detail)
150
    {
×
151
        var sb = new StringBuilder();
×
152
        sb.Append(PresentHeader(m_Specs));
×
153
        sb.Append(Present(detail, m_Specs));
×
154
        return sb.ToString();
×
155
    }
×
156

157
    /// <inheritdoc />
158
    public async IAsyncEnumerable<string> PresentVouchers(IAsyncEnumerable<Voucher> vouchers)
159
    {
×
160
        yield return PresentHeader(m_Specs);
×
161
        await foreach (var voucher in vouchers)
×
162
        foreach (var detail in voucher.Details)
×
163
            yield return Present(new(voucher, detail), m_Specs);
×
164
    }
×
165

166
    /// <inheritdoc />
167
    public async IAsyncEnumerable<string> PresentVoucherDetails(IAsyncEnumerable<VoucherDetail> details)
168
    {
×
169
        yield return PresentHeader(DetailSpec);
×
170
        await foreach (var detail in details)
×
171
            yield return Present(new(null, detail), DetailSpec);
×
172
    }
×
173

174
    /// <inheritdoc />
175
    public async IAsyncEnumerable<string> PresentVoucherDetails(IAsyncEnumerable<VoucherDetailR> details)
176
    {
×
177
        yield return PresentHeader(m_Specs);
×
178
        await foreach (var detail in details)
×
179
            yield return Present(detail, m_Specs);
×
180
    }
×
181

182
    public Voucher ParseVoucher(string str) => throw new NotImplementedException();
2✔
183
    public VoucherDetail ParseVoucherDetail(string str) => throw new NotImplementedException();
2✔
184
    public string PresentAsset(Asset asset) => throw new NotImplementedException();
2✔
185
    public Asset ParseAsset(string str) => throw new NotImplementedException();
2✔
186
    public string PresentAmort(Amortization amort) => throw new NotImplementedException();
2✔
187
    public Amortization ParseAmort(string str) => throw new NotImplementedException();
2✔
188

189
    public IAsyncEnumerable<string> PresentAssets(IAsyncEnumerable<Asset> assets)
190
        => throw new NotImplementedException();
×
191

192
    public IAsyncEnumerable<string> PresentAmorts(IAsyncEnumerable<Amortization> amorts)
193
        => throw new NotImplementedException();
×
194

195
    private string PresentHeader(IList<ColumnSpec> spec)
196
    {
2✔
197
        var sb = new StringBuilder();
2✔
198
        for (var i = 0; i < spec.Count; i++)
25✔
199
        {
23✔
200
            var s = spec[i];
23✔
201
            if (i > 0)
23✔
202
                sb.Append(m_Sep);
21✔
203
            sb.Append(s);
23✔
204
        }
23✔
205

206
        sb.Append("\n");
2✔
207
        return sb.ToString();
2✔
208
    }
2✔
209

210
    /// <summary>
211
    ///     将带记账凭证的细目转换为Csv表示
212
    /// </summary>
213
    /// <param name="d">细目</param>
214
    /// <param name="spec">列</param>
215
    /// <returns>Csv表示</returns>
216
    private string Present(VoucherDetailR d, IList<ColumnSpec> spec)
217
    {
2✔
218
        var sb = new StringBuilder();
2✔
219
        for (var i = 0; i < spec.Count; i++)
25✔
220
        {
23✔
221
            if (i > 0)
23✔
222
                sb.Append(m_Sep);
21✔
223

224
            sb.Append(spec[i] switch
×
225
                {
226
                    ColumnSpec.VoucherID => d.Voucher.ID,
2✔
227
                    ColumnSpec.VoucherDate => d.Voucher.Date.AsDate(),
2✔
228
                    ColumnSpec.VoucherType => d.Voucher.Type,
1✔
229
                    ColumnSpec.User => d.User,
2✔
230
                    ColumnSpec.Currency => d.Currency,
2✔
231
                    ColumnSpec.Title => d.Title.AsTitle(),
2✔
232
                    ColumnSpec.TitleComment => TitleManager.GetTitleName(d.Title),
2✔
233
                    ColumnSpec.SubTitle => d.SubTitle.AsSubTitle(),
2✔
234
                    ColumnSpec.SubTitleComment => TitleManager.GetTitleName(d.Title, d.SubTitle),
2✔
235
                    ColumnSpec.Content => d.Content.Quotation('\''),
2✔
236
                    ColumnSpec.Remark => d.Remark.Quotation('"'),
2✔
237
                    ColumnSpec.Fund => $"{d.Fund:R}",
2✔
238
                    _ => throw new ArgumentOutOfRangeException(),
×
239
                });
240
        }
23✔
241

242
        sb.Append("\n");
2✔
243
        return sb.ToString();
2✔
244
    }
2✔
245

246
    [Flags]
247
    private enum ColumnSpec
248
    {
249
        Voucher = 0x1000,
250
        VoucherID = 0x1001,
251
        VoucherDate = 0x1002,
252
        VoucherType = 0x1003,
253
        User = 0xc,
254
        Currency = 0x4,
255
        Title = 0x5,
256
        TitleComment = 0x6,
257
        SubTitle = 0x7,
258
        SubTitleComment = 0x8,
259
        Content = 0x9,
260
        Remark = 0xa,
261
        Fund = 0xb,
262
    }
263
}
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