Skip to content

Commit ec55811

Browse files
author
Jani Giannoudis
committed
case set: added change reason and forecast
report: added user type payroll service get derived reports: added support for user type command manager: fixed working path with keep-path option exchange import: improved handling of text and binary content updated version to 0.9.0-beta.4
1 parent 084b56f commit ec55811

17 files changed

+209
-87
lines changed

Client.Core/Command/CommandBase.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,18 +61,18 @@ protected void ProcessError(ICommandConsole console, Exception exception)
6161
{
6262
return;
6363
}
64+
var message = exception.GetBaseException().Message;
6465

6566
// api error
6667
var apiError = exception.GetApiErrorMessage();
6768
if (!string.IsNullOrWhiteSpace(apiError))
6869
{
70+
message = apiError;
6971
console.DisplayErrorLine(apiError);
7072
}
71-
else
72-
{
73-
// generic error log
74-
Log.Error(exception, exception.GetBaseException().Message);
75-
}
73+
74+
// log
75+
Log.Error(exception, message);
7676
}
7777

7878
/// <summary>

Client.Core/Command/CommandLineParser.cs

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,38 @@
11
using System;
2-
using System.Collections.Generic;
32
using System.Linq;
3+
using System.Collections.Generic;
44
using System.Runtime.CompilerServices;
55

66
namespace PayrollEngine.Client.Command;
77

