StockTakeEdit.xaml.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. using Comal.Classes;
  2. using InABox.Clients;
  3. using InABox.Core;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.IO;
  7. using System.Linq;
  8. using System.Linq.Expressions;
  9. using System.Text;
  10. using System.Threading.Tasks;
  11. using System.Transactions;
  12. using InABox.Mobile;
  13. using Syncfusion.SfPdfViewer.XForms;
  14. using Syncfusion.XForms.PopupLayout;
  15. using Xamarin.Forms;
  16. using Xamarin.Forms.Xaml;
  17. using XF.Material.Forms.UI.Dialogs;
  18. namespace PRS.Mobile
  19. {
  20. [XamlCompilation(XamlCompilationOptions.Compile)]
  21. public partial class StockTakeEdit
  22. {
  23. public event StockTransactionSavedEvent TransactionSaved;
  24. public StockTakeEdit(StockTransaction transaction)
  25. {
  26. InitializeComponent();
  27. ViewModel.Transaction = transaction;
  28. Quantity.TextChanged += InputView_OnTextChanged;
  29. }
  30. private async void _tick_OnClicked(object sender, MobileMenuButtonClickedEventArgs args)
  31. {
  32. if (ViewModel.Transaction.ProductID == Guid.Empty)
  33. {
  34. await DisplayAlert("ERROR", "Please select a Product first.", "OK");
  35. return;
  36. }
  37. if (ViewModel.IsNew && ViewModel.Transaction.Quantity.IsEffectivelyEqual(0.0))
  38. {
  39. await DisplayAlert("ERROR", "New Holdings must have a quantity!", "OK");
  40. return;
  41. }
  42. if (ViewModel.Transaction.ImageID == Guid.Empty)
  43. {
  44. if (await DisplayAlert("No Image","There is no image attached to this product.\nSave anyway?","Yes","No") == false)
  45. return;
  46. }
  47. TransactionSaved?.Invoke(this, new StockTransactionSavedArgs(ViewModel.Transaction));
  48. Navigation.PopAsync();
  49. }
  50. private void IncreaseQty_Clicked(object sender, MobileButtonClickEventArgs args)
  51. {
  52. var alloc = ViewModel.Transaction.Allocations?.FirstOrDefault();
  53. if (alloc != null)
  54. alloc.Quantity = alloc.Quantity + 1;
  55. ViewModel.Transaction.RefreshQuantity();
  56. }
  57. private void DecreaseQty_Clicked(object sender, MobileButtonClickEventArgs args)
  58. {
  59. var alloc = ViewModel.Transaction.Allocations?.FirstOrDefault();
  60. if (alloc != null)
  61. alloc.Quantity = Math.Max(0, alloc.Quantity - 1);
  62. ViewModel.Transaction.RefreshQuantity();
  63. }
  64. private void SelectStyle_Clicked(object sender, MobileButtonClickEventArgs args)
  65. {
  66. ShowPopup(() =>
  67. SelectionView.Execute<ProductStyleShell>(
  68. columns =>
  69. {
  70. columns.Add(new MobileGridTextColumn<ProductStyleShell>()
  71. { Column = x => x.Code, Width = GridLength.Auto });
  72. columns.Add(new MobileGridTextColumn<ProductStyleShell>()
  73. { Column = x => x.Description, Width = GridLength.Star });
  74. },
  75. refresh => App.Data.ProductStyles.Refresh(false),
  76. styles =>
  77. {
  78. ViewModel.Transaction.Target.StyleID = styles.FirstOrDefault()?.ID ?? Guid.Empty;
  79. ViewModel.Transaction.Target.StyleCode = styles.FirstOrDefault()?.Code ?? string.Empty;
  80. ViewModel.Transaction.Target.StyleDescription = styles.FirstOrDefault()?.Description ?? string.Empty;
  81. DismissPopup();
  82. })
  83. );
  84. }
  85. private void SelectJob_Clicked(object sender, MobileButtonClickEventArgs args)
  86. {
  87. ShowPopup(() =>
  88. SelectionView.Execute<JobShell>(
  89. columns =>
  90. {
  91. columns.Add(new MobileGridTextColumn<JobShell>()
  92. { Column = x => x.JobNumber, Width = GridLength.Auto });
  93. columns.Add(new MobileGridTextColumn<JobShell>()
  94. { Column = x => x.Name, Width = GridLength.Star });
  95. },
  96. refresh => App.Data.Jobs.Refresh(false),
  97. jobs =>
  98. {
  99. ViewModel.Transaction.Target.JobID = jobs.FirstOrDefault()?.ID ?? Guid.Empty;
  100. ViewModel.Transaction.Target.JobNumber = jobs.FirstOrDefault()?.JobNumber ?? string.Empty;
  101. ViewModel.Transaction.Target.JobName = jobs.FirstOrDefault()?.Name ?? string.Empty;
  102. DismissPopup();
  103. })
  104. );
  105. }
  106. private void SelectProduct_Clicked(object sender, MobileButtonClickEventArgs args)
  107. {
  108. ShowPopup(() =>
  109. SelectionView.Execute<ProductShell>(
  110. columns =>
  111. {
  112. columns.Add(new MobileGridTextColumn<ProductShell>()
  113. { Column = x => x.Code, Width = 200 });
  114. columns.Add(new MobileGridTextColumn<ProductShell>()
  115. { Column = x => x.Name, Width = GridLength.Star });
  116. },
  117. refresh => App.Data.Products.Refresh(false),
  118. products =>
  119. {
  120. ViewModel.Transaction.ProductID = products.FirstOrDefault()?.ID ?? Guid.Empty;
  121. ViewModel.Transaction.ProductCode = products.FirstOrDefault()?.Code ?? string.Empty;
  122. ViewModel.Transaction.ProductName = products.FirstOrDefault()?.Name ?? string.Empty;
  123. if (ViewModel.Transaction.Source.Shell != null)
  124. {
  125. ViewModel.Transaction.Source.Shell.DimensionsHasLength =
  126. products.FirstOrDefault()?.DimensionsUnit?.HasLength ?? false;
  127. ViewModel.Transaction.Source.Shell.DimensionsHasWidth =
  128. products.FirstOrDefault()?.DimensionsUnit?.HasWidth ?? false;
  129. ViewModel.Transaction.Source.Shell.DimensionsHasHeight =
  130. products.FirstOrDefault()?.DimensionsUnit?.HasHeight ?? false;
  131. ViewModel.Transaction.Source.Shell.DimensionsHasQuantity =
  132. products.FirstOrDefault()?.DimensionsUnit?.HasQuantity ?? false;
  133. ViewModel.Transaction.Source.Shell.DimensionsHasWeight =
  134. products.FirstOrDefault()?.DimensionsUnit?.HasWeight ?? false;
  135. }
  136. ViewModel.Transaction.DimensionsUnitID = products.FirstOrDefault()?.DimensionsUnitID ?? Guid.Empty;
  137. ViewModel.Transaction.DimensionsHeight = products.FirstOrDefault()?.DimensionsHeight ?? 0.0;
  138. ViewModel.Transaction.DimensionsWidth = products.FirstOrDefault()?.DimensionsWidth ?? 0.0;
  139. ViewModel.Transaction.DimensionsLength = products.FirstOrDefault()?.DimensionsLength ?? 0.0;
  140. ViewModel.Transaction.DimensionsQuantity = products.FirstOrDefault()?.DimensionsQuantity ?? 0.0;
  141. ViewModel.Transaction.DimensionsValue = products.FirstOrDefault()?.DimensionsValue ?? 0.0;
  142. ViewModel.Transaction.DimensionsUnitSize = products.FirstOrDefault()?.DimensionsUnitSize ?? string.Empty;
  143. ViewModel.Transaction.Cost = products.FirstOrDefault()?.AverageCost ?? 0.0;
  144. ViewModel.Transaction.ImageID = products.FirstOrDefault()?.ImageID ??Guid.Empty;
  145. if (ViewModel.Transaction.ImageID != Guid.Empty && products.FirstOrDefault()?.Parent != null)
  146. {
  147. if (products.FirstOrDefault()!.Parent.Images.TryGetValue(ViewModel.Transaction.ImageID, out var data))
  148. ViewModel.Transaction.Image = data;
  149. else
  150. {
  151. DocumentModel docmodel = new DocumentModel(App.Data,
  152. () => new Filter<Document>(x => x.ID).IsEqualTo(ViewModel.Transaction.ImageID));
  153. docmodel.Refresh(true);
  154. ViewModel.Transaction.Image = docmodel.Items.FirstOrDefault()?.Data ?? new byte[] { };
  155. }
  156. }
  157. DismissPopup();
  158. })
  159. );
  160. }
  161. private void InputView_OnTextChanged(object sender, TextChangedEventArgs e)
  162. {
  163. if (!Quantity.IsVisible)
  164. return;
  165. if (sender is Entry entry)
  166. {
  167. if (double.TryParse(e.NewTextValue, out double qty))
  168. {
  169. var alloc = ViewModel.Transaction.Allocations?.FirstOrDefault();
  170. if (alloc != null)
  171. alloc.Quantity = qty;
  172. }
  173. else
  174. entry.Text = e.OldTextValue;
  175. ViewModel.Transaction.RefreshQuantity();
  176. }
  177. }
  178. private async void Delete_Clicked(object sender, MobileButtonClickEventArgs args)
  179. {
  180. if (await DisplayAlert("Confirm", "Are you sure you wish to delete holding?", "Yes", "No") == true)
  181. {
  182. var holding = ViewModel.Transaction?.Source?.Shell;
  183. if (holding?.Parent != null)
  184. {
  185. holding.Parent.Items.Remove(holding);
  186. holding.Parent.Transactions.Remove(ViewModel.Transaction);
  187. }
  188. Navigation.PopAsync();
  189. }
  190. }
  191. private async Task AddImage<T, TOptions>(TOptions options)
  192. where T : MobileImageSource<T, TOptions>
  193. where TOptions : MobileImageOptions<T>, new()
  194. {
  195. App.Data.Products.Refresh(false);
  196. var product = App.Data.Products.FirstOrDefault(x => x.ID == ViewModel.Transaction.ProductID);
  197. if (product != null)
  198. {
  199. MobileDocument file = null;
  200. try
  201. {
  202. file = await MobileDocument.From<T>(options);
  203. }
  204. catch (Exception e)
  205. {
  206. await DisplayAlert("ERROR", e.Message, "OK");
  207. }
  208. if (file != null)
  209. {
  210. using (await MaterialDialog.Instance.LoadingDialogAsync("Saving Image"))
  211. {
  212. Document doc = new Document()
  213. {
  214. FileName = file.FileName,
  215. Data = file.Data,
  216. CRC = CoreUtils.CalculateCRC(file.Data),
  217. TimeStamp = DateTime.Now
  218. };
  219. new Client<Document>().Save(doc, "Created on Mobile Device");
  220. product.ImageID = doc.ID;
  221. product.Save("Photo Updated from Mobile Device");
  222. product.Parent.Images[doc.ID] = file.Data;
  223. ViewModel.Transaction.ImageID = doc.ID;
  224. ViewModel.Transaction.Image = file.Data;
  225. }
  226. }
  227. }
  228. else
  229. DisplayAlert("Error","Please select a Product first!","OK");
  230. }
  231. private async void _imagesphoto_Clicked(object sender, EventArgs e)
  232. {
  233. if (ViewModel.Transaction.ImageID != Guid.Empty)
  234. {
  235. if (await DisplayAlert("Confirm", "Are you sure you wish to replace the existing image?", "Yes",
  236. "No") == false)
  237. return;
  238. }
  239. await AddImage<MobileDocumentCameraSource, MobileDocumentCameraOptions>(
  240. PhotoUtils.CreateCameraOptions());
  241. }
  242. private async void _imageslibrary_Clicked(object sender, EventArgs e)
  243. {
  244. if (ViewModel.Transaction.ImageID != Guid.Empty)
  245. {
  246. if (await DisplayAlert("Confirm", "Are you sure you wish to replace the existing image?", "Yes",
  247. "No") == false)
  248. return;
  249. }
  250. await AddImage<MobileDocumentPhotoLibrarySource, MobileDocumentPhotoLibraryOptions>(
  251. PhotoUtils.CreatePhotoLibraryOptions());
  252. }
  253. private void SelectUnitSize_Clicked(object sender, MobileButtonClickEventArgs args)
  254. {
  255. var editor = new DimensionsEditor() { Transaction = ViewModel.Transaction };
  256. editor.CloseRequested += (o, eventArgs) => PopupManager.DismissPopup();
  257. ShowPopup(
  258. ()=> editor,
  259. new PopupManagerConfiguration()
  260. {
  261. SizeMode = AutoSizeMode.Height,
  262. Modal = true,
  263. }
  264. );
  265. }
  266. private void SelectAllocations_Clicked(object sender, MobileButtonClickEventArgs args)
  267. {
  268. var editor = new AllocationsEditor() { Transaction = ViewModel.Transaction };
  269. editor.CloseRequested += (o, eventArgs) => PopupManager.DismissPopup();
  270. ShowPopup(
  271. () => editor,
  272. new PopupManagerConfiguration()
  273. {
  274. SizeMode = AutoSizeMode.Height,
  275. Modal = true
  276. }
  277. );
  278. }
  279. }
  280. }