ForeignCurrencyGrid.cs 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. using System;
  2. using System.Linq;
  3. using System.Threading.Tasks;
  4. using System.Windows;
  5. using System.Windows.Controls;
  6. using System.Windows.Media.Imaging;
  7. using Comal.Classes;
  8. using InABox.Clients;
  9. using InABox.Configuration;
  10. using InABox.Core;
  11. using InABox.DynamicGrid;
  12. using InABox.Wpf;
  13. using InABox.WPF;
  14. using OpenExchangeRates;
  15. using Exception = System.Exception;
  16. namespace PRSDesktop;
  17. public class ForeignCurrencyGridSettings : BaseObject, IGlobalConfigurationSettings
  18. {
  19. [TextBoxEditor]
  20. [EditorSequence(1)]
  21. public string ApiKey { get; set; } = "";
  22. [TextBoxEditor]
  23. [EditorSequence(2)]
  24. public string BaseCurrency { get; set; } = "AUD";
  25. }
  26. public class ForeignCurrencyGridPreferences : BaseObject, IUserConfigurationSettings
  27. {
  28. public DynamicGridSelectedFilterSettings Filters { get; set; } = new();
  29. }
  30. public class ForeignCurrencyGrid : DynamicDataGrid<ForeignCurrency>
  31. {
  32. private readonly BitmapImage tick = PRSDesktop.Resources.tick.AsBitmapImage();
  33. private readonly Button update;
  34. private ForeignCurrencyGridSettings _settings;
  35. private ForeignCurrencyGridPreferences _preferences;
  36. public ForeignCurrencyGrid()
  37. {
  38. Task[] tasks = {
  39. Task.Run(() =>
  40. {
  41. _settings = new GlobalConfiguration<ForeignCurrencyGridSettings>().Load();
  42. }),
  43. Task.Run(() =>
  44. {
  45. _preferences = new UserConfiguration<ForeignCurrencyGridPreferences>().Load();
  46. }),
  47. };
  48. Task.WaitAll(tasks);
  49. FilterComponent.SetSettings(_preferences!.Filters, false);
  50. FilterComponent.OnFiltersSelected += FilterComponent_OnFilterSelected;
  51. HiddenColumns.Add(x=>x.Code);
  52. HiddenColumns.Add(x=>x.Description);
  53. HiddenColumns.Add(x=>x.Identifier);
  54. HiddenColumns.Add(x=>x.Active);
  55. ActionColumns.Add(new DynamicTickColumn<ForeignCurrency,bool>(x=>x.Active, tick, tick, null, ToggleActive));
  56. AddButton(null, PRSDesktop.Resources.autoupdate.AsBitmapImage(), UpdateSettings);
  57. update = AddButton("Update", PRSDesktop.Resources.payment.AsBitmapImage(), UpdateExchangeRates);
  58. update.Visibility = !string.IsNullOrEmpty(_settings!.ApiKey) ? Visibility.Visible : Visibility.Collapsed;
  59. }
  60. private void FilterComponent_OnFilterSelected(DynamicGridSelectedFilterSettings settings)
  61. {
  62. _preferences.Filters = settings;
  63. new UserConfiguration<ForeignCurrencyGridPreferences>().Save(_preferences);
  64. }
  65. private bool UpdateSettings(Button button, CoreRow[] rows)
  66. {
  67. if (DynamicGridUtils.EditObject(_settings))
  68. {
  69. new GlobalConfiguration<ForeignCurrencyGridSettings>().Save(_settings);
  70. update.Visibility = !string.IsNullOrEmpty(_settings.ApiKey) ? Visibility.Visible : Visibility.Collapsed;
  71. }
  72. return false;
  73. }
  74. private bool ToggleActive(CoreRow? row)
  75. {
  76. if (row == null)
  77. return false;
  78. var fc = row.ToObject<ForeignCurrency>();
  79. fc.Active = !fc.Active;
  80. new Client<ForeignCurrency>().Save(fc, $"Set to {(fc.Active ? "Active" : "InActive")} ");
  81. return true;
  82. }
  83. protected override BaseEditor? GetEditor(object item, DynamicGridColumn column)
  84. {
  85. BaseEditor? editor;
  86. if (column.ColumnName.Equals(nameof(ForeignCurrency.Identifier)) && string.IsNullOrWhiteSpace(_settings.ApiKey))
  87. {
  88. editor = base.GetEditor(item, column)?.CloneEditor() ?? new NullEditor();
  89. editor.Editable = Editable.Hidden;
  90. editor.Visible = Visible.Hidden;
  91. }
  92. else
  93. editor = base.GetEditor(item, column);
  94. return editor;
  95. }
  96. private bool UpdateExchangeRates(Button button, CoreRow[] rows)
  97. {
  98. try
  99. {
  100. Progress.ShowModal("Retrieving Currencies", progress =>
  101. {
  102. var data = new Client<ForeignCurrency>().Query().ToObjects<ForeignCurrency>().ToList();
  103. progress.Report("Updating Data");
  104. using (var client = new OpenExchangeRatesClient("ff16587e173b43788a34c035a2c53edd"))
  105. {
  106. var currencies = client.GetCurrenciesAsync().Result;
  107. if (currencies == null)
  108. throw new Exception("No Currencies Returned");
  109. var rates = client.GetLatestRatesAsync().Result;
  110. if (rates == null)
  111. throw new Exception("No Rates Returned");
  112. if (!rates.Rates.TryGetValue("AUD", out decimal aud_decimal))
  113. throw new Exception("Cannot Find AUD rate");
  114. var usd_aud = Convert.ToDouble(aud_decimal);
  115. if (usd_aud.IsEffectivelyEqual(0.0))
  116. throw new Exception("USD -> AUD conversion return 0.00");
  117. foreach (var rate in rates.Rates)
  118. {
  119. var foreign_usd = Convert.ToDouble(rate.Value);
  120. var items = data.Where(x => String.Equals(x.Identifier, rate.Key)).ToList();
  121. if (!items.Any())
  122. {
  123. if (currencies.TryGetValue(rate.Key, out string? description))
  124. {
  125. var newitem = new ForeignCurrency()
  126. {
  127. Code = rate.Key,
  128. Description = description,
  129. Identifier = rate.Key,
  130. Active = false
  131. };
  132. items.Add(newitem);
  133. data.Add(newitem);
  134. }
  135. }
  136. foreach (var item in items)
  137. item.ExchangeRate = foreign_usd / usd_aud;
  138. }
  139. }
  140. var updates = data.Where(x => x.IsChanged()).ToArray();
  141. if (updates.Any())
  142. {
  143. progress.Report($"Updating {updates.Length} records...");
  144. new Client<ForeignCurrency>().Save(updates, "Updated from openexchangerates.org");
  145. }
  146. });
  147. }
  148. catch (Exception e)
  149. {
  150. MessageWindow.ShowError("Error retrieving data!", e);
  151. }
  152. return true;
  153. }
  154. }