StockTakeEdit.xaml.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  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. {
  110. bool force = false;
  111. return SelectionView.Execute<ProductShell>(
  112. columns =>
  113. {
  114. columns.Add(new MobileGridTextColumn<ProductShell>()
  115. { Column = x => x.Code, Width = 200 });
  116. columns.Add(new MobileGridTextColumn<ProductShell>()
  117. { Column = x => x.Name, Width = GridLength.Star });
  118. },
  119. refresh =>
  120. {
  121. var result = App.Data.Products.Refresh(force);
  122. force = true;
  123. return result;
  124. },
  125. products =>
  126. {
  127. ViewModel.Transaction.ProductID = products.FirstOrDefault()?.ID ?? Guid.Empty;
  128. ViewModel.Transaction.ProductCode = products.FirstOrDefault()?.Code ?? string.Empty;
  129. ViewModel.Transaction.ProductName = products.FirstOrDefault()?.Name ?? string.Empty;
  130. if (ViewModel.Transaction.Source.Shell != null)
  131. {
  132. ViewModel.Transaction.Source.Shell.DimensionsHasLength =
  133. products.FirstOrDefault()?.DimensionsUnit?.HasLength ?? false;
  134. ViewModel.Transaction.Source.Shell.DimensionsHasWidth =
  135. products.FirstOrDefault()?.DimensionsUnit?.HasWidth ?? false;
  136. ViewModel.Transaction.Source.Shell.DimensionsHasHeight =
  137. products.FirstOrDefault()?.DimensionsUnit?.HasHeight ?? false;
  138. ViewModel.Transaction.Source.Shell.DimensionsHasQuantity =
  139. products.FirstOrDefault()?.DimensionsUnit?.HasQuantity ?? false;
  140. ViewModel.Transaction.Source.Shell.DimensionsHasWeight =
  141. products.FirstOrDefault()?.DimensionsUnit?.HasWeight ?? false;
  142. }
  143. ViewModel.Transaction.DimensionsUnitID =
  144. products.FirstOrDefault()?.DimensionsUnitID ?? Guid.Empty;
  145. ViewModel.Transaction.DimensionsHeight = products.FirstOrDefault()?.DimensionsHeight ?? 0.0;
  146. ViewModel.Transaction.DimensionsWidth = products.FirstOrDefault()?.DimensionsWidth ?? 0.0;
  147. ViewModel.Transaction.DimensionsLength = products.FirstOrDefault()?.DimensionsLength ?? 0.0;
  148. ViewModel.Transaction.DimensionsQuantity =
  149. products.FirstOrDefault()?.DimensionsQuantity ?? 0.0;
  150. ViewModel.Transaction.DimensionsValue = products.FirstOrDefault()?.DimensionsValue ?? 0.0;
  151. ViewModel.Transaction.DimensionsUnitSize =
  152. products.FirstOrDefault()?.DimensionsUnitSize ?? string.Empty;
  153. ViewModel.Transaction.Cost = products.FirstOrDefault()?.AverageCost ?? 0.0;
  154. ViewModel.Transaction.ImageID = products.FirstOrDefault()?.ImageID ?? Guid.Empty;
  155. if (ViewModel.Transaction.ImageID != Guid.Empty &&
  156. products.FirstOrDefault()?.Parent != null)
  157. {
  158. if (products.FirstOrDefault()!.Parent.Images.TryGetValue(ViewModel.Transaction.ImageID,
  159. out var data))
  160. ViewModel.Transaction.Image = data;
  161. else
  162. {
  163. DocumentModel docmodel = new DocumentModel(App.Data,
  164. () => new Filter<Document>(x => x.ID).IsEqualTo(ViewModel.Transaction.ImageID));
  165. docmodel.Refresh(true);
  166. ViewModel.Transaction.Image =
  167. docmodel.Items.FirstOrDefault()?.Data ?? new byte[] { };
  168. }
  169. }
  170. DismissPopup();
  171. });
  172. }
  173. );
  174. }
  175. private void InputView_OnTextChanged(object sender, TextChangedEventArgs e)
  176. {
  177. if (!Quantity.IsVisible)
  178. return;
  179. if (sender is Entry entry)
  180. {
  181. if (double.TryParse(e.NewTextValue, out double qty))
  182. {
  183. var alloc = ViewModel.Transaction.Allocations?.FirstOrDefault();
  184. if (alloc != null)
  185. alloc.Quantity = qty;
  186. }
  187. else
  188. entry.Text = e.OldTextValue;
  189. ViewModel.Transaction.RefreshQuantity();
  190. }
  191. }
  192. private async void Delete_Clicked(object sender, MobileButtonClickEventArgs args)
  193. {
  194. if (await DisplayAlert("Confirm", "Are you sure you wish to delete holding?", "Yes", "No") == true)
  195. {
  196. var holding = ViewModel.Transaction?.Source?.Shell;
  197. if (holding?.Parent != null)
  198. {
  199. holding.Parent.Items.Remove(holding);
  200. holding.Parent.Transactions.Remove(ViewModel.Transaction);
  201. }
  202. Navigation.PopAsync();
  203. }
  204. }
  205. private async Task AddImage<T, TOptions>(TOptions options)
  206. where T : MobileImageSource<T, TOptions>
  207. where TOptions : MobileImageOptions<T>, new()
  208. {
  209. App.Data.Products.Refresh(false);
  210. var product = App.Data.Products.FirstOrDefault(x => x.ID == ViewModel.Transaction.ProductID);
  211. if (product != null)
  212. {
  213. MobileDocument file = null;
  214. try
  215. {
  216. file = await MobileDocument.From<T>(options);
  217. }
  218. catch (Exception e)
  219. {
  220. await DisplayAlert("ERROR", e.Message, "OK");
  221. }
  222. if (file != null)
  223. {
  224. using (await MaterialDialog.Instance.LoadingDialogAsync("Saving Image"))
  225. {
  226. Document doc = new Document()
  227. {
  228. FileName = file.FileName,
  229. Data = file.Data,
  230. CRC = CoreUtils.CalculateCRC(file.Data),
  231. TimeStamp = DateTime.Now
  232. };
  233. new Client<Document>().Save(doc, "Created on Mobile Device");
  234. product.ImageID = doc.ID;
  235. product.Save("Photo Updated from Mobile Device");
  236. product.Parent.Images[doc.ID] = file.Data;
  237. ViewModel.Transaction.ImageID = doc.ID;
  238. ViewModel.Transaction.Image = file.Data;
  239. }
  240. }
  241. }
  242. else
  243. DisplayAlert("Error","Please select a Product first!","OK");
  244. }
  245. private async void _imagesphoto_Clicked(object sender, EventArgs e)
  246. {
  247. if (ViewModel.Transaction.ImageID != Guid.Empty)
  248. {
  249. if (await DisplayAlert("Confirm", "Are you sure you wish to replace the existing image?", "Yes",
  250. "No") == false)
  251. return;
  252. }
  253. await AddImage<MobileDocumentCameraSource, MobileDocumentCameraOptions>(
  254. PhotoUtils.CreateCameraOptions());
  255. }
  256. private async void _imageslibrary_Clicked(object sender, EventArgs e)
  257. {
  258. if (ViewModel.Transaction.ImageID != Guid.Empty)
  259. {
  260. if (await DisplayAlert("Confirm", "Are you sure you wish to replace the existing image?", "Yes",
  261. "No") == false)
  262. return;
  263. }
  264. await AddImage<MobileDocumentPhotoLibrarySource, MobileDocumentPhotoLibraryOptions>(
  265. PhotoUtils.CreatePhotoLibraryOptions());
  266. }
  267. private void SelectUnitSize_Clicked(object sender, MobileButtonClickEventArgs args)
  268. {
  269. var editor = new DimensionsEditor() { Transaction = ViewModel.Transaction };
  270. editor.CloseRequested += (o, eventArgs) => PopupManager.DismissPopup();
  271. ShowPopup(
  272. ()=> editor,
  273. new PopupManagerConfiguration()
  274. {
  275. SizeMode = AutoSizeMode.Height,
  276. Modal = true,
  277. }
  278. );
  279. }
  280. private void SelectAllocations_Clicked(object sender, MobileButtonClickEventArgs args)
  281. {
  282. var editor = new AllocationsEditor() { Transaction = ViewModel.Transaction };
  283. editor.CloseRequested += (o, eventArgs) => PopupManager.DismissPopup();
  284. ShowPopup(
  285. () => editor,
  286. new PopupManagerConfiguration()
  287. {
  288. SizeMode = AutoSizeMode.Height,
  289. Modal = true
  290. }
  291. );
  292. }
  293. }
  294. }