ManufacturingPacket.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Linq.Expressions;
  5. using InABox.Core;
  6. namespace Comal.Classes
  7. {
  8. public class ManufacturingPacketArea : IFormula<ManufacturingPacket, object>
  9. {
  10. public Expression<Func<ManufacturingPacket, object>> Value => x => x.Height;
  11. public Expression<Func<ManufacturingPacket, object>>[] Modifiers =>
  12. new Expression<Func<ManufacturingPacket, object>>[] { x => x.Width, x => 0.000001m };
  13. public FormulaOperator Operator => FormulaOperator.Multiply;
  14. public FormulaType Type => FormulaType.Virtual;
  15. }
  16. public class ManufacturingPacketVolume : IFormula<ManufacturingPacket, object>
  17. {
  18. public Expression<Func<ManufacturingPacket, object>> Value => x => x.Height;
  19. public Expression<Func<ManufacturingPacket, object>>[] Modifiers => new Expression<Func<ManufacturingPacket, object>>[]
  20. { x => x.Width, x => x.Length, x => 0.000000001m };
  21. public FormulaOperator Operator => FormulaOperator.Multiply;
  22. public FormulaType Type => FormulaType.Virtual;
  23. }
  24. public class ManufacturingPacketTime : CoreAggregate<ManufacturingPacket, ManufacturingPacketStage, TimeSpan>
  25. {
  26. public override Expression<Func<ManufacturingPacketStage, TimeSpan>> Aggregate => x => x.Time;
  27. public override AggregateCalculation Calculation => AggregateCalculation.Sum;
  28. public override Dictionary<Expression<Func<ManufacturingPacketStage, object>>, Expression<Func<ManufacturingPacket, object>>> Links =>
  29. new Dictionary<Expression<Func<ManufacturingPacketStage, object>>, Expression<Func<ManufacturingPacket, object>>>()
  30. {
  31. { ManufacturingPacketStage => ManufacturingPacketStage.Parent.ID, ManufacturingPacket => ManufacturingPacket.ID }
  32. };
  33. }
  34. public class ManufacturingPacketTimeRemaining : CoreAggregate<ManufacturingPacket, ManufacturingPacketStage, TimeSpan>
  35. {
  36. public override Expression<Func<ManufacturingPacketStage, TimeSpan>> Aggregate => x => x.TimeRemaining;
  37. public Expression<Func<ManufacturingPacketStage, Guid>> Link => x => x.Parent.ID;
  38. public override AggregateCalculation Calculation => AggregateCalculation.Sum;
  39. public override Dictionary<Expression<Func<ManufacturingPacketStage, object>>, Expression<Func<ManufacturingPacket, object>>> Links =>
  40. new Dictionary<Expression<Func<ManufacturingPacketStage, object>>, Expression<Func<ManufacturingPacket, object>>>()
  41. {
  42. { ManufacturingPacketStage => ManufacturingPacketStage.Parent.ID, ManufacturingPacket => ManufacturingPacket.ID }
  43. };
  44. }
  45. public class ManufacturingPacketActualTime : CoreAggregate<ManufacturingPacket, ManufacturingHistory, TimeSpan>
  46. {
  47. public override Expression<Func<ManufacturingHistory, TimeSpan>> Aggregate => x => x.WorkDuration;
  48. public override AggregateCalculation Calculation => AggregateCalculation.Sum;
  49. public override Dictionary<Expression<Func<ManufacturingHistory, object>>, Expression<Func<ManufacturingPacket, object>>> Links =>
  50. new Dictionary<Expression<Func<ManufacturingHistory, object>>, Expression<Func<ManufacturingPacket, object>>>()
  51. {
  52. { ManufacturingHistory => ManufacturingHistory.Packet.ID, ManufacturingPacket => ManufacturingPacket.ID }
  53. };
  54. }
  55. [UserTracking("Manufacturing")]
  56. [Caption("Manufacturing")]
  57. public class ManufacturingPacket : Entity, IPersistent, IRemotable, IOneToMany<Setout>, ILicense<ManufacturingLicense>, IIssues
  58. {
  59. [TextBoxEditor]
  60. [EditorSequence(1)]
  61. public string Title { get; set; }
  62. [CodeEditor(Visible = Visible.Default, Editable = Editable.Enabled)]
  63. [EditorSequence(2)]
  64. public string Serial { get; set; }
  65. [EditorSequence(3)]
  66. [EntityRelationship(DeleteAction.Cascade)]
  67. public SetoutLink SetoutLink { get; set; }
  68. [EditorSequence(4)]
  69. public JobITPLink ITP { get; set; }
  70. [TextBoxEditor]
  71. [EditorSequence(5)]
  72. public string Location { get; set; }
  73. // Used to calculate time & materials
  74. [EditorSequence(7)]
  75. [IntegerEditor]
  76. public int Quantity { get; set; }
  77. [EditorSequence(8)]
  78. [IntegerEditor]
  79. // Determines # of barcodes to print
  80. public int BarcodeQty { get; set; }
  81. [EditorSequence(9)]
  82. [TimestampEditor(Editable = Editable.Hidden)]
  83. public override DateTime Created
  84. {
  85. get => base.Created;
  86. set => base.Created = value;
  87. }
  88. [EditorSequence(10)]
  89. [DateTimeEditor]
  90. public DateTime DueDate { get; set; }
  91. [EditorSequence("Design", 101)]
  92. [EntityRelationship(DeleteAction.Cascade)]
  93. public PDFDocumentLink Drawing { get; set; }
  94. // To be overlaid over the PDF document
  95. [EditorSequence("Design", 102)]
  96. [TextBoxEditor]
  97. public string WaterMark { get; set; }
  98. [EditorSequence("Design", 103)]
  99. public double Height { get; set; }
  100. [EditorSequence("Design", 104)]
  101. public double Width { get; set; }
  102. [EditorSequence("Design", 105)]
  103. public double Length { get; set; }
  104. [EditorSequence("Manufacturing", 200)]
  105. public ManufacturingTemplateLink ManufacturingTemplateLink { get; set; }
  106. [EditorSequence("Manufacturing", 201)]
  107. [TimestampEditor(Editable = Editable.Disabled)]
  108. public DateTime Issued { get; set; }
  109. [EditorSequence("Manufacturing", 202)]
  110. [LoggableProperty]
  111. public bool Priority { get; set; }
  112. [EditorSequence("Manufacturing", 203)]
  113. [LoggableProperty]
  114. public bool Distributed { get; set; }
  115. [EditorSequence("Manufacturing", 204)]
  116. [TextBoxEditor(Editable = Editable.Disabled)]
  117. public string Trolleys { get; set; }
  118. [EditorSequence("Manufacturing", 205)]
  119. [TimestampEditor(Editable = Editable.Hidden)]
  120. public DateTime BarcodePrinted { get; set; }
  121. [EditorSequence("Manufacturing", 206)]
  122. [DateTimeEditor(Editable = Editable.Disabled)]
  123. [SecondaryIndex]
  124. public DateTime Completed { get; set; }
  125. [SecondaryIndex]
  126. [TimestampEditor]
  127. [EditorSequence("Manufacturing", 207)]
  128. public DateTime Archived { get; set; } = DateTime.MinValue;
  129. [CheckBoxEditor]
  130. [EditorSequence("Issues", 2)]
  131. [LoggableProperty]
  132. public bool OnHold { get; set; }
  133. [MemoEditor]
  134. [EditorSequence("Issues", 1)]
  135. [LoggableProperty]
  136. public string Issues { get; set; }
  137. [NullEditor]
  138. public SetoutGroupLink SetoutGroup { get; set; }
  139. public override string ToString()
  140. {
  141. return string.Format("{0} {1}", SetoutLink.Number, Serial);
  142. }
  143. public static void Progress(IEnumerable<ManufacturingPacket> packets, ManufacturingPacketStage[] Stages)
  144. {
  145. //List<ManufacturingPacketStage> updates = new List<ManufacturingPacketStage>();
  146. foreach (var packet in packets.Where(x => !x.StageLink.Equals(CoreUtils.FullGuid)))
  147. {
  148. var stages = Stages.Where(x => x.Parent.ID.Equals(packet.ID));
  149. long sequence = 0;
  150. var stage = stages.FirstOrDefault(x => x.ID.Equals(packet.StageLink.ID));
  151. if (stage != null)
  152. {
  153. stage.Completed = DateTime.Now;
  154. stage.PercentageComplete = 100.0F;
  155. sequence = stage.Sequence;
  156. }
  157. // Update the pointer to the next stage
  158. stage = stages.Where(x => x.Sequence > sequence).FirstOrDefault();
  159. if (stage != null)
  160. {
  161. stage.QualityStatus = QualityStatus.NotChecked;
  162. stage.QualityNotes = "";
  163. stage.Station = 0;
  164. stage.Started = DateTime.MinValue;
  165. stage.Completed = DateTime.MinValue;
  166. stage.PercentageComplete = 0.0F;
  167. packet.StageLink.ID = stage.ID;
  168. packet.StageLink.Synchronise(stage);
  169. }
  170. else
  171. {
  172. packet.StageLink.ID = CoreUtils.FullGuid;
  173. }
  174. packet.Issued = !packet.StageLink.IsValid() ? DateTime.MinValue : packet.Issued.IsEmpty() ? DateTime.Now : packet.Issued;
  175. packet.Completed = packet.StageLink.ID.Equals(CoreUtils.FullGuid)
  176. ? packet.Completed.IsEmpty() ? DateTime.Now : packet.Completed
  177. : DateTime.MinValue;
  178. }
  179. }
  180. public static void Regress(IEnumerable<ManufacturingPacket> pkts, ManufacturingPacketStage[] stgs)
  181. {
  182. foreach(var packet in pkts)
  183. {
  184. var stages = stgs.Where(x => x.Parent.ID.Equals(packet.ID));
  185. var sequence = long.MaxValue;
  186. var stage = stages.FirstOrDefault(x => x.ID.Equals(packet.StageLink.ID));
  187. if (stage != null)
  188. {
  189. stage.Completed = DateTime.MinValue;
  190. stage.PercentageComplete = 0.0F;
  191. stage.QualityStatus = QualityStatus.NotChecked;
  192. stage.QualityNotes = "";
  193. sequence = stage.Sequence;
  194. }
  195. // Update the pointer to the previous stage
  196. stage = stages.Where(x => x.Sequence < sequence).LastOrDefault();
  197. if (stage != null)
  198. {
  199. stage.QualityStatus = QualityStatus.NotChecked;
  200. stage.QualityNotes = "";
  201. stage.Station = 0;
  202. stage.Started = DateTime.MinValue;
  203. stage.Completed = DateTime.MinValue;
  204. stage.PercentageComplete = 0.0F;
  205. }
  206. packet.StageLink.ID = stage == null ? Guid.Empty : stage.ID;
  207. packet.Issued = !packet.StageLink.IsValid() ? DateTime.MinValue : packet.Issued.IsEmpty() ? DateTime.Now : packet.Issued;
  208. packet.DueDate = packet.Issued.IsEmpty() ? DateTime.MinValue : packet.DueDate;
  209. packet.Completed = packet.StageLink.ID.Equals(CoreUtils.FullGuid)
  210. ? packet.Completed.IsEmpty() ? DateTime.Now : packet.Completed
  211. : DateTime.MinValue;
  212. }
  213. }
  214. #region Aggregates
  215. [EditorSequence(300)]
  216. [DoubleEditor(Editable = Editable.Hidden)]
  217. [Formula(typeof(ManufacturingPacketArea))]
  218. public double Area { get; set; }
  219. [EditorSequence(301)]
  220. [DoubleEditor(Editable = Editable.Hidden)]
  221. [Formula(typeof(ManufacturingPacketVolume))]
  222. public double Volume { get; set; }
  223. [EditorSequence(302)]
  224. [Aggregate(typeof(ManufacturingPacketTime))]
  225. public TimeSpan Time { get; set; }
  226. [EditorSequence(303)]
  227. [Aggregate(typeof(ManufacturingPacketTimeRemaining))]
  228. public TimeSpan TimeRemaining { get; set; }
  229. [EditorSequence(304)]
  230. [Aggregate(typeof(ManufacturingPacketActualTime))]
  231. public TimeSpan ActualTime { get; set; }
  232. #endregion
  233. #region Internal / NullEditor Properties
  234. [NullEditor]
  235. public ManufacturingPacketStageLink StageLink { get; set; }
  236. [NullEditor]
  237. public QAFormLink QAForm { get; set; }
  238. // I think ITPs will end up being linked to a stage,
  239. // So this might get obsoleted at some point
  240. [NullEditor]
  241. public JobStageLink JobStage { get; set; }
  242. [NullEditor]
  243. [EntityRelationship(DeleteAction.SetNull)]
  244. public PurchaseOrderItemLink OrderItem { get; set; }
  245. [NullEditor]
  246. public DateTime EstimatedDate { get; set; }
  247. #endregion
  248. #region Obsolete Properties
  249. // The code of the Linked Manufacturing Template
  250. // Suggested - set to obsolete?
  251. [NullEditor]
  252. [Obsolete("Replaced with ManufacturingTemplateLink.Code", true)]
  253. public string Code { get; set; }
  254. // The Factory to which this packet template belongs
  255. // Suggestion - Set to obsolete?
  256. [NullEditor]
  257. [Obsolete("Replaced with ManufacturingTemplateLink.FactoryLink.ID")]
  258. public string Group { get; set; }
  259. [NullEditor]
  260. [Obsolete("Replaced with BarcodeQty")]
  261. public bool GroupedBarcode { get; set; }
  262. private BarcodeType _barcodetype = BarcodeType.Unspecified;
  263. [NullEditor]
  264. [Obsolete("Replaced with BarcodeQty")]
  265. public BarcodeType BarcodeType
  266. {
  267. get => _barcodetype == BarcodeType.Unspecified ? GroupedBarcode ? BarcodeType.Grouped : BarcodeType.Individual : _barcodetype;
  268. set => _barcodetype = value;
  269. }
  270. // Comes from Setout.Title (Should be Reference)
  271. [NullEditor]
  272. [Obsolete("Replaced with SetoutLink.Reference")]
  273. public string Reference { get; set; }
  274. // Comes from Setout.Location
  275. [NullEditor]
  276. [Obsolete("Replaced with SetoutLink.Description")]
  277. public string Description { get; set; }
  278. [Obsolete("Replaced With ManufacturingTemplateLink")]
  279. [NullEditor]
  280. public Guid ManufacturingItemID { get; set; }
  281. [NullEditor]
  282. [Obsolete("Replaced with ManufacturingPacketLink.Code")]
  283. public string Template { get; set; }
  284. [Obsolete("Replaced With SetoutLink.JobLink")]
  285. [EntityRelationship(DeleteAction.Cascade)]
  286. [NullEditor]
  287. public JobLink JobLink { get; set; }
  288. #endregion
  289. #region Functions
  290. //public void MovePrevious()
  291. //{
  292. // bool bFound = false;
  293. // SetoutStage prev = null;
  294. // foreach (SetoutStage stage in Stages)
  295. // {
  296. // if (bFound)
  297. // {
  298. // stage.Started = DateTime.MinValue;
  299. // stage.Completed = DateTime.MinValue;
  300. // stage.PercentageComplete = 0.0F;
  301. // }
  302. // else if (stage.Completed.IsEmpty())
  303. // {
  304. // stage.Started = DateTime.MinValue;
  305. // stage.Completed = DateTime.MinValue;
  306. // stage.PercentageComplete = 0.0F;
  307. // bFound = true;
  308. // if (prev != null)
  309. // prev.Completed = DateTime.MinValue;
  310. // }
  311. // else
  312. // prev = stage;
  313. // }
  314. // if (prev == null)
  315. // Issued = DateTime.MinValue;
  316. // Completed = DateTime.MinValue;
  317. // Stage = CurrentStage();
  318. //}
  319. //public void MoveNext()
  320. //{
  321. // bool bFound = false;
  322. // bool bComplete = true;
  323. // if (Issued.IsEmpty())
  324. // Issued = DateTime.Now;
  325. // foreach (SetoutStage stage in Stages)
  326. // {
  327. // if (bFound)
  328. // {
  329. // stage.Started = DateTime.MinValue;
  330. // stage.Completed = DateTime.MinValue;
  331. // stage.PercentageComplete = 0.0F;
  332. // bComplete = false;
  333. // }
  334. // else if (stage.Started.IsEmpty())
  335. // {
  336. // //stage.Started = DateTime.Now;
  337. // stage.Completed = DateTime.MinValue;
  338. // stage.PercentageComplete = 0.0F;
  339. // bComplete = false;
  340. // bFound = true;
  341. // }
  342. // else if (stage.Completed.IsEmpty())
  343. // {
  344. // stage.Completed = DateTime.Now;
  345. // stage.PercentageComplete = 100.0F;
  346. // bFound = true;
  347. // }
  348. // }
  349. // //Completed = bComplete ? DateTime.Now : DateTime.MinValue;
  350. // bool bIsComplete = !Stages.Any(x => x.Completed.Equals(DateTime.MinValue));
  351. // if (bIsComplete && Completed.Equals(DateTime.MinValue))
  352. // Completed = DateTime.Now;
  353. // Stage = CurrentStage();
  354. //}
  355. //public Boolean IsComplete()
  356. //{
  357. // if ((!Issued.IsEmpty()) && (Stages != null))
  358. // {
  359. // foreach (SetoutStage stage in Stages)
  360. // {
  361. // if (stage.Completed.IsEmpty())
  362. // return false;
  363. // }
  364. // return true;
  365. // }
  366. // return false;
  367. //}
  368. //public String Status()
  369. //{
  370. // if ((Stages == null) || (!Stages.Any()))
  371. // return "No Template!";
  372. // if (Issued.IsEmpty())
  373. // return "To Be Issued";
  374. // var stage = GetCurrentStage();
  375. // if (stage != null)
  376. // {
  377. // if (!Archived.IsEmpty())
  378. // return "Cancelled";
  379. // else
  380. // return String.Format("{0} ({1:F2}%)", stage.Name, stage.PercentageComplete);
  381. // }
  382. // return "Complete";
  383. //}
  384. //public Guid CurrentStage()
  385. //{
  386. // if (Issued.IsEmpty())
  387. // return Guid.Empty;
  388. // SetoutStage stage = GetCurrentStage();
  389. // if (stage != null)
  390. // return stage.SectionID;
  391. // return CoreUtils.FullGuid;
  392. //}
  393. //public SetoutStage GetCurrentStage()
  394. //{
  395. // if ((!Issued.IsEmpty()) && (Stages != null))
  396. // {
  397. // foreach (SetoutStage stage in Stages)
  398. // {
  399. // if (stage.Completed.IsEmpty())
  400. // return stage;
  401. // }
  402. // }
  403. // return null;
  404. //}
  405. //public void SetStage(Guid id, bool complete = false)
  406. //{
  407. // bool bFound = id == Guid.Empty;
  408. // Issued = (id == Guid.Empty) ? DateTime.MinValue : Issued.IsEmpty() ? DateTime.Now : Issued;
  409. // if (id == CoreUtils.FullGuid)
  410. // {
  411. // foreach (SetoutStage stage in Stages)
  412. // {
  413. // stage.Started = stage.Started.IsEmpty() ? DateTime.Now : stage.Started;
  414. // stage.Completed = stage.Completed.IsEmpty() ? DateTime.Now : stage.Completed;
  415. // stage.PercentageComplete = 100.0F;
  416. // Completed = stage.Completed;
  417. // }
  418. // }
  419. // else
  420. // {
  421. // //Completed = DateTime.MinValue;
  422. // foreach (SetoutStage stage in Stages)
  423. // {
  424. // if (stage.SectionID.Equals(id))
  425. // {
  426. // bFound = true;
  427. // //stage.Started = stage.Started.IsEmpty() ? DateTime.Now : stage.Started;
  428. // stage.Completed = complete ? DateTime.Now : DateTime.MinValue;
  429. // stage.PercentageComplete = stage.Completed.IsEmpty() ? 0.0F : 100.0F;
  430. // }
  431. // else
  432. // {
  433. // if (!bFound)
  434. // {
  435. // // Stages Before this stage - Update Started and Completed if Empty
  436. // if (stage.Started.IsEmpty())
  437. // stage.Started = DateTime.Now;
  438. // if (stage.Completed.IsEmpty())
  439. // stage.Completed = DateTime.Now;
  440. // stage.PercentageComplete = 100.0F;
  441. // }
  442. // else
  443. // {
  444. // // Stages After This Stage - Blank out Started and Completed
  445. // stage.Started = DateTime.MinValue;
  446. // stage.Completed = DateTime.MinValue;
  447. // stage.PercentageComplete = 0.0F;
  448. // }
  449. // }
  450. // }
  451. // }
  452. // bool bIsComplete = !Stages.Any(x => x.Completed.Equals(DateTime.MinValue));
  453. // if (bIsComplete && Completed.Equals(DateTime.MinValue))
  454. // Completed = DateTime.Now;
  455. // Stage = CurrentStage();
  456. //}
  457. #endregion
  458. }
  459. }