StoreRequiConfirmationPage.xaml.cs 22 KB

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