88
/// <summary>Represents the environment command line arguments</summary>
9-
public class CommandLineParser(string[] commandLineArgs)
9+
public class CommandLineParser(string[] arguments)
1010
{
11-
private string[] CommandLineArgs { get; } = commandLineArgs ?? throw new ArgumentNullException(nameof(commandLineArgs));
11+
/// <summary>Command line arguments</summary>
12+
public string[] Arguments { get; } = arguments ?? throw new ArgumentNullException(nameof(arguments));
1213

1314
/// <summary>Get the command line arguments count, excluding the implicit parameter at index 0</summary>
1415
public int ParameterCount =>
1516
Count - 1;
1617

1718
/// <summary>Get the command line arguments count</summary>
1819
public int Count =>
19-
CommandLineArgs.Length;
20+
Arguments.Length;
2021

2122
/// <summary>Determines whether the specified argument exists</summary>
2223
/// <param name="name">The argument</param>
2324
/// <returns>True if the specified argument exists</returns>
2425
private bool Contains(string name) =>
25-
CommandLineArgs.FirstOrDefault(x => string.Equals(name, x, StringComparison.InvariantCultureIgnoreCase)) != null;
26+
Arguments.FirstOrDefault(x => string.Equals(name, x, StringComparison.InvariantCultureIgnoreCase)) != null;
2627

2728
/// <summary>Determines whether the specified argument exists</summary>
2829
/// <returns>True if the specified toggle exists</returns>
2930
public bool IsValidOrder()
3031
{
31-
var arguments = CommandLineArgs;
3232
int? firstToggleIndex = null;
33-
for (var i = 0; i < arguments.Length; i++)
33+
for (var i = 0; i < Arguments.Length; i++)
3434
{
35-
var argument = arguments[i];
35+
var argument = Arguments[i];
3636
if (IsToggleArgument(argument))
3737
{
3838
firstToggleIndex ??= i;
@@ -79,8 +79,8 @@ public string GetMember(int index, [CallerMemberName] string memberName = "", bo
7979

8080
/// <summary>Gets the specified index, starting at 1</summary>
8181
/// <param name="index">The argument index</param>
82-
/// <param name="name">The argument name (optional)</param>
83-
/// <param name="allowToggle">Argument can be a toggle (optional)</param>
82+
/// <param name="name">The argument name (default=null)</param>
83+
/// <param name="allowToggle">Argument can be a toggle (default: false)</param>
8484
/// <returns>The argument value</returns>
8585
public string Get(int index, string name = null, bool allowToggle = false)
8686
{
@@ -89,7 +89,7 @@ public string Get(int index, string name = null, bool allowToggle = false)
8989
throw new ArgumentOutOfRangeException(nameof(index));
9090
}
9191

92-
if (CommandLineArgs.Length <= index || index >= CommandLineArgs.Length)
92+
if (Arguments.Length <= index || index >= Arguments.Length)
9393
{
9494
return null;
9595
}
@@ -104,7 +104,7 @@ public string Get(int index, string name = null, bool allowToggle = false)
104104
}
105105
}
106106

107-
var arg = CommandLineArgs[index];
107+
var arg = Arguments[index];
108108

109109
// name
110110
if (name != null)
@@ -130,7 +130,7 @@ public string GetByName(string name)
130130
throw new ArgumentException(nameof(name));
131131
}
132132
var marker = $"{name}:";
133-
foreach (var cmdLineArg in CommandLineArgs)
133+
foreach (var cmdLineArg in Arguments)
134134
{
135135
if (cmdLineArg.StartsWith(marker, StringComparison.InvariantCultureIgnoreCase))
136136
{
@@ -249,7 +249,7 @@ public T GetEnum<T>(int index, T defaultValue, string name = null)
249249
/// <summary>Gets all toggle with fallback value</summary>
250250
/// <returns>The argument value</returns>
251251
public IEnumerable<string> GetToggles() =>
252-
CommandLineArgs.Where(IsToggleArgument);
252+
Arguments.Where(IsToggleArgument);
253253

254254
/// <summary>Gets a toggle with fallback value</summary>
255255
/// <typeparam name="T">The enum type</typeparam>
@@ -265,10 +265,10 @@ public string TestUnknownToggles(IEnumerable<Type> enumTypes)
265265
{
266266
var enumTypesArray = enumTypes.ToArray();
267267
// test for unknown toggles
268-
for (var i = 1; i < CommandLineArgs.Length; i++)
268+
for (var i = 1; i < Arguments.Length; i++)
269269
{
270270
// command line argument
271-
var arg = CommandLineArgs[i];
271+
var arg = Arguments[i];
272272
if (!IsToggleArgument(arg))
273273
{
274274
continue;
@@ -315,11 +315,11 @@ public Type TestMultipleToggles(IEnumerable<Type> enumTypes)
315315
/// </summary>
316316
public string[] GetArguments()
317317
{
318-
if (commandLineArgs.Length <= 2)
318+
if (arguments.Length <= 2)
319319
{
320320
return null;
321321
}
322-
return CommandLineArgs.Skip(2).ToArray();
322+
return Arguments.Skip(2).ToArray();
323323
}
324324

325325
#region Static
@@ -328,6 +328,7 @@ public string[] GetArguments()
328328
public static CommandLineParser NewFromEnvironment() =>
329329
new(Environment.GetCommandLineArgs());
330330

331+
331332
/// <summary>New command line parser from command string</summary>
332333
public static CommandLineParser NewFromCommand(string command) =>
333334
new(SplitCommandArguments(command));

Client.Core/Command/CommandManager.cs

Lines changed: 64 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -239,18 +239,29 @@ private async Task<int> ExecuteAsync(ICommand command, CommandLineParser command
239239

240240
#region Command File
241241

242-
private class FileItem(string text, ICommand command, CommandLineParser parser)
242+
private class FileItem
243243
{
244-
public FileItem(string text, CommandLineParser parser, List<FileItem> children) :
244+
public FileItem(string text, string path, CommandLineParser parser, List<FileItem> children) :
245245
this(text, null, parser)
246246
{
247+
Path = path;
247248
Parser = parser;
248249
Children = children;
249250
}
250251

251-
internal string Text { get; } = text;
252-
public ICommand Command { get; } = command;
253-
public CommandLineParser Parser { get; } = parser;
252+
// ReSharper disable once ConvertToPrimaryConstructor
253+
public FileItem(string text, ICommand command, CommandLineParser parser)
254+
{
255+
Text = text;
256+
Command = command;
257+
Parser = parser;
258+
}
259+
260+
// ReSharper disable once UnusedAutoPropertyAccessor.Local
261+
internal string Text { get; }
262+
internal string Path { get; }
263+
public ICommand Command { get; }
264+
public CommandLineParser Parser { get; }
254265
internal List<FileItem> Children { get; } = [];
255266
}
256267

@@ -288,19 +299,19 @@ private async Task<int> ExecuteFileAsync(CommandLineParser parser, PayrollHttpCl
288299

289300
private async Task<int> ExecuteFileItemAsync(FileItem item, PayrollHttpClient httpClient = null)
290301
{
291-
// command
292-
if (item.Command != null)
293-
{
294-
return await ExecuteAsync(item.Command, item.Parser, httpClient);
295-
}
296-
297302
// command file
298303
// working dir
299304
var currentDirectory = Directory.GetCurrentDirectory();
300-
if (item.Parser.GetEnumToggle(PathChangeMode.ChangePath) == PathChangeMode.ChangePath)
305+
if (!string.IsNullOrWhiteSpace(item.Path) &&
306+
item.Parser.GetEnumToggle(PathChangeMode.ChangePath) == PathChangeMode.ChangePath)
307+
{
308+
EnsureCurrentDirectory(item.Path);
309+
}
310+
311+
// command
312+
if (item.Command != null)
301313
{
302-
var directory = new FileInfo(item.Text).DirectoryName;
303-
EnsureCurrentDirectory(directory);
314+
return await ExecuteAsync(item.Command, item.Parser, httpClient);
304315
}
305316

306317
// display
@@ -330,19 +341,47 @@ private async Task<int> ExecuteFileItemAsync(FileItem item, PayrollHttpClient ht
330341
return 0;
331342
}
332343

333-
private List<FileItem> ReadCommandFile(CommandLineParser fileParser)
344+
private List<FileItem> ReadCommandFile(CommandLineParser parser, bool rootCommandFile = false)
334345
{
335346
// test file
336-
var fileName = fileParser.Get(1);
347+
var fileName = parser.Get(1);
337348
if (!IsCommandFile(fileName))
338349
{
339350
return null;
340351
}
341352

353+
var fileItems = new List<FileItem>();
342354
var info = new FileInfo(fileName);
343355
var fileBaseName = info.Name;
344356

357+
// command file
358+
if (!rootCommandFile && IsCommandFile(fileName))
359+
{
360+
var parsedLine = ParseParameters(parser, fileName);
361+
// transfer command line arguments
362+
var lineParser = new CommandLineParser(parser.Arguments);
363+
364+
var linePathMode = lineParser.GetEnumToggle<PathChangeMode>(default);
365+
Logger?.Trace($"Command file {fileName} (path-mode: {linePathMode})");
366+
var commandFileItems = ReadCommandFile(lineParser, rootCommandFile: true);
367+
368+
// restore working dir
369+
if (linePathMode == PathChangeMode.ChangePath)
370+
{
371+
EnsureCurrentDirectory(info.DirectoryName);
372+
}
373+
374+
// add file item
375+
if (commandFileItems != null)
376+
{
377+
var fileItem = new FileItem(parsedLine, info.DirectoryName, lineParser, commandFileItems);
378+
fileItems.Add(fileItem);
379+
}
380+
return fileItems;
381+
}
382+
345383
// ensure working dir
384+
var pathMode = parser.GetEnumToggle<PathChangeMode>(default);
346385
var startDirectory = Directory.GetCurrentDirectory();
347386
EnsureCurrentDirectory(info.DirectoryName);
348387
if (!File.Exists(fileBaseName))
@@ -352,9 +391,8 @@ private List<FileItem> ReadCommandFile(CommandLineParser fileParser)
352391
}
353392

354393
// read commands
355-
var fileItems = new List<FileItem>();
356394
var lines = File.ReadAllLines(fileBaseName).Select(x => x.Trim()).ToList();
357-
Logger?.Trace($"Parsing command file {fileBaseName} ({lines.Count} lines)");
395+
Logger?.Trace($"Parsing command file {fileBaseName} ({lines.Count} lines, path-mode: {pathMode}))");
358396

359397
var error = false;
360398
foreach (var line in lines)
@@ -365,24 +403,28 @@ private List<FileItem> ReadCommandFile(CommandLineParser fileParser)
365403
continue;
366404
}
367405

368-
var parsedLine = ParseParameters(fileParser, line);
406+
var parsedLine = ParseParameters(parser, line);
369407

370408
var lineParser = CommandLineParser.NewFromCommand(parsedLine);
371409
var name = lineParser.Get(1);
372410

373411
// command file
374412
if (IsCommandFile(name))
375413
{
376-
Logger?.Trace($"Command file {fileName} command file: {parsedLine}");
377414
var commandFileItems = ReadCommandFile(lineParser);
415+
var linePathMode = lineParser.GetEnumToggle<PathChangeMode>(default);
416+
Logger?.Trace($"Command file {fileName} command file: {parsedLine} (path-mode: {linePathMode})");
378417

379418
// restore working dir
380-
EnsureCurrentDirectory(info.DirectoryName);
419+
if (linePathMode == PathChangeMode.ChangePath)
420+
{
421+
EnsureCurrentDirectory(info.DirectoryName);
422+
}
381423

382424
// add file item
383425
if (commandFileItems != null)
384426
{
385-
var fileItem = new FileItem(parsedLine, lineParser, commandFileItems);
427+
var fileItem = new FileItem(parsedLine, info.DirectoryName, lineParser, commandFileItems);
386428
fileItems.Add(fileItem);
387429
}
388430
continue;

Client.Core/ExceptionExtensions.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,14 @@ public static string GetApiErrorMessage(this Exception exception)
2626
{
2727
var buffer = new StringBuilder();
2828
buffer.AppendLine(apiError.Title);
29-
foreach (var error in apiError.Errors)
29+
if (apiError.Errors != null)
3030
{
31-
foreach (var errorValue in error.Value)
31+
foreach (var error in apiError.Errors)
3232
{
33-
buffer.AppendLine($"{error.Key}: {errorValue.Trim()}");
33+
foreach (var errorValue in error.Value)
34+
{
35+
buffer.AppendLine($"{error.Key}: {errorValue.Trim()}");
36+
}
3437
}
3538
}
3639
return buffer.ToString().Trim('\r', '\n', '"');
@@ -77,7 +80,7 @@ private static ApiError GetApiError(this Exception exception)
7780
try
7881
{
7982
var apiError = JsonSerializer.Deserialize<ApiError>(message);
80-
if (apiError.Status != 0)
83+
if (apiError != null && apiError.Status != 0)
8184
{
8285
return apiError;
8386
}

0 commit comments

Comments
 (0)