StoreRequiConfirmationPage.xaml.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Threading.Tasks;
  5. using Xamarin.Forms;
  6. using Xamarin.Forms.Xaml;
  7. using Comal.Classes;
  8. using InABox.Core;
  9. using InABox.Clients;
  10. using XF.Material.Forms.UI.Dialogs;
  11. using System.IO;
  12. using Xamarin.Essentials;
  13. namespace PRS.Mobile
  14. {
  15. [XamlCompilation(XamlCompilationOptions.Compile)]
  16. public partial class StoreRequiConfirmationPage
  17. {
  18. #region Fields
  19. public delegate void SaveSelectedEvent();
  20. public event SaveSelectedEvent OnSaveSelected;
  21. JobShell job = new JobShell();
  22. bool newRequi;
  23. Requisition requisition;
  24. bool isNewRequest = false;
  25. Dictionary<Image, Document> imagesDocuments = new Dictionary<Image, Document>();
  26. List<StoreRequiItemShell> requiItems = new List<StoreRequiItemShell>();
  27. List<StoreRequiItemShell> oldrequiitems = new List<StoreRequiItemShell>();
  28. #endregion
  29. #region Constructor and appearing
  30. public StoreRequiConfirmationPage(Requisition _requisition, List<StoreRequiItemShell> _requiitems, List<StoreRequiItemShell> _oldrequiitems) //requi could be existing or a blank/new requi (ID empty)
  31. {
  32. InitializeComponent();
  33. requiItems = _requiitems;
  34. if (requiItems[0].IsNotes == true)
  35. {
  36. requiItems.RemoveAt(0);
  37. }
  38. oldrequiitems = _oldrequiitems;
  39. requiStatusLbl.IsVisible = true;
  40. requiStatusFrame.IsVisible = true;
  41. boxesLbl.IsVisible = true;
  42. boxesQtyFrame.IsVisible = true;
  43. photosLbl.IsVisible = true;
  44. photosFrame.IsVisible = true;
  45. if (_requisition.ID != Guid.Empty)
  46. forDeliveryRb.IsChecked = true;
  47. else
  48. takenNowRb.IsChecked = true;
  49. dueLbl.IsVisible = false;
  50. dueFrame.IsVisible = false;
  51. ChooseTrack(_requisition);
  52. }
  53. public StoreRequiConfirmationPage() //when no requi is passed, app is creating a new requi request
  54. {
  55. InitializeComponent();
  56. isNewRequest = true;
  57. NewRequiTrack();
  58. UpdateColours();
  59. notesTitleLbl.Text = "Request";
  60. dueDatePckr.IsEnabled = true;
  61. reduceQtyBtn.IsEnabled = false;
  62. increaseQtyBtn.IsEnabled = false;
  63. TakePhoto.IsEnabled = false;
  64. ChooseImage.IsEnabled = false;
  65. }
  66. private void ChooseTrack(Comal.Classes.Requisition _requisition)
  67. {
  68. if (_requisition.ID == Guid.Empty)
  69. {
  70. NewRequiTrack();
  71. }
  72. else
  73. {
  74. ExistingRequiTrack(_requisition);
  75. }
  76. }
  77. private void NewRequiTrack()
  78. {
  79. newRequi = true;
  80. requisition = new Requisition();
  81. requisition.Title = "New Requisition";
  82. requisition.Boxes = 1;
  83. boxQtyLbl.Text = requisition.Boxes.ToString();
  84. titleLbl.Text = "New Requisition";
  85. requisition.Title = "New Requisition";
  86. requisition.Due = DateTime.Now;
  87. requisition.RequestedBy.ID = App.Data.Me.ID;
  88. requisition.RequestedBy.Name = App.Data.Me.Name;
  89. //create new requi
  90. }
  91. private void ExistingRequiTrack(Comal.Classes.Requisition _requisition)
  92. {
  93. newRequi = false;
  94. requisition = _requisition;
  95. titleLbl.Text = "Requi " + _requisition.Number.ToString();
  96. LoadPhotos();
  97. UpdateScreen();
  98. }
  99. #endregion
  100. #region Screen Update
  101. private void UpdateScreen()
  102. {
  103. jobLbl.Text = requisition.JobLink.JobNumber + " " + requisition.JobLink.Name;
  104. boxQtyLbl.Text = requisition.Boxes.ToString();
  105. if (string.IsNullOrEmpty(notesEdt.Text))
  106. {
  107. List<string> notes = new List<string>();
  108. foreach (string s in requisition.Notes)
  109. {
  110. string substring = s.Replace("=", string.Empty);
  111. substring = substring.Trim();
  112. if (!string.IsNullOrWhiteSpace(substring))
  113. notes.Add(substring);
  114. }
  115. notesEdt.Text = String.Join("\n", notes);
  116. }
  117. UpdateColours();
  118. }
  119. private void UpdateColours()
  120. {
  121. if (requisition.JobLink.ID == Guid.Empty)
  122. jobFrame.BorderColor = Color.Red;
  123. else
  124. jobFrame.BorderColor = Color.Gray;
  125. if (images.Children.Count == 0)
  126. photosFrame.BorderColor = Color.Red;
  127. else
  128. photosFrame.BorderColor = Color.Gray;
  129. if (isNewRequest)
  130. photosFrame.BorderColor = Color.Gray;
  131. }
  132. private void LoadPhotos()
  133. {
  134. if (requisition.Documents != 0)
  135. {
  136. var table = QueryPhotos();
  137. while (table == null)
  138. table = QueryPhotos();
  139. if (table.Rows.Count != 0)
  140. {
  141. foreach (var row in table.Rows)
  142. {
  143. List<object> list = row.Values;
  144. if (list[0] == null) { list[0] = Guid.Empty; }
  145. Guid requisitionDocLinkID = Guid.Parse(list[0].ToString());
  146. Client.Query(
  147. new Filter<Document>(x => x.ID).IsEqualTo(requisitionDocLinkID),
  148. Columns.All<Document>(),
  149. null,
  150. (t, e) =>
  151. {
  152. CoreRow docrow = t.Rows.FirstOrDefault();
  153. if (docrow != null)
  154. {
  155. byte[] data = docrow.Get<Document, byte[]>(x => x.Data);
  156. ImageSource src = ImageSource.FromStream(() => new MemoryStream(data));
  157. Image img = new Image();
  158. img.HeightRequest = 150;
  159. img.WidthRequest = 150;
  160. img.Aspect = Aspect.AspectFit;
  161. img.Source = src;
  162. img.GestureRecognizers.Add(new TapGestureRecognizer
  163. {
  164. Command = new Command(OnTap),
  165. CommandParameter = src,
  166. NumberOfTapsRequired = 1
  167. });
  168. Device.BeginInvokeOnMainThread(() =>
  169. {
  170. ImageScroller.IsVisible = true;
  171. images.Children.Add(img);
  172. UpdateColours();
  173. });
  174. }
  175. }
  176. );
  177. }
  178. }
  179. }
  180. }
  181. private CoreTable QueryPhotos()
  182. {
  183. try
  184. {
  185. return new Client<RequisitionDocument>().Query(
  186. new Filter<RequisitionDocument>(x => x.EntityLink.ID).IsEqualTo(requisition.ID),
  187. new Columns<RequisitionDocument>(ColumnTypeFlags.None).Add(x => x.DocumentLink.ID),
  188. null
  189. );
  190. }
  191. catch (Exception ex)
  192. {
  193. InABox.Mobile.MobileLogging.Log(ex);
  194. return null;
  195. }
  196. }
  197. #endregion
  198. #region Selection
  199. private void SelectJobBtn_Clicked(object sender, EventArgs e)
  200. {
  201. JobSelectionPage jobSelectionPage = new JobSelectionPage(
  202. (job) =>
  203. {
  204. if (job != null)
  205. {
  206. requisition.JobLink.ID = job.ID;
  207. requisition.JobLink.Name = job.Name;
  208. requisition.JobLink.JobNumber = job.JobNumber;
  209. UpdateScreen();
  210. }
  211. }
  212. );
  213. Navigation.PushAsync(jobSelectionPage);
  214. }
  215. private void ReduceQtyBtn_Clicked(object sender, EventArgs e)
  216. {
  217. if (requisition.Boxes <= 1)
  218. return;
  219. else
  220. {
  221. requisition.Boxes--;
  222. UpdateScreen();
  223. }
  224. }
  225. private void IncreaseQtyBtn_Clicked(object sender, EventArgs e)
  226. {
  227. requisition.Boxes++;
  228. UpdateScreen();
  229. }
  230. private void DueDatePckr_DateSelected(object sender, EventArgs e)
  231. {
  232. requisition.Due = dueDatePckr.Date;
  233. }
  234. #endregion
  235. #region Photos
  236. private void TakePhoto_Clicked(object sender, EventArgs e)
  237. {
  238. TakeAPhoto();
  239. }
  240. private void ChooseImage_Clicked(object sender, EventArgs e)
  241. {
  242. ChooseAPhoto();
  243. }
  244. private async void TakeAPhoto()
  245. {
  246. var file = await MediaPicker.CapturePhotoAsync();
  247. if (file == null)
  248. return;
  249. using (await MaterialDialog.Instance.LoadingDialogAsync(message: "Adding Photo"))
  250. {
  251. Image img = null;
  252. var memoryStream = new MemoryStream();
  253. using (var stream = await file.OpenReadAsync())
  254. await stream.CopyToAsync(memoryStream);
  255. var data = memoryStream.ToArray();
  256. Document doc = new Document()
  257. {
  258. FileName = Path.GetFileName(file.FileName),
  259. Data = data,
  260. CRC = CoreUtils.CalculateCRC(data),
  261. TimeStamp = DateTime.Now
  262. };
  263. ImageSource src = ImageSource.FromStream(() => new MemoryStream(data));
  264. img = new Image();
  265. img.HeightRequest = 150;
  266. img.WidthRequest = 150;
  267. img.Aspect = Aspect.AspectFit;
  268. img.Source = src;
  269. img.GestureRecognizers.Add(new TapGestureRecognizer
  270. {
  271. Command = new Command(OnTap),
  272. CommandParameter = src,
  273. NumberOfTapsRequired = 1
  274. });
  275. imagesDocuments.Add(img, doc);
  276. if (img != null)
  277. {
  278. Device.BeginInvokeOnMainThread(() =>
  279. {
  280. ImageScroller.IsVisible = true;
  281. images.Children.Add(img);
  282. UpdateColours();
  283. });
  284. }
  285. }
  286. }
  287. private async void ChooseAPhoto()
  288. {
  289. var file = await MediaPicker.PickPhotoAsync();
  290. if (file == null)
  291. return;
  292. using (await MaterialDialog.Instance.LoadingDialogAsync(message: "Adding Photo"))
  293. {
  294. Image img = null;
  295. var memoryStream = new MemoryStream();
  296. using (var stream = await file.OpenReadAsync())
  297. await stream.CopyToAsync(memoryStream);
  298. var data = memoryStream.ToArray();
  299. Document doc = new Document()
  300. {
  301. FileName = Path.GetFileName(file.FileName),
  302. Data = data,
  303. CRC = CoreUtils.CalculateCRC(data),
  304. TimeStamp = DateTime.Now
  305. };
  306. ImageSource src = ImageSource.FromStream(() => new MemoryStream(data));
  307. img = new Image();
  308. img.HeightRequest = 150;
  309. img.WidthRequest = 150;
  310. img.Aspect = Aspect.AspectFit;
  311. img.Source = src;
  312. img.GestureRecognizers.Add(new TapGestureRecognizer
  313. {
  314. Command = new Command(OnTap),
  315. CommandParameter = src,
  316. NumberOfTapsRequired = 1
  317. });
  318. imagesDocuments.Add(img, doc);
  319. if (img != null)
  320. {
  321. Device.BeginInvokeOnMainThread(() =>
  322. {
  323. ImageScroller.IsVisible = true;
  324. images.Children.Add(img);
  325. UpdateColours();
  326. });
  327. }
  328. }
  329. }
  330. private void OnTap(object obj)
  331. {
  332. ImageViewerPage viewer = new ImageViewerPage(obj as ImageSource, () => DeleteImage(obj));
  333. Navigation.PushAsync(viewer);
  334. }
  335. private void DeleteImage(object obj)
  336. {
  337. Image img = imagesDocuments.Keys.First(x => x.Source.Equals(obj as ImageSource));
  338. imagesDocuments.Remove(img);
  339. Device.BeginInvokeOnMainThread(() =>
  340. {
  341. images.Children.Clear();
  342. if (imagesDocuments.Count > 0)
  343. {
  344. foreach (Image image in imagesDocuments.Keys)
  345. {
  346. images.Children.Add(image);
  347. }
  348. }
  349. UpdateColours();
  350. });
  351. }
  352. #endregion
  353. #region Save
  354. private async void SaveBtn_Clicked(object sender, EventArgs e)
  355. {
  356. if (CheckSaveOk())
  357. {
  358. if (isNewRequest)
  359. {
  360. requisition.Request = notesEdt.Text;
  361. DoSaveRequi(requisition);
  362. DisplayAlert("Success", "Requisition " + requisition.Number + " Created", "Ok");
  363. }
  364. else
  365. {
  366. if (takenNowRb.IsChecked)
  367. {
  368. requisition.TakenBy.ID = App.Data.Me.ID;
  369. requisition.TakenBy.Name = App.Data.Me.Name;
  370. }
  371. using (await MaterialDialog.Instance.LoadingDialogAsync(message: "Saving"))
  372. {
  373. SaveRequi();
  374. }
  375. if (requisition.ID != Guid.Empty)
  376. {
  377. using (await MaterialDialog.Instance.LoadingDialogAsync(message: "Saving"))
  378. {
  379. SavePhotos();
  380. SaveItems();
  381. }
  382. await DisplayAlert("Success", "Requisition " + requisition.Number + " Saved", "Ok");
  383. OnSaveSelected?.Invoke();
  384. Navigation.PopAsync();
  385. }
  386. }
  387. }
  388. }
  389. private Requisition DoSaveRequi(Comal.Classes.Requisition requisition)
  390. {
  391. try
  392. {
  393. new Client<Comal.Classes.Requisition>().Save(requisition, "Created on Mobile Device");
  394. return requisition;
  395. }
  396. catch (Exception ex)
  397. {
  398. InABox.Mobile.MobileLogging.Log(ex);
  399. return DoSaveRequi(requisition);
  400. }
  401. }
  402. private void SaveRequi()
  403. {
  404. requisition.Filled = DateTime.Now;
  405. requisition.Notes = new string[] { notesEdt.Text };
  406. DoSaveRequi(requisition);
  407. }
  408. private void SaveItems()
  409. {
  410. Task.Run(() =>
  411. {
  412. List<RequisitionItem> toDelete = new List<RequisitionItem>();
  413. if (oldrequiitems.Count > 0)
  414. {
  415. foreach (StoreRequiItemShell oldshell in oldrequiitems)
  416. {
  417. StoreRequiItemShell shell = requiItems.Find(x => x.ID.Equals(oldshell.ID));
  418. if (shell == null)
  419. {
  420. toDelete.Add(new RequisitionItem { ID = oldshell.ID });
  421. }
  422. }
  423. if (toDelete.Count > 0)
  424. {
  425. DoDeleteRequiItems(toDelete);
  426. }
  427. }
  428. });
  429. List<RequisitionItem> toSave = new List<RequisitionItem>();
  430. foreach (StoreRequiItemShell requiItemShell in requiItems)
  431. {
  432. RequisitionItem item = new RequisitionItem();
  433. item.RequisitionLink.ID = requisition.ID;
  434. item.ID = requiItemShell.ID;
  435. item.Product.ID = requiItemShell.ProductID;
  436. item.Product.Code = requiItemShell.ProductCode;
  437. item.Product.Name = requiItemShell.ProductName;
  438. item.Location.ID = requiItemShell.LocationID;
  439. item.Quantity = requiItemShell.Quantity;
  440. item.Description = requiItemShell.ProductName;
  441. item.Code = requiItemShell.ProductCode;
  442. item.JobLink.ID = requiItemShell.JobID;
  443. item.Style.ID = requiItemShell.StyleID;
  444. item.Picked = item.Picked == DateTime.MinValue ? DateTime.Now : item.Picked;
  445. item.Dimensions.Unit.ID = requiItemShell.Dimensions.Unit.ID;
  446. item.Dimensions.Unit.HasQuantity = requiItemShell.Dimensions.Unit.HasQuantity;
  447. item.Dimensions.Unit.HasLength = requiItemShell.Dimensions.Unit.HasLength;
  448. item.Dimensions.Unit.HasHeight = requiItemShell.Dimensions.Unit.HasHeight;
  449. item.Dimensions.Unit.HasWeight = requiItemShell.Dimensions.Unit.HasWeight;
  450. item.Dimensions.Unit.HasWidth = requiItemShell.Dimensions.Unit.HasWidth;
  451. item.Dimensions.Quantity = requiItemShell.Dimensions.Quantity;
  452. item.Dimensions.Length = requiItemShell.Dimensions.Length;
  453. item.Dimensions.Height = requiItemShell.Dimensions.Height;
  454. item.Dimensions.Weight = requiItemShell.Dimensions.Weight;
  455. item.Dimensions.Width = requiItemShell.Dimensions.Width;
  456. item.Dimensions.Unit.Format = requiItemShell.Dimensions.Unit.Format;
  457. item.Dimensions.Unit.Formula = requiItemShell.Dimensions.Unit.Formula;
  458. item.Dimensions.UnitSize = requiItemShell.Dimensions.UnitSize;
  459. toSave.Add(item);
  460. }
  461. DoSaveRequiItems(toSave);
  462. }
  463. private void DoDeleteRequiItems(List<RequisitionItem> toDelete)
  464. {
  465. try
  466. {
  467. new Client<RequisitionItem>().Delete(toDelete, "Updated from mobile device");
  468. }
  469. catch (Exception ex)
  470. {
  471. InABox.Mobile.MobileLogging.Log(ex);
  472. DoDeleteRequiItems(toDelete);
  473. }
  474. }
  475. private void DoSaveRequiItems(List<RequisitionItem> toSave)
  476. {
  477. try
  478. {
  479. new Client<RequisitionItem>().Save(toSave, "Saved requi on mobile device");
  480. }
  481. catch (Exception ex)
  482. {
  483. InABox.Mobile.MobileLogging.Log(ex);
  484. DoSaveRequiItems(toSave);
  485. }
  486. }
  487. private void SavePhotos()
  488. {
  489. Task.Run(() =>
  490. {
  491. if (imagesDocuments.Count != 0)
  492. {
  493. DoSaveDocuments();
  494. List<RequisitionDocument> newRequiDocuments = new List<RequisitionDocument>();
  495. foreach (Document doc in imagesDocuments.Values)
  496. {
  497. var requiDocument = new RequisitionDocument();
  498. requiDocument.EntityLink.ID = requisition.ID;
  499. requiDocument.DocumentLink.ID = doc.ID;
  500. requiDocument.DocumentLink.FileName = doc.FileName;
  501. newRequiDocuments.Add(requiDocument);
  502. }
  503. DoSaveRequiDocuments(newRequiDocuments);
  504. }
  505. });
  506. }
  507. private void DoSaveDocuments()
  508. {
  509. try
  510. {
  511. new Client<Document>().Save(imagesDocuments.Values, "Photo Taken on Mobile device Requis module");
  512. }
  513. catch (Exception ex)
  514. {
  515. InABox.Mobile.MobileLogging.Log(ex);
  516. DoSaveDocuments();
  517. }
  518. }
  519. private void DoSaveRequiDocuments(List<RequisitionDocument> newRequiDocuments)
  520. {
  521. try
  522. {
  523. new Client<RequisitionDocument>().Save(newRequiDocuments, "Photo Taken on Mobile device Requis module");
  524. }
  525. catch (Exception ex)
  526. {
  527. InABox.Mobile.MobileLogging.Log(ex);
  528. DoSaveRequiDocuments(newRequiDocuments);
  529. }
  530. }
  531. private bool CheckSaveOk()
  532. {
  533. bool bOK = false;
  534. if (requisition.JobLink.ID != Guid.Empty)
  535. {
  536. bOK = true;
  537. }
  538. else
  539. {
  540. DisplayAlert("Unable to save", "Add a Job", "OK");
  541. return bOK;
  542. }
  543. if (images.Children.Count > 0)
  544. {
  545. bOK = true;
  546. }
  547. else if (isNewRequest)
  548. {
  549. bOK = true;
  550. }
  551. else
  552. {
  553. bOK = false;
  554. DisplayAlert("Unable to save", "Add a Photo", "OK");
  555. return bOK;
  556. }
  557. return bOK;
  558. }
  559. #endregion
  560. }
  561. }