RequisitionItemScanner.xaml.cs 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel.Design;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. using Comal.Classes;
  8. using InABox.Core;
  9. using InABox.Mobile;
  10. using Xamarin.Essentials;
  11. using Xamarin.Forms;
  12. using Xamarin.Forms.Xaml;
  13. using ZXing;
  14. namespace PRS.Mobile
  15. {
  16. public class RequisitionItemScannerHoldingMatchConverter : AbstractConverter<StockHoldingShell, Color>
  17. {
  18. public RequisitionItemScannerViewModel ViewModel { get; set; }
  19. protected override Color Convert(StockHoldingShell? value, object? parameter = null)
  20. {
  21. bool bMatched = false;
  22. if (value != null)
  23. {
  24. if (ViewModel.SaveArgs != null)
  25. bMatched = value.ID == ViewModel.SaveArgs.Holding.ID;
  26. else if (ViewModel.Item != null)
  27. {
  28. bMatched =
  29. value.LocationID == ViewModel.Item.LocationID
  30. && value.ProductID == ViewModel.Item.ProductID
  31. && value.StyleID == ViewModel.Item.StyleID
  32. && value.DimensionsUnitID == ViewModel.Item.DimensionsUnitID
  33. && value.DimensionsUnitSize == ViewModel.Item.DimensionsUnitSize;
  34. }
  35. }
  36. return bMatched ? Color.LightGreen : Color.LightYellow;
  37. }
  38. }
  39. public class RequisitionItemScannerViewModel : BindableObject
  40. {
  41. private RequisitionItemShell? _item;
  42. private RequisitionItemScannerSaveArgs? _saveArgs;
  43. public RequisitionItemShell? Item
  44. {
  45. get => _item;
  46. set
  47. {
  48. if (Equals(value, _item)) return;
  49. _item = value;
  50. OnPropertyChanged();
  51. OnPropertyChanged(nameof(HasItem));
  52. }
  53. }
  54. public bool HasItem => Item != null;
  55. public RequisitionItemScannerSaveArgs? SaveArgs
  56. {
  57. get => _saveArgs;
  58. set
  59. {
  60. if (Equals(value, _saveArgs)) return;
  61. _saveArgs = value;
  62. OnPropertyChanged();
  63. OnPropertyChanged(nameof(HasSaveArgs));
  64. }
  65. }
  66. public bool HasSaveArgs => SaveArgs != null;
  67. public StockHoldingModel Holdings { get; private set; }
  68. public String FoundItem { get; set; }
  69. public RequisitionItemScannerViewModel()
  70. {
  71. Holdings = new StockHoldingModel(App.Data, () => new Filter<StockHolding>().None());
  72. }
  73. }
  74. public class RequisitionItemScannerSaveArgs : EventArgs
  75. {
  76. public StockHoldingShell Holding { get; private set; }
  77. public Guid JobID { get; private set; }
  78. public Guid JobRequisitionItemID { get; private set; }
  79. public double Quantity { get; set; }
  80. public RequisitionItemScannerSaveArgs(StockHoldingShell holding, Guid jobid, Guid jobrequisitionitemid, double quantity)
  81. {
  82. Holding = holding;
  83. JobID = jobid;
  84. JobRequisitionItemID = jobrequisitionitemid;
  85. Quantity = quantity;
  86. }
  87. }
  88. public delegate void RequisitionItemScannerSaveEvent(object sender, RequisitionItemScannerSaveArgs args);
  89. [XamlCompilation(XamlCompilationOptions.Compile)]
  90. public partial class RequisitionItemScanner : MobilePage
  91. {
  92. public event RequisitionItemScannerSaveEvent? OnSave;
  93. public RequisitionItemScanner(RequisitionItemShell? item)
  94. {
  95. InitializeComponent();
  96. HoldingMatchConverter.ViewModel = _viewModel;
  97. _viewModel.Item = item;
  98. var options = new ZXing.Mobile.MobileBarcodeScanningOptions()
  99. {
  100. PossibleFormats = new List<ZXing.BarcodeFormat>() { ZXing.BarcodeFormat.QR_CODE },
  101. AutoRotate = false,
  102. TryInverted = true,
  103. TryHarder = true,
  104. };
  105. _scanView.Options = options;
  106. _scanView.IsAnalyzing = false;
  107. _scanView.IsScanning = true;
  108. if ((item?.ProductID ?? Guid.Empty) != Guid.Empty)
  109. SearchProductID(item!.ProductID);
  110. }
  111. protected override void OnAppearing()
  112. {
  113. base.OnAppearing();
  114. _scanView.IsAnalyzing = true;
  115. }
  116. protected override void OnDisappearing()
  117. {
  118. _scanView.IsAnalyzing = false;
  119. base.OnDisappearing();
  120. }
  121. private bool bProcessing = false;
  122. private void ScanView_OnScanResult(ZXing.Result result)
  123. {
  124. if (bProcessing)
  125. return;
  126. if (!Guid.TryParse(result.Text, out Guid id) || id == Guid.Empty)
  127. {
  128. _viewModel.Holdings.Filter =
  129. () => new Filter<StockHolding>().None();
  130. _viewModel.Holdings.Refresh(true);
  131. return;
  132. }
  133. bProcessing = true;
  134. Vibration.Vibrate();
  135. var producttask = Task.Run(() => { SearchProductID(id); });
  136. var locationtask = Task.Run(() => { SearchLocationID(id); });
  137. Task.WaitAll(producttask,locationtask);
  138. bProcessing = false;
  139. }
  140. private void SearchLocationID(Guid id)
  141. {
  142. App.Data.StockLocations.Refresh(false);
  143. var location = App.Data.StockLocations.FirstOrDefault(x => Guid.Equals(x.ID,id));
  144. if (location != null)
  145. {
  146. _viewModel.Holdings.Filter = () =>
  147. new Filter<StockHolding>(x => x.Location.ID).IsEqualTo(location.ID);
  148. _viewModel.Holdings.Refresh(true,
  149. () => Dispatcher.BeginInvokeOnMainThread(() =>
  150. {
  151. _items.ItemTemplate = _locationTemplate;
  152. _viewModel.FoundItem = location.Description;
  153. })
  154. );
  155. }
  156. }
  157. private void SearchProductID(Guid id)
  158. {
  159. App.Data.Products.Refresh(false);
  160. var product = App.Data.Products.FirstOrDefault(x => Guid.Equals(x.ID,id));
  161. if (product != null)
  162. {
  163. _viewModel.Holdings.Filter =
  164. () => new Filter<StockHolding>(x => x.Product.ID).IsEqualTo(product.ID);
  165. _viewModel.Holdings.Refresh(true,
  166. () => Dispatcher.BeginInvokeOnMainThread(() =>
  167. {
  168. _items.ItemTemplate = _productTemplate;
  169. _viewModel.FoundItem = product.Name;
  170. })
  171. );
  172. }
  173. }
  174. private void ProductSearch_Clicked(object sender, MobileButtonClickEventArgs args)
  175. {
  176. ShowPopup(() => SelectionView.Execute<ProductShell>(
  177. columns =>
  178. {
  179. columns.Add(new MobileGridTextColumn<ProductShell>()
  180. { Column = x => x.Code, Width = 100 });
  181. columns.Add(new MobileGridTextColumn<ProductShell>()
  182. { Column = x => x.Name, Width = GridLength.Star });
  183. },
  184. refresh => App.Data.Products.Refresh(false),
  185. products =>
  186. {
  187. SearchProductID(products.FirstOrDefault()?.ID ?? Guid.Empty);
  188. DismissPopup();
  189. })
  190. );
  191. }
  192. private void LocationSearch_Clicked(object sender, MobileButtonClickEventArgs args)
  193. {
  194. ShowPopup(() => SelectionView.Execute<StockLocationShell>(
  195. columns =>
  196. {
  197. columns.Add(new MobileGridTextColumn<StockLocationShell>()
  198. { Column = x => x.Code, Width = 100 });
  199. columns.Add(new MobileGridTextColumn<StockLocationShell>()
  200. { Column = x => x.Description, Width = GridLength.Star });
  201. },
  202. refresh => App.Data.StockLocations.Refresh(false),
  203. locations =>
  204. {
  205. SearchLocationID(locations.FirstOrDefault()?.ID ?? Guid.Empty);
  206. DismissPopup();
  207. })
  208. );
  209. }
  210. private void SelectFromHolding_Click(object sender, EventArgs e)
  211. {
  212. var holding = (sender as MobileCard)?.BindingContext as StockHoldingShell;
  213. if (holding == null)
  214. return;
  215. ShowPopup(() =>
  216. {
  217. var editor = new SelectFromHoldingView(holding, _viewModel.Item?.Quantity ?? 0.0F);
  218. editor.OnSave += (o, args) =>
  219. {
  220. if (!_viewModel.HasItem)
  221. OnSave?.Invoke(this, args);
  222. else
  223. _viewModel.SaveArgs = args;
  224. _viewModel.Holdings.Refresh(false);
  225. DismissPopup();
  226. };
  227. editor.OnCancel += (o, args) => DismissPopup();
  228. return editor;
  229. },
  230. new PopupManagerConfiguration()
  231. {
  232. RequestedHeight = Math.Min(700,500 + (holding.Allocations.Length * 55))
  233. });
  234. }
  235. private void SaveItem_Clicked(object sender, MobileMenuButtonClickedEventArgs args)
  236. {
  237. if (_viewModel.HasSaveArgs)
  238. {
  239. OnSave?.Invoke(this, _viewModel.SaveArgs);
  240. Navigation.PopAsync();
  241. }
  242. }
  243. }
  244. }