BaseIntegrationGrid.cs 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. using System;
  2. using System.Collections.Generic;
  3. using Comal.Classes;
  4. using InABox.Core;
  5. using InABox.DynamicGrid;
  6. using System.Linq;
  7. using System.Linq.Expressions;
  8. using System.Windows;
  9. using System.Windows.Controls;
  10. using System.Windows.Input;
  11. using System.Windows.Media.Imaging;
  12. using AutoProperties;
  13. using Comal.Classes.SecurityDescriptors;
  14. using InABox.Clients;
  15. using InABox.Configuration;
  16. using InABox.Wpf;
  17. using InABox.WPF;
  18. namespace PRSDesktop.Integrations.Common;
  19. public class IntegrationGridCreateEntityArgs<TEntity, TType>(TEntity entity, TType mapping)
  20. {
  21. public TEntity Entity { get; private set; } = entity;
  22. public TType Mapping { get; private set; } = mapping;
  23. }
  24. public abstract class BaseIntegrationGrid<TType, TEntity,TLink> : DynamicItemsListGrid<TType>
  25. where TType : BaseIntegrationSource<TEntity,TLink>, new()
  26. where TEntity : Entity, IRemotable, IPersistent, new()
  27. where TLink : EntityLink<TEntity>
  28. {
  29. private static readonly DependencyProperty SourceTypeProperty = DependencyProperty.Register(
  30. nameof(SourceType),
  31. typeof(IntegrationSourceType),
  32. typeof(BaseIntegrationGrid<TType, TEntity,TLink>)
  33. );
  34. public IntegrationSourceType SourceType
  35. {
  36. get => (IntegrationSourceType)GetValue(SourceTypeProperty);
  37. set => SetValue(SourceTypeProperty, value);
  38. }
  39. private static readonly DependencyProperty CreateEntityProperty = DependencyProperty.Register(
  40. nameof(CreateEntity),
  41. typeof(ICommand),
  42. typeof(BaseIntegrationGrid<TType, TEntity,TLink>)
  43. );
  44. public ICommand? CreateEntity
  45. {
  46. get => GetValue(CreateEntityProperty) as ICommand;
  47. set => SetValue(CreateEntityProperty, value);
  48. }
  49. private static readonly DependencyProperty AfterCreateEntityProperty = DependencyProperty.Register(
  50. nameof(AfterCreateEntity),
  51. typeof(ICommand),
  52. typeof(BaseIntegrationGrid<TType, TEntity,TLink>)
  53. );
  54. public ICommand? AfterCreateEntity
  55. {
  56. get => GetValue(AfterCreateEntityProperty) as ICommand;
  57. set => SetValue(AfterCreateEntityProperty, value);
  58. }
  59. private DynamicImageColumn _createordelete;
  60. protected override void Init()
  61. {
  62. base.Init();
  63. var required = Columns.Required<TType>();
  64. foreach (var req in required)
  65. HiddenColumns.Add(req.Property);
  66. HiddenColumns.Add(x => x.DirectMatch);
  67. AddButton("Create All", PRSDesktop.Resources.plus.AsBitmapImage(), CreateAll);
  68. _createordelete = new DynamicImageColumn(CreateImage, CreateOrDeleteOne);
  69. ActionColumns.Add(_createordelete);
  70. }
  71. private BitmapImage? CreateImage(CoreRow? row)
  72. {
  73. return row == null
  74. ? PRSDesktop.Resources.plus.AsBitmapImage()
  75. : row.Get<TType, Guid>(x => x.Entity.ID) == Guid.Empty
  76. ? PRSDesktop.Resources.plus.AsBitmapImage()
  77. : row.Get<TType,bool>(x=>x.DirectMatch)
  78. ? PRSDesktop.Resources.locked.AsBitmapImage()
  79. : PRSDesktop.Resources.minus.AsBitmapImage();
  80. }
  81. private bool CreateOrDeleteOne(CoreRow? row)
  82. {
  83. if (row == null)
  84. return false;
  85. if (row.Get<TType, bool>(x => x.DirectMatch) && row.Get<TType,Guid>(x=>x.Entity.ID) != Guid.Empty)
  86. return false;
  87. var item = Items[row.Index];
  88. if (item.Entity.ID == Guid.Empty)
  89. CreateItem(item);
  90. else
  91. DeleteItem(item);
  92. Refresh(false,true);
  93. DoChanged();
  94. return true;
  95. }
  96. private bool CreateAll(Button button, CoreRow[] rows)
  97. {
  98. foreach (var item in Items.Where(x => !string.IsNullOrWhiteSpace(x.Code) && x.Entity.ID == Guid.Empty))
  99. CreateItem(item);
  100. DoChanged();
  101. return true;
  102. }
  103. protected abstract Expression<Func<TEntity,object?>> EntityCode { get; }
  104. private void CreateItem(TType item)
  105. {
  106. var lookup = Client.Query<TEntity>(
  107. new Filter<TEntity>(EntityCode).IsEqualTo(item.Code),
  108. Columns.Required<TEntity>().Add(EntityCode)
  109. ).ToArray<TEntity>();
  110. if (lookup.Any())
  111. {
  112. item.Source = SourceType;
  113. item.Entity.CopyFrom(lookup.First());
  114. item.DirectMatch = true;
  115. return;
  116. }
  117. var entity = new TEntity();
  118. var args = new IntegrationGridCreateEntityArgs<TEntity,TType>(entity,item);
  119. try
  120. {
  121. CreateEntity?.Execute(args);
  122. new Client<TEntity>().Save(entity, "Created by Integration Window");
  123. item.Source = SourceType;
  124. item.Entity.CopyFrom(entity);
  125. item.DirectMatch = true;
  126. try
  127. {
  128. var args2 = new IntegrationGridCreateEntityArgs<TEntity,TType>(entity,item);
  129. AfterCreateEntity?.Execute(args2);
  130. }
  131. catch (Exception e)
  132. {
  133. MessageWindow.ShowError(e.Message, e, "AfterCreate Error");
  134. Logger.Send(LogType.Error,"",$"Exception in AfterCreateEntity: {e.Message}\n{e.StackTrace}");
  135. }
  136. }
  137. catch (Exception e)
  138. {
  139. MessageWindow.ShowError(e.Message, e, "CreateItem Error");
  140. Logger.Send(LogType.Error,"",$"Exception in CreateEntity: {e.Message}\n{e.StackTrace}");
  141. }
  142. }
  143. private void DeleteItem(TType item)
  144. {
  145. MultiQuery query = new();
  146. query.Add(
  147. new Filter<TEntity>(EntityCode).IsEqualTo(item.Code),
  148. Columns.Required<TEntity>().Add(x => x.ID).Add(EntityCode)
  149. );
  150. query.Add(
  151. new Filter<TType>(x=>x.Entity.ID).IsEqualTo(item.Entity.ID).And(x=>x.Code).IsEqualTo(item.Code),
  152. Columns.Required<TType>().Add(x=>x.ID)
  153. );
  154. query.Query();
  155. var mappings = query.Get<TType>().ToArray<TType>();
  156. if (mappings.Any())
  157. {
  158. item.ID = Guid.Empty;
  159. Client.Delete(mappings, "Removed By AWG Mapping Window");
  160. }
  161. var entities = query.Get<TEntity>().ToArray<TEntity>();
  162. if (entities.Any())
  163. {
  164. item.Entity.CopyFrom(entities.First());
  165. item.DirectMatch = true;
  166. }
  167. else
  168. {
  169. item.Entity.CopyFrom(new TEntity());
  170. item.DirectMatch = false;
  171. }
  172. item.CommitChanges();
  173. SaveItem(item);
  174. DoChanged();
  175. }
  176. protected override void DoReconfigure(DynamicGridOptions options)
  177. {
  178. base.DoReconfigure(options);
  179. options.AddRows = false;
  180. options.EditRows = false;
  181. options.DeleteRows = false;
  182. options.FilterRows = true;
  183. options.HideDatabaseFilters = true;
  184. options.DirectEdit = true;
  185. options.HideDirectEditButton = true;
  186. options.SelectColumns = true;
  187. options.MultiSelect = true;
  188. options.RecordCount = true;
  189. }
  190. protected override DynamicGridColumns LoadColumns()
  191. {
  192. var result = new DynamicGridColumns();
  193. result.Add<TType>(x => x.Code, 250, "Code");
  194. result.Add<TType>(x => x.Description, 0, "Description");
  195. result.Add<TType>(x => x.Entity.ID, 200, typeof(TEntity).GetCaption());
  196. return result;
  197. }
  198. protected override BaseEditor CustomiseEditor(DynamicGridColumn column, BaseEditor editor)
  199. {
  200. editor = base.CustomiseEditor(column, editor);
  201. if (String.Equals(CoreUtils.GetFullPropertyName<TType, string>(x => x.Code, "."), column.ColumnName))
  202. editor.Editable = Editable.Disabled;
  203. else if (String.Equals(CoreUtils.GetFullPropertyName<TType, string>(x => x.Description, "."), column.ColumnName))
  204. editor.Editable = Editable.Disabled;
  205. else if (String.Equals(CoreUtils.GetFullPropertyName<TType, Guid>(x => x.Entity.ID, "."), column.ColumnName))
  206. {
  207. var popup = new CodePopupEditor(typeof(TEntity)) { CodeColumn = "Code", CanAdd = Security.CanEdit<TEntity>() };
  208. var required = Columns.Required<TEntity>();
  209. foreach (var req in required)
  210. popup.OtherColumns[$"Entity.{req.Property}"] = req.Property;
  211. popup.OnCreateItem += o =>
  212. {
  213. };
  214. editor = popup;
  215. }
  216. // else if(new Column<TType>(x => x.Entity.ID).IsEqualTo(column.ColumnName) && editor is CodePopupEditor popup)
  217. // popup.CanAdd = Security.CanEdit<TEntity>();
  218. return editor;
  219. }
  220. protected override void OnAfterEditorValueChanged(DynamicEditorGrid? grid, TType[] items, AfterEditorValueChangedArgs args,
  221. Dictionary<string, object?> changes)
  222. {
  223. base.OnAfterEditorValueChanged(grid, items, args, changes);
  224. //DoChanged();
  225. }
  226. public override void SaveItem(TType item)
  227. {
  228. var code = CoreUtils.GetPropertyValue(item.Entity, CoreUtils.GetFullPropertyName(EntityCode, "."))?.ToString() ?? "";
  229. item.DirectMatch = Equals(code, item.Code);
  230. if (!Equals(item.ID, Guid.Empty) && (Equals(code, item.Code) || string.IsNullOrWhiteSpace(code)))
  231. {
  232. Client.Delete(item, "Removed By AWG Mapping Window");
  233. item.ID = Guid.Empty;
  234. item.CommitChanges();
  235. return;
  236. }
  237. if (!string.IsNullOrWhiteSpace(code) && !Equals(code,item.Code))
  238. Client.Save(item,"Updated by Integration Window ");
  239. base.SaveItem(item);
  240. //DoChanged();
  241. }
  242. }