|
|
@@ -21,6 +21,7 @@ namespace MAX
|
|
21
|
21
|
private int _userId;
|
|
22
|
22
|
private string _username;
|
|
23
|
23
|
private string _password;
|
|
|
24
|
+ private bool _logResponses;
|
|
24
|
25
|
|
|
25
|
26
|
private TcpClient _connection = null;
|
|
26
|
27
|
private NetworkStream _connectionStream = null;
|
|
|
@@ -28,7 +29,7 @@ namespace MAX
|
|
28
|
29
|
|
|
29
|
30
|
private bool _disposed = false;
|
|
30
|
31
|
|
|
31
|
|
- public Client(ILogger logger, string host, int port, int vendorId, string serialNumber, int userId, string username, string password)
|
|
|
32
|
+ public Client(ILogger logger, bool logResponses, string host, int port, int vendorId, string serialNumber, int userId, string username, string password)
|
|
32
|
33
|
{
|
|
33
|
34
|
_logger = logger;
|
|
34
|
35
|
_host = host;
|
|
|
@@ -38,14 +39,15 @@ namespace MAX
|
|
38
|
39
|
_userId = userId;
|
|
39
|
40
|
_username = username;
|
|
40
|
41
|
_password = password;
|
|
|
42
|
+ _logResponses = logResponses;
|
|
41
|
43
|
|
|
42
|
44
|
ConnectTimeout = 10000;
|
|
43
|
45
|
ReceiveTimeout = 10000;
|
|
44
|
46
|
SendTimeout = 10000;
|
|
45
|
47
|
}
|
|
46
|
48
|
|
|
47
|
|
- public Client(ILogger logger, string host, int port, LoginCredentials credentials)
|
|
48
|
|
- : this(logger, host, port, credentials.Vendor.Id, credentials.Vendor.SerialNumber,
|
|
|
49
|
+ public Client(ILogger logger, bool logResponses, string host, int port, LoginCredentials credentials)
|
|
|
50
|
+ : this(logger, logResponses, host, port, credentials.Vendor.Id, credentials.Vendor.SerialNumber,
|
|
49
|
51
|
credentials.User.Id, credentials.User.Username, credentials.Password)
|
|
50
|
52
|
{
|
|
51
|
53
|
}
|
|
|
@@ -120,28 +122,28 @@ namespace MAX
|
|
120
|
122
|
Username = _username,
|
|
121
|
123
|
FirstName = parts[4],
|
|
122
|
124
|
Surname = parts[3],
|
|
123
|
|
- Enabled = bool.Parse(parts[6]),
|
|
124
|
|
- Level = (User.UserLevel)int.Parse(parts[1]),
|
|
125
|
|
- System = int.Parse(parts[2]),
|
|
126
|
|
- LastLogin = DateTime.Parse(parts[5])
|
|
|
125
|
+ Enabled = ParseBool(parts[6], "User.Enabled(6)", response),
|
|
|
126
|
+ Level = (User.UserLevel)ParseInt(parts[1], "User.Level(1)", response),
|
|
|
127
|
+ System = ParseInt(parts[2], "User.System(2)", response),
|
|
|
128
|
+ LastLogin = ParseDateTime(parts[5], "User.LastLogin(5)", response)
|
|
127
|
129
|
};
|
|
128
|
130
|
|
|
129
|
131
|
if (user.Level == User.UserLevel.CustomUser)
|
|
130
|
132
|
{
|
|
131
|
|
- user.CanPrintOffline = bool.Parse(parts[7]);
|
|
132
|
|
- user.OfflinePrintValue = decimal.Parse(parts[8]);
|
|
133
|
|
- user.CanPrintOnline = bool.Parse(parts[9]);
|
|
134
|
|
- user.OnlinePrintValue = decimal.Parse(parts[10]);
|
|
135
|
|
- user.CanReprintOffline = bool.Parse(parts[11]);
|
|
136
|
|
- user.OfflineReprintValue = decimal.Parse(parts[12]);
|
|
137
|
|
- user.CanReprintOnline = bool.Parse(parts[13]);
|
|
138
|
|
- user.OnlineReprintValue = decimal.Parse(parts[14]);
|
|
139
|
|
- user.BulkExport = bool.Parse(parts[15]);
|
|
140
|
|
- user.BulkExportMaxValue = decimal.Parse(parts[16]);
|
|
141
|
|
- user.BulkOrder = bool.Parse(parts[17]);
|
|
142
|
|
- user.BulkOrderMaxValue = decimal.Parse(parts[18]);
|
|
143
|
|
- user.BulkViewPins = bool.Parse(parts[19]);
|
|
144
|
|
- user.BulkReExport = bool.Parse(parts[20]);
|
|
|
133
|
+ user.CanPrintOffline = ParseBool(parts[7], "User.CanPrintOffline(7)", response);
|
|
|
134
|
+ user.OfflinePrintValue = ParseDecimal(parts[8], "User.OfflinePrintValue(8)", response);
|
|
|
135
|
+ user.CanPrintOnline = ParseBool(parts[9], "User.CanPrintOnline(9)", response);
|
|
|
136
|
+ user.OnlinePrintValue = ParseDecimal(parts[10], "User.OnlinePrintValue(10)", response);
|
|
|
137
|
+ user.CanReprintOffline = ParseBool(parts[11], "User.CanReprintOffline(11)", response);
|
|
|
138
|
+ user.OfflineReprintValue = ParseDecimal(parts[12], "User.OfflineReprintValue(12)", response);
|
|
|
139
|
+ user.CanReprintOnline = ParseBool(parts[13], "User.CanReprintOnline(13)", response);
|
|
|
140
|
+ user.OnlineReprintValue = ParseDecimal(parts[14], "User.OnlineReprintValue(14)", response);
|
|
|
141
|
+ user.BulkExport = ParseBool(parts[15], "User.BulkExport(15)", response);
|
|
|
142
|
+ user.BulkExportMaxValue = ParseDecimal(parts[16], "User.BulkExportMaxValue(16)", response);
|
|
|
143
|
+ user.BulkOrder = ParseBool(parts[17], "User.BulkOrder(17)", response);
|
|
|
144
|
+ user.BulkOrderMaxValue = ParseDecimal(parts[18], "User.BulkOrderMaxValue(18)", response);
|
|
|
145
|
+ user.BulkViewPins = ParseBool(parts[19], "User.BulkViewPins(19)", response);
|
|
|
146
|
+ user.BulkReExport = ParseBool(parts[20], "User.BulkReExport(20)", response);
|
|
145
|
147
|
}
|
|
146
|
148
|
|
|
147
|
149
|
return user;
|
|
|
@@ -184,7 +186,12 @@ namespace MAX
|
|
184
|
186
|
|
|
185
|
187
|
private string Decrypt(string cipherText)
|
|
186
|
188
|
{
|
|
187
|
|
- return Utils.TripleDESDecrypt(cipherText, _des);
|
|
|
189
|
+ var response = Utils.TripleDESDecrypt(cipherText, _des);
|
|
|
190
|
+ if (_logResponses)
|
|
|
191
|
+ {
|
|
|
192
|
+ _logger.LogDebug("Decrypted response for {0}: {1}", LoginCredentials.Format(_userId, _username, _vendorId, _serialNumber), response);
|
|
|
193
|
+ }
|
|
|
194
|
+ return response;
|
|
188
|
195
|
}
|
|
189
|
196
|
|
|
190
|
197
|
private string Encrypt(string plainText)
|
|
|
@@ -246,14 +253,14 @@ namespace MAX
|
|
246
|
253
|
var parts = response.Split('|');
|
|
247
|
254
|
return new Account()
|
|
248
|
255
|
{
|
|
249
|
|
- Id = int.Parse(parts[1]),
|
|
|
256
|
+ Id = ParseInt(parts[1], "Account.Id(1)", response),
|
|
250
|
257
|
Name = parts[2],
|
|
251
|
|
- Balance = decimal.Parse(parts[3]),
|
|
252
|
|
- Status = (Account.AccountStatus)int.Parse(parts[4]),
|
|
|
258
|
+ Balance = ParseDecimal(parts[3], "Account.Balance(3)", response),
|
|
|
259
|
+ Status = (Account.AccountStatus)ParseInt(parts[4], "Account.AccountStatus(4)", response),
|
|
253
|
260
|
Reference = parts[5],
|
|
254
|
261
|
Warehouse = new Warehouse()
|
|
255
|
262
|
{
|
|
256
|
|
- Id = int.Parse(parts[6]),
|
|
|
263
|
+ Id = ParseInt(parts[6], "Account.Warehouse.Id(6)", response),
|
|
257
|
264
|
Name = parts[7]
|
|
258
|
265
|
}
|
|
259
|
266
|
};
|
|
|
@@ -268,7 +275,7 @@ namespace MAX
|
|
268
|
275
|
var response = ExpectResponse(Decrypt(await ReadMessageAsync().ConfigureAwait(false)), "OK");
|
|
269
|
276
|
|
|
270
|
277
|
var parts = response.Split('|');
|
|
271
|
|
- var count = int.Parse(parts[1]);
|
|
|
278
|
+ var count = ParseInt(parts[1], "Products.Count(1)", response);
|
|
272
|
279
|
|
|
273
|
280
|
var catalogue = new ProductCatalogue();
|
|
274
|
281
|
|
|
|
@@ -280,7 +287,7 @@ namespace MAX
|
|
280
|
287
|
response = ExpectResponse(Decrypt(await ReadMessageAsync().ConfigureAwait(false)), "OK");
|
|
281
|
288
|
|
|
282
|
289
|
parts = response.Split('|');
|
|
283
|
|
- int networkId = int.Parse(parts[4]);
|
|
|
290
|
+ int networkId = ParseInt(parts[4], "Product.NetworkId(4)", response);
|
|
284
|
291
|
Network network;
|
|
285
|
292
|
if (! catalogue.NetworkMap.TryGetValue(networkId, out network))
|
|
286
|
293
|
{
|
|
|
@@ -289,17 +296,70 @@ namespace MAX
|
|
289
|
296
|
|
|
290
|
297
|
catalogue.AddProduct(
|
|
291
|
298
|
network: network,
|
|
292
|
|
- id: int.Parse(parts[1]),
|
|
293
|
|
- faceValue: decimal.Parse(parts[2]),
|
|
|
299
|
+ id: ParseInt(parts[1], "Product.Id(1)", response),
|
|
|
300
|
+ faceValue: ParseDecimal(parts[2], "Product.FaceValue(2)", response),
|
|
294
|
301
|
description: parts[3],
|
|
295
|
|
- voucherType: (Batch.Vouchertype)int.Parse(parts[6]),
|
|
296
|
|
- discountPercentage: decimal.Parse(parts[7])
|
|
|
302
|
+ voucherType: (Batch.Vouchertype)ParseInt(parts[6], "Product.VoucherType(6)", response),
|
|
|
303
|
+ discountPercentage: ParseDecimal(parts[7], "Product.DiscountPercentage(7)", response)
|
|
297
|
304
|
);
|
|
298
|
305
|
}
|
|
299
|
306
|
|
|
300
|
307
|
return catalogue;
|
|
301
|
308
|
}
|
|
302
|
309
|
|
|
|
310
|
+ private bool LogParseError(string value, string valueName, string valueType, string fullResponse)
|
|
|
311
|
+ {
|
|
|
312
|
+ _logger.LogError(
|
|
|
313
|
+ "Failed to parse value: valueType={0} valueName={1} value={2} fullResponse={3} {4}",
|
|
|
314
|
+ valueType,
|
|
|
315
|
+ valueName,
|
|
|
316
|
+ value,
|
|
|
317
|
+ fullResponse,
|
|
|
318
|
+ LoginCredentials.Format(_userId, _username, _vendorId, _serialNumber)
|
|
|
319
|
+ );
|
|
|
320
|
+ throw new Exception(String.Format("Invalid value for {0}", valueName));
|
|
|
321
|
+ }
|
|
|
322
|
+
|
|
|
323
|
+ private bool ParseBool(string value, string valueName, string fullResponse)
|
|
|
324
|
+ {
|
|
|
325
|
+ bool ret;
|
|
|
326
|
+ if (! bool.TryParse(value, out ret))
|
|
|
327
|
+ {
|
|
|
328
|
+ LogParseError(value, valueName, "bool", fullResponse);
|
|
|
329
|
+ }
|
|
|
330
|
+ return ret;
|
|
|
331
|
+ }
|
|
|
332
|
+
|
|
|
333
|
+ private DateTime ParseDateTime(string value, string valueName, string fullResponse)
|
|
|
334
|
+ {
|
|
|
335
|
+ DateTime ret;
|
|
|
336
|
+ if (!DateTime.TryParse(value, out ret))
|
|
|
337
|
+ {
|
|
|
338
|
+ LogParseError(value, valueName, "DateTime", fullResponse);
|
|
|
339
|
+ }
|
|
|
340
|
+ return ret;
|
|
|
341
|
+ }
|
|
|
342
|
+
|
|
|
343
|
+ private decimal ParseDecimal(string value, string valueName, string fullResponse)
|
|
|
344
|
+ {
|
|
|
345
|
+ decimal ret;
|
|
|
346
|
+ if (!decimal.TryParse(value, out ret))
|
|
|
347
|
+ {
|
|
|
348
|
+ LogParseError(value, valueName, "decimal", fullResponse);
|
|
|
349
|
+ }
|
|
|
350
|
+ return ret;
|
|
|
351
|
+ }
|
|
|
352
|
+
|
|
|
353
|
+ private int ParseInt(string value, string valueName, string fullResponse)
|
|
|
354
|
+ {
|
|
|
355
|
+ int ret;
|
|
|
356
|
+ if (!int.TryParse(value, out ret))
|
|
|
357
|
+ {
|
|
|
358
|
+ LogParseError(value, valueName, "int", fullResponse);
|
|
|
359
|
+ }
|
|
|
360
|
+ return ret;
|
|
|
361
|
+ }
|
|
|
362
|
+
|
|
303
|
363
|
public async Task<OrderResponse> PlaceOrderAsync(int accountId, Product product, int quantity,
|
|
304
|
364
|
string customerReference, string internalReference, Guid? orderGuid, byte[] key)
|
|
305
|
365
|
{
|
|
|
@@ -333,11 +393,11 @@ namespace MAX
|
|
333
|
393
|
{
|
|
334
|
394
|
Batch = new Batch()
|
|
335
|
395
|
{
|
|
336
|
|
- Id = int.Parse(parts[1]),
|
|
|
396
|
+ Id = ParseInt(parts[1], "Batch.Id(1)", response),
|
|
337
|
397
|
OrderReference = parts[2],
|
|
338
|
|
- RequestedQuantity = int.Parse(parts[3]),
|
|
339
|
|
- DeliveredQuantity = int.Parse(parts[4]),
|
|
340
|
|
- Cost = decimal.Parse(parts[5]),
|
|
|
398
|
+ RequestedQuantity = ParseInt(parts[3], "Batch.RequestQuantity(3)", response),
|
|
|
399
|
+ DeliveredQuantity = ParseInt(parts[4], "Batch.DeliveredQuantity(4)", response),
|
|
|
400
|
+ Cost = ParseDecimal(parts[5], "Batch.Cost(5)", response),
|
|
341
|
401
|
InternalReference = internalReference,
|
|
342
|
402
|
OrderGuid = orderGuid,
|
|
343
|
403
|
AccountId = accountId,
|
|
|
@@ -353,7 +413,7 @@ namespace MAX
|
|
353
|
413
|
OrderedById = _userId,
|
|
354
|
414
|
ReadyForDownload = false
|
|
355
|
415
|
},
|
|
356
|
|
- RemainingBalance = decimal.Parse(parts[6])
|
|
|
416
|
+ RemainingBalance = ParseDecimal(parts[6], "Batch.RemainingBalance(6)", response)
|
|
357
|
417
|
};
|
|
358
|
418
|
}
|
|
359
|
419
|
|
|
|
@@ -379,7 +439,12 @@ namespace MAX
|
|
379
|
439
|
{
|
|
380
|
440
|
throw new Exception("Invalid message size");
|
|
381
|
441
|
}
|
|
382
|
|
- return Encoding.ASCII.GetString(await ReadBytesAsync(size).ConfigureAwait(false));
|
|
|
442
|
+ var response = Encoding.ASCII.GetString(await ReadBytesAsync(size).ConfigureAwait(false));
|
|
|
443
|
+ if (_logResponses)
|
|
|
444
|
+ {
|
|
|
445
|
+ _logger.LogDebug("Response for {0}: {1}", LoginCredentials.Format(_userId, _username, _vendorId, _serialNumber), response);
|
|
|
446
|
+ }
|
|
|
447
|
+ return response;
|
|
383
|
448
|
}
|
|
384
|
449
|
|
|
385
|
450
|
public int ReceiveTimeout { get; set; }
|