StockMovementPage.xaml.cs 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq.Expressions;
  4. using Comal.Classes;
  5. using InABox.Core;
  6. using Xamarin.Forms;
  7. namespace PRS.Mobile
  8. {
  9. public delegate void SaveMovementEvent(StockMovement movement);
  10. public partial class StockMovementPage
  11. {
  12. private StockMovement _movement = null;
  13. private StockHolding _holding = null;
  14. private StockMovementBatchType _type = StockMovementBatchType.Stocktake;
  15. public event SaveMovementEvent OnSaveMovement;
  16. double _qty = 0.0F;
  17. bool firstNotification = true;
  18. public StockMovementPage(StockHolding holding, StockMovement movement, ImageSource src, StockMovementBatchType type)
  19. {
  20. _holding = holding;
  21. _movement = movement;
  22. _type = type;
  23. InitializeComponent();
  24. StyleReadOnlyRow.Height = type != StockMovementBatchType.Transfer ? new GridLength(1.0, GridUnitType.Auto) : new GridLength(0.0, GridUnitType.Absolute);
  25. StyleRow.Height = type == StockMovementBatchType.Transfer ? new GridLength(1.0, GridUnitType.Auto) : new GridLength(0.0, GridUnitType.Absolute);
  26. ChangeStyle.IsVisible = type == StockMovementBatchType.Transfer;
  27. JobReadOnlyRow.Height = (type != StockMovementBatchType.Issue) && (type != StockMovementBatchType.Transfer) ? new GridLength(1.0, GridUnitType.Auto) : new GridLength(0.0, GridUnitType.Absolute);
  28. JobRow.Height = (type == StockMovementBatchType.Issue) || (type == StockMovementBatchType.Transfer) ? new GridLength(1.0, GridUnitType.Auto) : new GridLength(0.0, GridUnitType.Absolute);
  29. ChangeJob.IsVisible = (type == StockMovementBatchType.Issue) || (type == StockMovementBatchType.Transfer);
  30. LocationRow.Height = type == StockMovementBatchType.Transfer ? new GridLength(1.0, GridUnitType.Auto) : new GridLength(0.0, GridUnitType.Absolute);
  31. ChangeLocation.IsVisible = type == StockMovementBatchType.Transfer;
  32. ToolbarItems.Clear();
  33. ToolbarItems.Add(new ToolbarItem("Save", "", () =>
  34. {
  35. _movement.Received = 0.0F;
  36. _movement.Issued = 0.0F;
  37. if (_type == StockMovementBatchType.Issue)
  38. _movement.Issued = _qty;
  39. else if (_type == StockMovementBatchType.Receipt)
  40. _movement.Received = _qty;
  41. else if (_type == StockMovementBatchType.Transfer)
  42. _movement.Received = _qty;
  43. else
  44. {
  45. if (_qty < _holding.Units)
  46. _movement.Issued = _holding.Units - _qty;
  47. else
  48. _movement.Received = _qty - _holding.Units;
  49. }
  50. OnSaveMovement?.Invoke(_movement);
  51. Navigation.PopAsync();
  52. }));
  53. Title = String.Format("{0}: {1}",type.ToString(),holding.Product.Code);
  54. if (src != null)
  55. {
  56. Image.Source = src;
  57. ImageFrame.IsVisible = true;
  58. }
  59. else
  60. NoImageFrame.IsVisible = true;
  61. Description.Text = holding.Product.Name;
  62. StyleReadOnly.Text = String.Format("{0}: {1}", _movement.Style.Code, _movement.Style.Description);
  63. ChangeStyle.Text = String.Format("{0}: {1}", _movement.Style.Code, _movement.Style.Description);
  64. JobReadOnly.Text = _movement.Job.ID != Guid.Empty ? String.Format("{0}: {1}", _movement.Job.JobNumber, _movement.Job.Name) : "General Stock";
  65. ChangeJob.Text = _movement.Job.ID != Guid.Empty ? String.Format("{0}: {1}", _movement.Job.JobNumber, _movement.Job.Name) : "General Stock";
  66. ChangeLocation.Text = String.Format("{0}: {1}", _movement.Location.Code, _movement.Location.Description);
  67. _qty = type == StockMovementBatchType.Stocktake
  68. ? _holding.Units + movement.Received - movement.Issued
  69. : type == StockMovementBatchType.Issue
  70. ? movement.Issued
  71. : type == StockMovementBatchType.Receipt
  72. ? movement.Received
  73. : movement.Issued;
  74. Qty.Text = _qty.ToString();
  75. Qty.Placeholder = type == StockMovementBatchType.Stocktake
  76. ? "On Hand"
  77. : type == StockMovementBatchType.Issue
  78. ? "Issue"
  79. : type == StockMovementBatchType.Receipt
  80. ? "Receive"
  81. : "Transfer";
  82. }
  83. protected override void OnAppearing()
  84. {
  85. base.OnAppearing();
  86. firstNotification = true;
  87. }
  88. private void UpdateQty(double delta, bool update)
  89. {
  90. bool bOK = double.TryParse(Qty.Text, out double qty);
  91. if (bOK)
  92. {
  93. qty += delta;
  94. if (qty < 0.0F && _type == StockMovementBatchType.Stocktake) qty = 0.0F;
  95. if (qty < 0.0F && firstNotification)
  96. {
  97. firstNotification = false;
  98. DisplayAlert("Warning", "Are you correcting a mistake by using negative values? It will be flagged in the system as a correction.", "OK");
  99. _movement.Notes = _movement.Notes + "Transaction is a mistake correction. ";
  100. }
  101. _qty = qty;
  102. if (update)
  103. Qty.Text = qty.ToString();
  104. Qty.BackgroundColor = Color.WhiteSmoke;
  105. }
  106. else
  107. Qty.BackgroundColor = Color.LightSalmon;
  108. }
  109. void Qty_TextChanged(System.Object sender, Xamarin.Forms.TextChangedEventArgs e)
  110. {
  111. UpdateQty(0.0F, false);
  112. }
  113. void More_Clicked(System.Object sender, System.EventArgs e)
  114. {
  115. UpdateQty(1.0F, true);
  116. }
  117. void Less_Clicked(System.Object sender, System.EventArgs e)
  118. {
  119. UpdateQty(-1.0F, true);
  120. }
  121. void Job_Clicked(System.Object sender, System.EventArgs e)
  122. {
  123. GenericSelectionPage page = new GenericSelectionPage(
  124. "Select Job",
  125. new SelectionViewModel<Job>(
  126. new Filter<Job>(X => X.JobStatus.Active).IsEqualTo(true),
  127. new Expression<Func<Job, object>>[] { X => X.JobNumber, X => X.Name },
  128. new Expression<Func<Job, object>>[] { },
  129. new SortOrder<Job>(x => x.JobNumber)
  130. )
  131. );
  132. page.OnItemSelected += (o,e) => {
  133. var job = e.Row.ToObject<Job>();
  134. _movement.Job.ID = job.ID;
  135. _movement.Job.Synchronise(job);
  136. Dispatcher.BeginInvokeOnMainThread(() =>
  137. {
  138. ChangeJob.Text = job.ID != Guid.Empty ? String.Format("{0}: {1}", job.JobNumber, job.Name) : "General Stock";
  139. });
  140. };
  141. Navigation.PushAsync(page);
  142. }
  143. void Style_Clicked(System.Object sender, System.EventArgs e)
  144. {
  145. GenericSelectionPage page = new GenericSelectionPage(
  146. "Select Style",
  147. new SelectionViewModel<ProductStyle>(
  148. null,
  149. new Expression<Func<ProductStyle, object>>[] { X => X.Code, X => X.Description },
  150. new Expression<Func<ProductStyle, object>>[] { },
  151. new SortOrder<ProductStyle>(x => x.Code)
  152. )
  153. );
  154. page.OnItemSelected += (o,e) => {
  155. var style = e.Row.ToObject<ProductStyle>();
  156. _movement.Style.ID = style.ID;
  157. _movement.Style.Synchronise(style);
  158. Dispatcher.BeginInvokeOnMainThread(() =>
  159. {
  160. ChangeStyle.Text = String.Format("{0}: {1}", style.Code, style.Description);
  161. });
  162. };
  163. Navigation.PushAsync(page);
  164. }
  165. void Location_Clicked(System.Object sender, System.EventArgs e)
  166. {
  167. GenericSelectionPage page = new GenericSelectionPage(
  168. "Select Location",
  169. new SelectionViewModel<StockLocation>(
  170. new Filter<StockLocation>(X => X.Active).IsEqualTo(true),
  171. new Expression<Func<StockLocation, object>>[] { X => X.Code, X => X.Description },
  172. new Expression<Func<StockLocation, object>>[] { },
  173. new SortOrder<StockLocation>(x => x.Code)
  174. )
  175. );
  176. page.OnItemSelected += (o,e) => {
  177. var location = e.Row.ToObject<StockLocation>();
  178. _movement.Location.ID = location.ID;
  179. _movement.Location.Synchronise(location);
  180. Dispatcher.BeginInvokeOnMainThread(() =>
  181. {
  182. ChangeLocation.Text = String.Format("{0}: {1}", location.Code, location.Description);
  183. });
  184. };
  185. Navigation.PushAsync(page);
  186. }
  187. }
  188. }