Receivals.xaml.cs 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using InABox.Core;
  7. using InABox.Clients;
  8. using Comal.Classes;
  9. using Xamarin.Forms;
  10. using Xamarin.Forms.Xaml;
  11. using System.Threading;
  12. using System.Threading.Tasks;
  13. using comal.timesheets.QAForms;
  14. using XF.Material.Forms.UI.Dialogs;
  15. using comal.timesheets;
  16. using Xamarin.Essentials;
  17. using System.IO;
  18. using PRSSecurity = InABox.Core.Security;
  19. namespace comal.timesheets
  20. {
  21. [XamlCompilation(XamlCompilationOptions.Compile)]
  22. public partial class Receivals : ContentPage
  23. {
  24. #region Fields & Constructor, OnAppearing
  25. Guid POID = Guid.Empty;
  26. List<POItemShell> poItemShells = new List<POItemShell>();
  27. List<StockLocationShell> stockLocationShells = new List<StockLocationShell>();
  28. bool bOpening = false;
  29. List<Guid> holdingsToLookup = new List<Guid>();
  30. string deviceType = "";
  31. Guid supplierID = Guid.Empty;
  32. string PONumber = "";
  33. Guid consignmentID = Guid.Empty;
  34. string consignmentNumber = "";
  35. List<POItemShell> listReceived = new List<POItemShell>();
  36. public Receivals(Guid _poID, string _PONumber, Guid _supplierID)
  37. {
  38. InitializeComponent();
  39. NavigationPage.SetHasBackButton(this, false);
  40. POID = _poID;
  41. PONumber = _PONumber;
  42. poNumberLbl.Text = "PO: " + _PONumber;
  43. var idiom = DeviceInfo.Idiom;
  44. if (idiom.Equals(DeviceIdiom.Tablet))
  45. {
  46. deviceType = "Tablet";
  47. }
  48. LoadPOItems();
  49. supplierID = _supplierID;
  50. AddIncomingStores();
  51. }
  52. protected override void OnAppearing()
  53. {
  54. base.OnAppearing();
  55. bOpening = false;
  56. }
  57. #endregion
  58. #region User Interaction
  59. private async void Exit_Clicked(object sender, EventArgs e)
  60. {
  61. if (listReceived.Count > 0)
  62. {
  63. DisplayAlert("Alert", "Consignment has items received and must be saved with photos before exiting", "OK");
  64. }
  65. else
  66. Navigation.PopAsync();
  67. }
  68. private async void Save_Clicked(object sender, EventArgs e)
  69. {
  70. ConsignmentCompletionPage completionPage = new ConsignmentCompletionPage(listReceived, consignmentID, consignmentNumber);
  71. completionPage.OnConsignmentSaved += () =>
  72. {
  73. Navigation.PopAsync();
  74. };
  75. Navigation.PushAsync(completionPage);
  76. }
  77. private void ConsignmentList_Tapped(object sender, EventArgs e)
  78. {
  79. if (bOpening)
  80. return;
  81. if (!PRSSecurity.IsAllowed<CanReceiveConsignments>())
  82. {
  83. DisplayAlert("Not allowed", "Please check security setting: Receive Consignments", "OK");
  84. return;
  85. }
  86. bOpening = true;
  87. POItemShell poItemShell = poItemListView.SelectedItem as POItemShell;
  88. if (poItemShell.Nonstock == true)
  89. {
  90. ChooseQtyNonStockItem(poItemShell);
  91. }
  92. else
  93. {
  94. ChooseQtyStockItem(poItemShell);
  95. }
  96. }
  97. private async void ChooseQtyStockItem(POItemShell poItemShell)
  98. {
  99. ConsignmentDetailsPopup popup = new ConsignmentDetailsPopup(poItemShell, stockLocationShells);
  100. popup.OnConsignmentPopupAccepted += async () =>
  101. {
  102. using (await MaterialDialog.Instance.LoadingDialogAsync(message: "Loading"))
  103. {
  104. poItemShell.StockLocationID = popup._POItemShell.StockLocationID;
  105. poItemShell.StockLocationCode = popup._POItemShell.StockLocationCode;
  106. poItemShell.StockLocationDescription = popup._POItemShell.StockLocationDescription;
  107. poItemShell.ReceivedQty = popup._POItemShell.ReceivedQty;
  108. StockLocationShell location = stockLocationShells.Find(x => x.ID.Equals(poItemShell.StockLocationID));
  109. if (location == null)
  110. {
  111. StockLocationShell newLocation = new StockLocationShell()
  112. {
  113. ID = poItemShell.StockLocationID,
  114. Code = poItemShell.StockLocationCode,
  115. Description = poItemShell.StockLocationDescription
  116. };
  117. stockLocationShells.Add(newLocation);
  118. }
  119. ChooseSavePathwayAsync(poItemShell);
  120. }
  121. };
  122. Navigation.PushAsync(popup);
  123. bOpening = false;
  124. }
  125. private async void ChooseQtyNonStockItem(POItemShell poItemShell)
  126. {
  127. Device.BeginInvokeOnMainThread(async () =>
  128. {
  129. //if nonstock item - only rec qty, otherwise open popup page
  130. string chosenOption = await DisplayPromptAsync("Enter Received Quantity", "", initialValue: poItemShell.ExpectedQty.ToString(), keyboard: Keyboard.Numeric);
  131. if (!string.IsNullOrEmpty(chosenOption) || chosenOption != "Cancel")
  132. {
  133. try
  134. {
  135. double qty = double.Parse(chosenOption);
  136. poItemShell.ReceivedQty = qty;
  137. }
  138. catch
  139. {
  140. DisplayAlert("Error", "Invalid Qty", "OK");
  141. bOpening = false;
  142. return;
  143. }
  144. bOpening = false;
  145. ChooseSavePathwayAsync(poItemShell);
  146. }
  147. else
  148. bOpening = false;
  149. });
  150. }
  151. private void SearchEnt_Changed(object sender, EventArgs e)
  152. {
  153. if (string.IsNullOrWhiteSpace(searchEnt.Text))
  154. {
  155. poItemListView.ItemsSource = poItemShells;
  156. }
  157. else
  158. {
  159. poItemListView.ItemsSource = poItemShells.Where(x =>
  160. x.Description.Contains(searchEnt.Text) || x.Description.Contains(UpperCaseFirst(searchEnt.Text)) || x.Description.Contains(LowerCaseFirst(searchEnt.Text))
  161. || x.Description.Contains(searchEnt.Text.ToUpper()) || x.Description.Contains(searchEnt.Text.ToLower()) ||
  162. x.ExpectedQty.ToString().Contains(searchEnt.Text)
  163. );
  164. }
  165. }
  166. static String UpperCaseFirst(string s)
  167. {
  168. char[] a = s.ToCharArray();
  169. a[0] = char.ToUpper(a[0]);
  170. return new string(a);
  171. }
  172. static String LowerCaseFirst(string s)
  173. {
  174. char[] a = s.ToCharArray();
  175. a[0] = char.ToLower(a[0]);
  176. return new string(a);
  177. }
  178. #endregion
  179. #region Saving
  180. private async Task ChooseSavePathwayAsync(POItemShell poItemShell)
  181. {
  182. if (consignmentID == Guid.Empty)
  183. await CreateNewConsignment();
  184. if (poItemShell.ReceivedQty == poItemShell.ExpectedQty)
  185. {
  186. SaveCorrectQuantityPOItem(poItemShell);
  187. }
  188. else if (poItemShell.ReceivedQty < poItemShell.ExpectedQty && poItemShell.ReceivedQty != 0)
  189. {
  190. SaveLesserQuantityPOItem(poItemShell);
  191. }
  192. else if (poItemShell.ReceivedQty > poItemShell.ExpectedQty)
  193. {
  194. SaveExtraQuantityPOItem(poItemShell);
  195. }
  196. }
  197. private async void SaveCorrectQuantityPOItem(POItemShell poItemShell)
  198. {
  199. await Task.Run(() =>
  200. {
  201. poItemShell.ReceivedQty = poItemShell.ExpectedQty;
  202. poItemShell.ReceivedDate = DateTime.Now;
  203. poItemShell.ConsignmentID = consignmentID;
  204. poItemShell.ConsignmentNumber = consignmentNumber;
  205. SavePOItem(poItemShell);
  206. int index = poItemShells.FindIndex(x => x.ID.Equals(poItemShell.ID));
  207. poItemShells.RemoveAt(index);
  208. RefreshLists(poItemShell);
  209. });
  210. }
  211. private void SavePOItem(POItemShell poItemShell)
  212. {
  213. Task.Run(() =>
  214. {
  215. listReceived.Add(poItemShell);
  216. PurchaseOrderItem purchaseOrderItem = new PurchaseOrderItem();
  217. purchaseOrderItem.Description = poItemShell.Description;
  218. purchaseOrderItem.ID = poItemShell.ID;
  219. purchaseOrderItem.Qty = poItemShell.ReceivedQty;
  220. purchaseOrderItem.ReceivedDate = DateTime.Now;
  221. purchaseOrderItem.Consignment.ID = consignmentID;
  222. purchaseOrderItem.PurchaseOrderLink.PONumber = poItemShell.PONumber;
  223. purchaseOrderItem.PurchaseOrderLink.ID = poItemShell.POID;
  224. purchaseOrderItem = CopyDetails(purchaseOrderItem, poItemShell);
  225. new Client<PurchaseOrderItem>().Save(purchaseOrderItem, "Updated from mobile device");
  226. });
  227. }
  228. private void RefreshLists(POItemShell poItemShell)
  229. {
  230. Device.BeginInvokeOnMainThread(() =>
  231. {
  232. poItemListView.ItemsSource = null;
  233. poItemListView.ItemsSource = poItemShells;
  234. poItemCountLbl.Text = "Items Unreceived: " + poItemShells.Count;
  235. if (poItemShell.StockLocationID != Guid.Empty)
  236. {
  237. StockLocationShell location = stockLocationShells.Find(x => x.ID.Equals(poItemShell.StockLocationID));
  238. location.PoItems.Add(poItemShell);
  239. location.NumberOfReceivedItems = "Received items: " + location.PoItems.Count;
  240. locationsStackLayout.Children.Clear();
  241. foreach (StockLocationShell shell in stockLocationShells)
  242. {
  243. StockLocationViewCell viewcell = new StockLocationViewCell(shell);
  244. locationsStackLayout.Children.Add(viewcell);
  245. }
  246. }
  247. });
  248. }
  249. private async void SaveLesserQuantityPOItem(POItemShell poItemShell)
  250. {
  251. using (await MaterialDialog.Instance.LoadingDialogAsync(message: "Loading"))
  252. {
  253. try
  254. {
  255. string originalDescription = poItemShell.Description;
  256. int index = poItemShells.FindIndex(x => x.ID.Equals(poItemShell.ID));
  257. poItemShells.RemoveAt(index);
  258. //placeholder added while all the loading / saving happens - to be replaced later when new purchaseorderitem ID is returned
  259. POItemShell placeHolderShell = poItemShell.DuplicateNewShell(poItemShell);
  260. placeHolderShell.ExpectedQty = poItemShell.ExpectedQty - poItemShell.ReceivedQty;
  261. poItemShells.Insert(index, placeHolderShell);
  262. SavePOItem(poItemShell); //original POItem is saved
  263. CoreTable table = new Client<PurchaseOrderItem>().Query(new Filter<PurchaseOrderItem>(x => x.ID).IsEqualTo(poItemShell.ID),
  264. columns);
  265. PurchaseOrderItem purchaseOrderItem = table.Rows.FirstOrDefault()?.ToObject<PurchaseOrderItem>();
  266. if (purchaseOrderItem == null)
  267. return;
  268. purchaseOrderItem.ID = Guid.Empty;
  269. purchaseOrderItem.Created = DateTime.Now;
  270. purchaseOrderItem.LastUpdate = DateTime.Now;
  271. purchaseOrderItem.OriginalValues.Remove("ID", out object obj);
  272. purchaseOrderItem.ReceivedDate = DateTime.MinValue;
  273. purchaseOrderItem.Qty = poItemShell.ExpectedQty - poItemShell.ReceivedQty;
  274. purchaseOrderItem.Description = originalDescription;
  275. purchaseOrderItem.Consignment.ID = Guid.Empty;
  276. purchaseOrderItem = CopyDetails(purchaseOrderItem, poItemShell);
  277. new Client<PurchaseOrderItem>().Save(purchaseOrderItem, "Update from mobile device");
  278. //new purchase order is split from original with different quantity and no consignment linked, saved to database
  279. POItemShell newShell = poItemShell.DuplicateNewShell(poItemShell);
  280. newShell.ID = purchaseOrderItem.ID;
  281. newShell.Description = purchaseOrderItem.Description;
  282. newShell.ExpectedQty = purchaseOrderItem.Qty;
  283. newShell.ConsignmentID = Guid.Empty;
  284. newShell.ConsignmentNumber = "";
  285. //placeholder is replaced by new shell with correct ID
  286. poItemShells.RemoveAt(index);
  287. poItemShells.Insert(index, newShell);
  288. RefreshLists(poItemShell);
  289. }
  290. catch { }
  291. }
  292. }
  293. private async void SaveExtraQuantityPOItem(POItemShell poItemShell)
  294. {
  295. await Task.Run(() =>
  296. {
  297. try
  298. {
  299. string originalDescription = poItemShell.Description;
  300. double originalExpectedQty = poItemShell.ExpectedQty;
  301. double originalReceivedQty = poItemShell.ReceivedQty;
  302. double extraSupplied = originalReceivedQty - originalExpectedQty;
  303. int index = poItemShells.FindIndex(x => x.ID.Equals(poItemShell.ID));
  304. poItemShells.RemoveAt(index);
  305. poItemShell.ReceivedDate = DateTime.Now;
  306. poItemShell.ConsignmentID = consignmentID;
  307. poItemShell.ConsignmentNumber = consignmentNumber;
  308. poItemShell.ReceivedQty = poItemShell.ExpectedQty;
  309. SavePOItem(poItemShell);
  310. RefreshLists(poItemShell);
  311. listReceived.Add(poItemShell);
  312. //for responsive view only
  313. POItemShell newShell = poItemShell.DuplicateNewShell(poItemShell);
  314. newShell.ReceivedQty = extraSupplied;
  315. newShell.ExpectedQty = extraSupplied;
  316. RefreshLists(newShell);
  317. listReceived.Add(newShell);
  318. CoreTable table = new Client<PurchaseOrderItem>().Query(new Filter<PurchaseOrderItem>(x => x.ID).IsEqualTo(poItemShell.ID)
  319. , columns);
  320. PurchaseOrderItem newPurchaseOrderItem = table.Rows.FirstOrDefault().ToObject<PurchaseOrderItem>();
  321. if (newPurchaseOrderItem == null)
  322. return;
  323. newPurchaseOrderItem.ReceivedDate = DateTime.Now;
  324. newPurchaseOrderItem.ID = Guid.Empty;
  325. newPurchaseOrderItem.Created = DateTime.Now;
  326. newPurchaseOrderItem.LastUpdate = DateTime.Now;
  327. newPurchaseOrderItem.OriginalValues.Remove("ID", out object obj);
  328. newPurchaseOrderItem.Qty = extraSupplied;
  329. newPurchaseOrderItem.Description = newShell.Description;
  330. newPurchaseOrderItem.Consignment.ID = consignmentID;
  331. newPurchaseOrderItem = CopyDetails(newPurchaseOrderItem, poItemShell);
  332. new Client<PurchaseOrderItem>().Save(newPurchaseOrderItem, "Update from mobile device");
  333. //new purchase order is split from original with different quantity, and consignment linked, saved to database
  334. }
  335. catch
  336. { }
  337. });
  338. }
  339. private PurchaseOrderItem CopyDetails(PurchaseOrderItem purchaseOrderItem, POItemShell poItemShell)
  340. {
  341. purchaseOrderItem.Product.ID = poItemShell.ProductID;
  342. purchaseOrderItem.Product.NonStock = poItemShell.Nonstock;
  343. purchaseOrderItem.Job.ID = poItemShell.JobID;
  344. purchaseOrderItem.Job.JobNumber = poItemShell.JobNumber;
  345. purchaseOrderItem.Job.Name = poItemShell.JobName;
  346. purchaseOrderItem.Style.ID = poItemShell.StyleID;
  347. purchaseOrderItem.Style.Code = poItemShell.StyleCode;
  348. purchaseOrderItem.Style.Description = poItemShell.StyleDescription;
  349. purchaseOrderItem.StockLocation.ID = poItemShell.StockLocationID;
  350. purchaseOrderItem.StockLocation.Description = poItemShell.StockLocationDescription;
  351. purchaseOrderItem.StockLocation.Code = poItemShell.StockLocationCode;
  352. purchaseOrderItem.Dimensions.Unit.ID = poItemShell.DimensionsUnitID;
  353. purchaseOrderItem.Dimensions.Quantity = poItemShell.DimensionsQuantity;
  354. purchaseOrderItem.Dimensions.Length = poItemShell.DimensionsLength;
  355. purchaseOrderItem.Dimensions.Width = poItemShell.DimensionsWidth;
  356. purchaseOrderItem.Dimensions.Height = poItemShell.DimensionsHeight;
  357. purchaseOrderItem.Dimensions.Weight = poItemShell.DimensionsWeight;
  358. purchaseOrderItem.Dimensions.Value = poItemShell.DimensionsValue;
  359. purchaseOrderItem.Dimensions.UnitSize = poItemShell.DimensionsUnitSize;
  360. purchaseOrderItem.Cost = poItemShell.Cost;
  361. return purchaseOrderItem;
  362. }
  363. #region ChoosingLocations
  364. private async void ChooseReceivingLocationBtn_Clicked(object sender, EventArgs e)
  365. {
  366. string chosenOption = await DisplayActionSheet("Choose an Option", "Cancel", null, "New Location / Pack", "Existing Location / Pack");
  367. switch (chosenOption)
  368. {
  369. case "Cancel":
  370. return;
  371. break;
  372. case "New Location / Pack":
  373. ChooseNewLocation();
  374. break;
  375. case "Existing Location / Pack":
  376. ChooseReceivingLocation();
  377. break;
  378. default:
  379. return;
  380. break;
  381. }
  382. }
  383. private void ChooseNewLocation()
  384. {
  385. try
  386. {
  387. StockLocation location = new StockLocation();
  388. location.Active = true;
  389. location.Warehouse.ID = Guid.Parse("b6249c4a-a834-4927-a42c-87a07895d6bd"); //EXTRUSIONS
  390. location.Warehouse.Description = "Extrusions";
  391. location.Warehouse.Code = "EXTRUSIONS";
  392. location.Area.Warehouse.ID = Guid.Parse("b6249c4a-a834-4927-a42c-87a07895d6bd"); //EXTRUSIONS
  393. location.Area.Warehouse.Description = "Extrusions";
  394. location.Area.ID = Guid.Parse("fa02ecd8-e642-49aa-98b5-c04d7ea0f4eb"); //Rack FLOOR
  395. location.Area.Description = "Rack FLOOR";
  396. location.Area.Code = "FLOOR";
  397. LocationDetailsPage locationDetailsPage = new LocationDetailsPage(location);
  398. locationDetailsPage.OnSave += (o, loc) =>
  399. {
  400. if (String.IsNullOrWhiteSpace(loc.Code))
  401. {
  402. MaterialDialog.Instance.AlertAsync(message: "Code may not be blank!");
  403. return false;
  404. }
  405. if (String.IsNullOrWhiteSpace(loc.Description))
  406. {
  407. MaterialDialog.Instance.AlertAsync(message: "Description may not be blank!");
  408. return false;
  409. }
  410. if (loc.Area.ID == Guid.Empty)
  411. {
  412. MaterialDialog.Instance.AlertAsync(message: "Area may not be blank!");
  413. return false;
  414. }
  415. CoreTable others = new Client<StockLocation>().Query(
  416. new Filter<StockLocation>(x => x.Code).IsEqualTo(loc.Code).And(x => x.ID).IsNotEqualTo(loc.ID),
  417. new Columns<StockLocation>(x => x.ID)
  418. );
  419. if (others.Rows.Any())
  420. {
  421. MaterialDialog.Instance.AlertAsync(message: "Location Code already exists!");
  422. return false;
  423. }
  424. try
  425. {
  426. new Client<StockLocation>().Save(loc, "Created Location");
  427. StockLocationShell shell = new StockLocationShell();
  428. shell.ID = loc.ID;
  429. shell.Code = loc.Code;
  430. shell.Description = loc.Description;
  431. stockLocationShells.Add(shell);
  432. Device.BeginInvokeOnMainThread(() =>
  433. {
  434. locationsStackLayout.Children.Clear();
  435. foreach (StockLocationShell shell2 in stockLocationShells)
  436. {
  437. StockLocationViewCell viewcell = new StockLocationViewCell(shell2);
  438. viewcell.stockLocationShell.NumberOfReceivedItems = "Received items: " + shell2.PoItems.Count();
  439. locationsStackLayout.Children.Add(viewcell);
  440. }
  441. });
  442. }
  443. catch (Exception err)
  444. {
  445. MaterialDialog.Instance.AlertAsync(message: "Unable to save Location\n" + err.Message);
  446. return false;
  447. }
  448. return true;
  449. };
  450. Navigation.PushAsync(locationDetailsPage);
  451. }
  452. catch { }
  453. }
  454. private void ChooseReceivingLocation()
  455. {
  456. if (bOpening)
  457. return;
  458. bOpening = true;
  459. StockLocationSelectionPage stockLocationSelectionPage = new StockLocationSelectionPage(true);
  460. stockLocationSelectionPage.OnMultiLocationSelected += async (s) =>
  461. {
  462. using (await MaterialDialog.Instance.LoadingDialogAsync(message: "Loading"))
  463. {
  464. foreach (StockLocationShell shell in s)
  465. {
  466. if (!stockLocationShells.Any(x => x.ID == shell.ID))
  467. {
  468. shell.Color = Color.Default;
  469. shell.NumberOfReceivedItems = "Received items: " + shell.PoItems.Count();
  470. stockLocationShells.Add(shell);
  471. }
  472. }
  473. Device.BeginInvokeOnMainThread(() =>
  474. {
  475. locationsStackLayout.Children.Clear();
  476. foreach (StockLocationShell shell in stockLocationShells)
  477. {
  478. StockLocationViewCell viewcell = new StockLocationViewCell(shell);
  479. viewcell.stockLocationShell.NumberOfReceivedItems = "Received items: " + shell.PoItems.Count();
  480. locationsStackLayout.Children.Add(viewcell);
  481. }
  482. });
  483. }
  484. };
  485. Navigation.PushAsync(stockLocationSelectionPage);
  486. }
  487. #endregion
  488. #endregion
  489. #region Loading
  490. private void AddIncomingStores()
  491. {
  492. Task.Run(() =>
  493. {
  494. try
  495. {
  496. StockLocation location = new Client<StockLocation>().Query(
  497. new Filter<StockLocation>(x => x.ID).IsEqualTo(Guid.Parse("3ebb1fe3-21f4-4731-b80a-a28f814982ea")),
  498. new Columns<StockLocation>(x => x.ID, x => x.Code, x => x.Description))
  499. .Rows.FirstOrDefault().ToObject<StockLocation>();
  500. stockLocationShells.Add(new StockLocationShell
  501. {
  502. ID = location.ID,
  503. Code = location.Code,
  504. Description = location.Description,
  505. NumberOfReceivedItems = "Received items: ",
  506. });
  507. StockLocationViewCell viewcell = new StockLocationViewCell(stockLocationShells[0]);
  508. Device.BeginInvokeOnMainThread(() =>
  509. {
  510. locationsStackLayout.Children.Add(viewcell);
  511. });
  512. }
  513. catch { }
  514. });
  515. }
  516. private void LoadPOItems()
  517. {
  518. Task.Run(() =>
  519. {
  520. try
  521. {
  522. CoreTable table = new Client<PurchaseOrderItem>().Query(
  523. new Filter<PurchaseOrderItem>(x => x.PurchaseOrderLink.ID).IsEqualTo(POID).And(x => x.ReceivedDate).IsEqualTo(DateTime.MinValue),
  524. columns);
  525. if (table.Rows.Any())
  526. {
  527. foreach (CoreRow row in table.Rows)
  528. {
  529. List<object> list = row.Values;
  530. if (list[0] == null) { list[0] = Guid.Empty; } //0
  531. if (list[1] == null) { list[1] = ""; } //1
  532. if (list[2] == null) { list[2] = ""; } //2
  533. if (list[3] == null) { list[3] = ""; } //3
  534. if (list[4] == null) { list[4] = ""; } //4
  535. if (list[5] == null) { list[5] = ""; } //5
  536. if (list[6] == null) { list[6] = 0F; } //6
  537. if (list[7] == null) { list[7] = Guid.Empty; } //7
  538. if (list[8] == null) { list[8] = Guid.Empty; } //8
  539. if (list[9] == null) { list[9] = DateTime.MinValue; } //9
  540. if (list[10] == null) { list[10] = Guid.Empty; } //10
  541. if (list[11] == null) { list[11] = ""; } //11
  542. if (list[12] == null) { list[12] = Guid.Empty; } //12
  543. if (list[13] == null) { list[13] = false; } //13
  544. if (list[14] == null) { list[14] = Guid.Empty; } //14
  545. if (list[15] == null) { list[15] = ""; } //15
  546. if (list[16] == null) { list[16] = ""; } //16
  547. if (list[17] == null) { list[17] = Guid.Empty; } //17
  548. if (list[18] == null) { list[18] = ""; } //18
  549. if (list[19] == null) { list[19] = ""; } //19
  550. if (list[20] == null) { list[20] = Guid.Empty; } //20
  551. if (list[21] == null) { list[21] = 0; } //21
  552. if (list[22] == null) { list[22] = 0; } //22
  553. if (list[23] == null) { list[23] = 0; } //23
  554. if (list[24] == null) { list[24] = 0; } //24
  555. if (list[25] == null) { list[25] = 0; } //25
  556. if (list[26] == null) { list[26] = 0; } //26
  557. if (list[27] == null) { list[27] = ""; } //27
  558. POItemShell item = new POItemShell()
  559. {
  560. ID = Guid.Parse(list[0].ToString()),
  561. PONumber = list[1].ToString(),
  562. ConsignmentNumber = "Cons: " + list[2].ToString(),
  563. JobName = list[3].ToString(),
  564. JobNumber = list[4].ToString(),
  565. Description = list[5].ToString(),
  566. ConsignmentID = Guid.Parse(list[7].ToString()),
  567. POID = Guid.Parse(list[8].ToString()),
  568. //FormCompleted = DateTime.Parse(list[10].ToString()),
  569. ReceivedDate = DateTime.Parse(list[9].ToString()),
  570. JobID = Guid.Parse(list[10].ToString()),
  571. SupplierCode = list[11].ToString(),
  572. ProductID = Guid.Parse(list[12].ToString()),
  573. Nonstock = Boolean.Parse(list[13].ToString()),
  574. StyleID = Guid.Parse(list[14].ToString()),
  575. StyleCode = list[15].ToString(),
  576. StyleDescription = list[16].ToString(),
  577. StockLocationID = Guid.Parse(list[17].ToString()),
  578. StockLocationDescription = list[18].ToString(),
  579. StockLocationCode = list[19].ToString(),
  580. DimensionsUnitID = Guid.Parse(list[20].ToString()),
  581. DimensionsQuantity = double.Parse(list[21].ToString()),
  582. DimensionsLength = double.Parse(list[22].ToString()),
  583. DimensionsWidth = double.Parse(list[23].ToString()),
  584. DimensionsHeight = double.Parse(list[24].ToString()),
  585. DimensionsWeight = double.Parse(list[25].ToString()),
  586. DimensionsValue = double.Parse(list[26].ToString()),
  587. DimensionsUnitSize = list[27].ToString()
  588. };
  589. if (double.TryParse(list[6].ToString(), out double result))
  590. item.ExpectedQty = result;
  591. poItemShells.Add(item);
  592. }
  593. LoadProductImages();
  594. Device.BeginInvokeOnMainThread(() =>
  595. {
  596. poItemListView.ItemsSource = poItemShells;
  597. poItemCountLbl.Text = "Items Unreceived: " + poItemShells.Count;
  598. });
  599. }
  600. }
  601. catch(Exception ex)
  602. {
  603. Device.BeginInvokeOnMainThread(() => { DisplayAlert("Error loading Purchase Order items - please try again", ex.Message, "OK"); });
  604. }
  605. });
  606. }
  607. private void LoadProductImages()
  608. {
  609. Task.Run(() =>
  610. {
  611. foreach (POItemShell shell in poItemShells)
  612. {
  613. if (shell.ProductID != Guid.Empty)
  614. {
  615. CoreTable table = new Client<Product>().Query
  616. (
  617. new Filter<Product>(x => x.ID).IsEqualTo(shell.ProductID).And(x => x.Image.ID).IsNotEqualTo(Guid.Empty),
  618. new Columns<Product>(x => x.Image.ID)
  619. );
  620. CoreTable table1 = new Client<Document>().Query
  621. (
  622. new Filter<Document>(x => x.ID).IsEqualTo(Guid.Parse(table.Rows.First().Values[0].ToString())),
  623. new Columns<Document>(x => x.Data)
  624. );
  625. CoreRow docrow = table1.Rows.FirstOrDefault();
  626. if (docrow != null)
  627. {
  628. byte[] data = docrow.Get<Document, byte[]>(x => x.Data);
  629. ImageSource src = ImageSource.FromStream(() => new MemoryStream(data));
  630. if (src != null)
  631. {
  632. shell.ImageSource = src;
  633. shell.ImageVisible = true;
  634. if (deviceType == "Tablet")
  635. {
  636. shell.LastRowHeight = 300;
  637. }
  638. else
  639. {
  640. shell.LastRowHeight = 150;
  641. }
  642. Device.BeginInvokeOnMainThread(() =>
  643. {
  644. poItemListView.ItemsSource = null;
  645. poItemListView.ItemsSource = poItemShells;
  646. });
  647. }
  648. }
  649. }
  650. }
  651. });
  652. }
  653. private async Task CreateNewConsignment()
  654. {
  655. using (await MaterialDialog.Instance.LoadingDialogAsync(message: "Creating new consignment"))
  656. {
  657. try
  658. {
  659. Consignment newConsignment = new Consignment() { };
  660. string name = "Unknown Supplier";
  661. if (supplierID != Guid.Empty)
  662. {
  663. newConsignment.Supplier.ID = supplierID;
  664. CoreTable supplierNameTable = new Client<Supplier>().Query(
  665. new Filter<Supplier>(x => x.ID).IsEqualTo(supplierID),
  666. new Columns<Supplier>(x => x.Name)
  667. );
  668. name = supplierNameTable.Rows.FirstOrDefault().Values[0].ToString();
  669. }
  670. newConsignment.Description = "Consignment for receival of items from " + name + ". Auto generated from mobile app by " + GlobalVariables.EmpName;
  671. CoreTable consignmentNumberTable = new Client<Consignment>().Query(
  672. new Filter<Consignment>(x => x.Number).Contains("APP").And(x => x.Created).IsGreaterThan(DateTime.Today.AddDays(-60)),
  673. new Columns<Consignment>(x => x.Number, x => x.Created),
  674. new SortOrder<Consignment>(x => x.Created));
  675. if (consignmentNumberTable.Rows.Any())
  676. {
  677. SetConsignmentNumber(newConsignment, consignmentNumberTable);
  678. }
  679. else
  680. {
  681. CoreTable consignmentNumberTable2 = new Client<Consignment>().Query(
  682. new Filter<Consignment>(x => x.Number).Contains("APP"),
  683. new Columns<Consignment>(x => x.Number, x => x.Created),
  684. new SortOrder<Consignment>(x => x.Created));
  685. if (consignmentNumberTable2.Rows.Any())
  686. {
  687. SetConsignmentNumber(newConsignment, consignmentNumberTable2);
  688. }
  689. else
  690. newConsignment.Number = "APP1" + " From PO: " + PONumber;
  691. }
  692. new Client<Consignment>().Save(newConsignment, "Updated from mobile device");
  693. consignmentID = newConsignment.ID;
  694. saveBtn.IsVisible = true;
  695. consignmentNumber = newConsignment.Number;
  696. consignmentNumberLbl.Text = "Consignment: " + newConsignment.Number;
  697. if (consignmentID == Guid.Empty)
  698. {
  699. DisplayAlert("Error", "Unable to create new consignment", "OK");
  700. Navigation.PopAsync();
  701. }
  702. }
  703. catch { }
  704. }
  705. }
  706. private Consignment SetConsignmentNumber(Consignment newConsignment, CoreTable table)
  707. {
  708. List<int> numbers = new List<int>();
  709. foreach (CoreRow row in table.Rows)
  710. {
  711. string number = row.Values[0].ToString();
  712. if (number.Contains(" From PO"))
  713. {
  714. int index = number.IndexOf(" From PO");
  715. string firstSubstring = number.Substring(0, index);
  716. string secondSubString = firstSubstring.Substring(3, firstSubstring.Length - 3);
  717. try
  718. {
  719. int i = int.Parse(secondSubString);
  720. numbers.Add(i);
  721. }
  722. catch { }
  723. }
  724. }
  725. numbers.Sort();
  726. int lastInt = numbers.Last();
  727. lastInt++;
  728. newConsignment.Number = "APP" + lastInt.ToString() + " From PO" + PONumber;
  729. return newConsignment;
  730. }
  731. Columns<PurchaseOrderItem> columns = new Columns<PurchaseOrderItem>(x => x.ID, //0
  732. x => x.PurchaseOrderLink.PONumber, //1
  733. x => x.Consignment.Number, //2
  734. x => x.Job.Name, //3
  735. x => x.Job.JobNumber, //4
  736. x => x.Description, //5
  737. x => x.Qty, //6
  738. x => x.Consignment.ID, //7
  739. x => x.PurchaseOrderLink.ID, //8
  740. x => x.ReceivedDate, //9
  741. x => x.Job.ID, //10
  742. x => x.SupplierCode, //11
  743. x => x.Product.ID, //12
  744. x => x.Product.NonStock, //13
  745. x => x.Style.ID, //14
  746. x => x.Style.Code, //15
  747. x => x.Style.Description, //16
  748. x => x.Product.DefaultLocation.ID, //17
  749. x => x.Product.DefaultLocation.Description, //18
  750. x => x.Product.DefaultLocation.Code, //19
  751. x => x.Dimensions.Unit.ID, //20
  752. x => x.Dimensions.Quantity, //21
  753. x => x.Dimensions.Length, //22
  754. x => x.Dimensions.Width, //23
  755. x => x.Dimensions.Height, //24
  756. x => x.Dimensions.Weight, //25
  757. x => x.Dimensions.Value, //26
  758. x => x.Dimensions.UnitSize, //27
  759. x => x.Cost //28
  760. );
  761. }
  762. #endregion
  763. }
  764. #region Classes
  765. public class POItemShell
  766. {
  767. public Guid ID { get; set; }
  768. public string PONumber { get; set; }
  769. public string ConsignmentNumber { get; set; }
  770. public string Description { get; set; }
  771. public Guid ConsignmentID { get; set; }
  772. public Guid POID { get; set; }
  773. public double ExpectedQty { get; set; }
  774. public Color Color { get; set; }
  775. public double ReceivedQty { get; set; }
  776. public bool HasQAForm { get; set; }
  777. public bool IsReadyForQA { get; set; }
  778. public Color QATextColor { get; set; }
  779. public Color QABtnColor { get; set; }
  780. public Guid DigitalFormID { get; set; }
  781. public DateTime FormCompleted { get; set; }
  782. public DateTime ReceivedDate { get; set; }
  783. public string SupplierCode { get; set; }
  784. public Guid ProductID { get; set; }
  785. public bool Nonstock { get; set; }
  786. public Guid JobID { get; set; }
  787. public string JobName { get; set; }
  788. public string JobNumber { get; set; }
  789. public Guid StyleID { get; set; }
  790. public string StyleCode { get; set; }
  791. public string StyleDescription { get; set; }
  792. public Guid StockLocationID { get; set; }
  793. public string StockLocationDescription { get; set; }
  794. public string StockLocationCode { get; set; }
  795. public bool ImageVisible { get; set; }
  796. public ImageSource ImageSource { get; set; }
  797. public double LastRowHeight { get; set; }
  798. public double Cost { get; set; }
  799. public Guid DimensionsUnitID { get; set; }
  800. public double DimensionsQuantity { get; set; }
  801. public double DimensionsLength { get; set; }
  802. public double DimensionsWidth { get; set; }
  803. public double DimensionsHeight { get; set; }
  804. public double DimensionsWeight { get; set; }
  805. public double DimensionsValue { get; set; }
  806. public string DimensionsUnitSize { get; set; }
  807. public POItemShell()
  808. {
  809. ID = Guid.Empty;
  810. PONumber = string.Empty;
  811. ConsignmentNumber = string.Empty;
  812. JobID = Guid.Empty;
  813. JobName = string.Empty;
  814. JobNumber = string.Empty;
  815. Description = string.Empty;
  816. ConsignmentID = Guid.Empty;
  817. POID = Guid.Empty;
  818. ExpectedQty = 0;
  819. Color = Color.Default;
  820. ReceivedQty = 0;
  821. HasQAForm = false;
  822. IsReadyForQA = false;
  823. QATextColor = Color.LightGray;
  824. DigitalFormID = Guid.Empty;
  825. FormCompleted = DateTime.MinValue;
  826. ReceivedDate = DateTime.MinValue;
  827. SupplierCode = string.Empty;
  828. ProductID = Guid.Empty;
  829. Nonstock = false;
  830. StyleID = Guid.Empty;
  831. StyleCode = string.Empty;
  832. StyleDescription = string.Empty;
  833. StockLocationID = Guid.Empty;
  834. StockLocationCode = "";
  835. StockLocationDescription = "";
  836. ImageVisible = false;
  837. ImageSource = "";
  838. LastRowHeight = 0;
  839. DimensionsUnitID = Guid.Empty;
  840. DimensionsQuantity = 0;
  841. DimensionsLength = 0;
  842. DimensionsWidth = 0;
  843. DimensionsHeight = 0;
  844. DimensionsWeight = 0;
  845. DimensionsValue = 0;
  846. DimensionsUnitSize = "";
  847. Cost = 0.0;
  848. }
  849. public POItemShell DuplicateNewShell(POItemShell poitemshell)
  850. {
  851. POItemShell shell = new POItemShell
  852. {
  853. ID = poitemshell.ID,
  854. PONumber = poitemshell.PONumber,
  855. ConsignmentNumber = poitemshell.ConsignmentNumber,
  856. JobID = poitemshell.JobID,
  857. JobName = poitemshell.JobName,
  858. JobNumber = poitemshell.JobNumber,
  859. Description = poitemshell.Description,
  860. ConsignmentID = poitemshell.ConsignmentID,
  861. POID = poitemshell.POID,
  862. ExpectedQty = poitemshell.ExpectedQty,
  863. Color = poitemshell.Color,
  864. ReceivedQty = poitemshell.ReceivedQty,
  865. HasQAForm = poitemshell.HasQAForm,
  866. IsReadyForQA = poitemshell.IsReadyForQA,
  867. QATextColor = poitemshell.QATextColor,
  868. QABtnColor = poitemshell.QABtnColor,
  869. DigitalFormID = poitemshell.DigitalFormID,
  870. FormCompleted = poitemshell.FormCompleted,
  871. ReceivedDate = poitemshell.ReceivedDate,
  872. SupplierCode = poitemshell.SupplierCode,
  873. ProductID = poitemshell.ProductID,
  874. Nonstock = poitemshell.Nonstock,
  875. StyleID = poitemshell.StyleID,
  876. StyleCode = poitemshell.StyleCode,
  877. StyleDescription = poitemshell.StyleDescription,
  878. StockLocationID = poitemshell.StockLocationID,
  879. StockLocationCode = poitemshell.StockLocationCode,
  880. StockLocationDescription = poitemshell.StockLocationDescription,
  881. ImageVisible = poitemshell.ImageVisible,
  882. ImageSource = poitemshell.ImageSource,
  883. LastRowHeight = poitemshell.LastRowHeight,
  884. DimensionsUnitID = poitemshell.DimensionsUnitID,
  885. DimensionsQuantity = poitemshell.DimensionsQuantity,
  886. DimensionsLength = poitemshell.DimensionsLength,
  887. DimensionsWidth = poitemshell.DimensionsWidth,
  888. DimensionsHeight = poitemshell.DimensionsHeight,
  889. DimensionsWeight = poitemshell.DimensionsWeight,
  890. DimensionsValue = poitemshell.DimensionsValue,
  891. DimensionsUnitSize = poitemshell.DimensionsUnitSize,
  892. Cost = poitemshell.Cost
  893. };
  894. return shell;
  895. }
  896. }
  897. #endregion