using Google.Protobuf; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel.DataAnnotations.Schema; using System.Drawing; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using System.Windows.Media.Imaging; using Tango.BL.ActionLogs; using Tango.BL.Builders; using Tango.BL.Enumerations; using Tango.BL.FineTuning; using Tango.BL.Interfaces; using Tango.BL.ValueObjects; using Tango.Core; using Tango.Core.ExtensionMethods; using Tango.Logging; using Tango.PMR.Exports; namespace Tango.BL.Entities { public partial class Job : JobBase { private double _lastLength; #region Constructors /// /// Initializes a new instance of the class. /// public Job() : base() { VectorFineTuningRunModel = new VectorFineTuningRunModel(); } /// /// Initializes a new instance of the class. /// public Job(DateTime creationDate) : this() { CreationDate = creationDate; } #endregion #region Events /// /// Occurs when the job total segments length has changed. /// public event EventHandler LengthChanged; #endregion #region Properties /// /// Gets the total job segments length. /// [NotMapped] [JsonIgnore] public double Length { get { _lastLength = GetLength(); return _lastLength; } } /// /// Gets the total job segments length multiplied by number of units if it is an embroidery job. /// [NotMapped] [JsonIgnore] public double LengthIncludingNumberOfUnits { get { _lastLength = GetLength(); var l = _lastLength * Math.Max(NumberOfUnits, 1); if (EnableInterSegment && NumberOfUnits > 1) { l += ((NumberOfUnits - 1) * InterSegmentLength); } return l; } } [NotMapped] [JsonIgnore] public double LengthIncludingNumberOfUnitsAndSpools { get { if (Machine.Type == MachineTypes.Eureka) { if (NumberOfSpools >= 4) { return LengthIncludingNumberOfUnits * NumberOfSpools; } } return LengthIncludingNumberOfUnits; } } [NotMapped] [JsonIgnore] public double WeightIncludingNumberOfUnits { get { if (Rml == null) return 0; var gramPerlength = Rml.GetGramPer1000mLength; var weight = (LengthIncludingNumberOfUnits * gramPerlength) / (1000);//(g) return weight; } } [NotMapped] [JsonIgnore] public double WeightIncludingNumberOfUnitsAndSpools { get { if (Machine.Type == MachineTypes.Eureka) { if (NumberOfSpools >= 4) { return WeightIncludingNumberOfUnits * NumberOfSpools; } } return WeightIncludingNumberOfUnits; } } [NotMapped] [JsonIgnore] public Int32 NumberOfUnitsMultipliedBySpools { get { if (Machine.Type == MachineTypes.Eureka) { if (NumberOfSpools >= 4) { return NumberOfUnits * NumberOfSpools; } } return NumberOfUnits; } } [NotMapped] [JsonIgnore] public double WeightNumberOfUnits { get { _lastLength = GetLength(); var l = _lastLength * Math.Max(NumberOfUnits, 1); if (EnableInterSegment && NumberOfUnits > 1) { l += ((NumberOfUnits - 1) * InterSegmentLength); } return l; } } /// /// Gets or sets the job property as enum instead of int. /// [NotMapped] [JsonIgnore] public JobStatuses JobStatus { get { return (JobStatuses)Status; } set { Status = value.ToInt32(); RaisePropertyChangedAuto(); } } /// /// Gets or sets the origin of the job. /// [NotMapped] [JsonIgnore] public JobSource JobSource { get { return (JobSource)Source; } set { Source = value.ToInt32(); RaisePropertyChangedAuto(); } } /// /// Gets or sets the job property as enum instead of int. /// [NotMapped] [JsonIgnore] public JobTypes JobType { get { return (JobTypes)Type; } set { Type = value.ToInt32(); RaisePropertyChangedAuto(); } } /// /// Gets or sets the job property as a property. /// [NotMapped] [JsonIgnore] public bool IsAllSegmentsPerSpool { get { return ((SpoolsDistributions)SpoolsDistribution) == SpoolsDistributions.AllSegments; } set { SpoolsDistribution = value ? SpoolsDistributions.AllSegments.ToInt32() : SpoolsDistributions.SingleSegment.ToInt32(); RaisePropertyChangedAuto(); } } /// /// Gets or sets the effective segments. /// [NotMapped] [JsonIgnore] public ObservableCollection EffectiveSegments { get { var segments = OrderedSegmentsWithGroups; if (EnableInterSegment && IsAllSegmentsPerSpool) { //int max = Segments.Max(x => x.SegmentIndex); int max = segments.Max(x => x.SegmentIndex); ObservableCollection effectiveSegments = new ObservableCollection(); foreach (var s in segments) { if (s is Segment) { Segment segment = s as Segment; effectiveSegments.Add(segment); if (s.SegmentIndex != max) { effectiveSegments.Add(CreateInterSegment(InterSegmentLength)); } } else if (s is SegmentsGroup) { SegmentsGroup segmentsGroup = s as SegmentsGroup; List groupSegments = segmentsGroup.Segments.ToList(); for (int repeats = 0; repeats < segmentsGroup.Repeats; repeats++) { for (int i = 0; i < groupSegments.Count; i++) { if (repeats > 0) { effectiveSegments.Add(groupSegments[i].Clone()); } else effectiveSegments.Add(groupSegments[i]); if (EnableInterSegment && !(repeats == (segmentsGroup.Repeats - 1) && i == (groupSegments.Count - 1))) { effectiveSegments.Add(CreateInterSegment(InterSegmentLength)); } } } if (EnableInterSegment && segmentsGroup.SegmentIndex != max) { effectiveSegments.Add(CreateInterSegment(InterSegmentLength)); } } } //foreach (var s in Segments.ToList().OrderBy(x => x.SegmentIndex)) //{ // effectiveSegments.Add(s); // if (s.SegmentIndex != max) // { // effectiveSegments.Add(CreateInterSegment(InterSegmentLength)); // } //} return effectiveSegments; } else { ObservableCollection effectiveSegments = new ObservableCollection(); foreach (var s in segments) { if (s is Segment) { effectiveSegments.Add(s as Segment); } else if (s is SegmentsGroup) { SegmentsGroup segmentsGroup = s as SegmentsGroup; List groupSegments = segmentsGroup.Segments.ToList(); for (int repeats = 0; repeats < segmentsGroup.Repeats; repeats++) { for (int i = 0; i < groupSegments.Count; i++) { if (repeats > 0) { effectiveSegments.Add(groupSegments[i].Clone()); } else effectiveSegments.Add(groupSegments[i]); } } } } return effectiveSegments; //return Segments.OrderBy(x => x.SegmentIndex).ToObservableCollection(); } } } /// /// Gets the ordered segments. /// [NotMapped] [JsonIgnore] public ObservableCollection OrderedSegments { get { return Segments.OrderBy(x => x.SegmentIndex).ToObservableCollection(); } } /// /// Gets the ordered segments and groups /// [NotMapped] [JsonIgnore] public ObservableCollection OrderedSegmentsWithGroups { get { if (Segments == null) return null; List orderedSegmentsWithGroups = new List(); orderedSegmentsWithGroups.AddRange(Segments.Where(x => x.SegmentsGroupGuid == null)); orderedSegmentsWithGroups.AddRange(SegmentsGroups); return orderedSegmentsWithGroups.OrderBy(x => x.SegmentIndex).ToObservableCollection(); // return Segments.OrderBy(x => x.SegmentIndex).ToObservableCollection(); } } /// /// Gets or sets the job fine tuning status. /// [NotMapped] [JsonIgnore] public FineTuningStatuses JobFineTuningStatus { get { return (FineTuningStatuses)FineTuningStatus; } set { FineTuningStatus = value.ToInt32(); RaisePropertyChangedAuto(); } } /// /// Gets or sets the job sample dye status. /// [NotMapped] [JsonIgnore] public SampleDyeStatuses JobSampleDyeStatus { get { return (SampleDyeStatuses)SampleDyeStatus; } set { SampleDyeStatus = value.ToInt32(); RaisePropertyChangedAuto(); } } private JobDesignations _designation; /// /// Gets or sets the designation. /// [NotMapped] [JsonIgnore] public JobDesignations Designation { get { return _designation; } set { _designation = value; RaisePropertyChangedAuto(); } } /// /// Gets or sets the state of the job editing. /// [NotMapped] [JsonIgnore] public EditingStates JobEditingState { get { return (EditingStates)EditingState; } set { EditingState = value.ToInt32(); RaisePropertyChangedAuto(); } } [NotMapped] [JsonIgnore] public double GramPerLength { get; set; } [NotMapped] [JsonIgnore] public String ThreadName { get { return Rml == null ? "" : Rml.DisplayName; } } #endregion #region Unmapped Fine Tuning [NotMapped] [JsonIgnore] public VectorFineTuningRunModel VectorFineTuningRunModel { get; set; } [NotMapped] [JsonIgnore] public double ResumeStartPosition { get; set; } #endregion #region Event Handlers /// /// Handles the CollectionChanged event of the Segments collection. /// /// The source of the event. /// The instance containing the event data. private void Segments_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { foreach (var segment in Segments.ToList()) { segment.PropertyChanged -= Segment_PropertyChanged; segment.PropertyChanged += Segment_PropertyChanged; } OnLengthChanged(); RaisePropertyChanged(nameof(EffectiveSegments)); } /// /// Handles the PropertyChanged event of all job segments. /// /// The source of the event. /// The instance containing the event data. private void Segment_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { if (e.PropertyName == nameof(Segment.Length)) { OnLengthChanged(); } else if (e.PropertyName == nameof(Segment.SegmentIndex)) { RaisePropertyChanged(nameof(EffectiveSegments)); } } #endregion #region Virtual Methods /// /// Called when the property has been changed /// protected virtual void OnLengthChanged() { if (_lastLength != GetLength()) { RaisePropertyChanged(nameof(Length)); RaisePropertyChanged(nameof(LengthIncludingNumberOfUnits)); LengthChanged?.Invoke(this, new EventArgs()); } } protected override void OnRmlChanged(Rml rml) { base.OnRmlChanged(rml); if (rml != null) { GramPerLength = Rml.GetGramPer1000mLength; } else GramPerLength = 0; RaisePropertyChanged(nameof(ThreadName)); } #endregion #region Override Methods /// /// Raises the property changed event. /// /// Name of the property. protected override void RaisePropertyChanged(string propName) { base.RaisePropertyChanged(propName); if (propName == nameof(Segments)) { if (Segments != null) { Segments.CollectionChanged -= Segments_CollectionChanged; Segments.CollectionChanged += Segments_CollectionChanged; OnLengthChanged(); RaisePropertyChanged(nameof(EffectiveSegments)); } } if (propName == nameof(InterSegmentLength) || propName == nameof(EnableInterSegment) || propName == nameof(SpoolsDistribution)) { OnLengthChanged(); RaisePropertyChanged(nameof(EffectiveSegments)); } if (propName == nameof(ColorSpace)) { //Make all brush stops the same color space if job color space is not null! if (ColorSpace != null) { Segments.SelectMany(x => x.BrushStops).ToList().ForEach(x => x.ColorSpace = ColorSpace); } } if (propName == nameof(NumberOfUnits)) { LengthChanged?.Invoke(this, new EventArgs()); } if (propName == nameof(LengthPercentageFactor)) { OnLengthChanged(); Segments.ToList().ForEach(x => x.RaiseLengthWithFactorChanged()); } if (InterSegmentLength < 1) { InterSegmentLength = 1; } } public override Job Clone() { Job cloned = base.Clone(); string copy = " - Copy"; int index = 1; string baseName = Name; if (this.Name.Contains(copy)) { int last = this.Name.LastIndexOf(copy); baseName = this.Name.Substring(0, last); string index_str = this.Name.Substring(last + copy.Length); if (!String.IsNullOrEmpty(index_str)) { int result; if (int.TryParse(index_str, out result)) index = result + 1; } } cloned.Name = baseName + copy + index; cloned.CreationDate = DateTime.UtcNow; cloned.IsSynchronized = false; cloned.LastRun = null; cloned.ColorSpace = ColorSpace; cloned.Customer = Customer; cloned.Rml = Rml; cloned.SpoolType = SpoolType; cloned.WindingMethod = WindingMethod; cloned.JobStatus = JobStatuses.Draft; cloned.Segments = Segments.Where(x => x.SegmentsGroupGuid == null).Select(x => x.Clone(cloned)).ToSynchronizedObservableCollection(); cloned.SegmentsGroups = SegmentsGroups.Select(x => x.Clone(cloned)).ToSynchronizedObservableCollection(); foreach (var segment in cloned.Segments) { segment.JobGuid = cloned.Guid; segment.Job = cloned; } return cloned; } #endregion #region Private Methods private double GetLength() { var segments = OrderedSegmentsWithGroups; if (segments == null || segments.Count == 0) return 0; double length = 0; int max = segments.Max(x => x.SegmentIndex); foreach (var s in segments) { if (s is Segment segment) { length += segment.LengthWithFactor + ((EnableInterSegment && IsAllSegmentsPerSpool && segment.SegmentIndex != max) ? InterSegmentLength : 0); } else if (s is SegmentsGroup segmentsGroup) { List groupSegments = segmentsGroup.Segments.ToList(); if (EnableInterSegment && IsAllSegmentsPerSpool) { for (int repeats = 0; repeats < segmentsGroup.Repeats; repeats++) { for (int i = 0; i < groupSegments.Count; i++) { length += groupSegments[i].LengthWithFactor; if (EnableInterSegment && !(repeats == (segmentsGroup.Repeats - 1) && i == (groupSegments.Count - 1))) { length += InterSegmentLength; } } } if (EnableInterSegment && segmentsGroup.SegmentIndex != max) { length += InterSegmentLength; } } else { length += (segmentsGroup.Segments.Sum(x => x.LengthWithFactor) * segmentsGroup.Repeats); } } } return length; } private double GetWeigth() { if (Rml == null) return 0; double length = GetLength(); var weight = (length * GramPerLength) / (1000);//length in m, return value in g return weight; } #endregion #region Public Methods public BitmapSource CreateSegmentsPie(double width, double height) { try { Bitmap bmp = new Bitmap((int)width, (int)height); using (Graphics g = Graphics.FromImage(bmp)) { g.Clear(Color.Transparent); g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High; g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; int fromAngle = -90; double totalLength = 0;//Segments.Sum(x => x.Length); //Excluding inter segment. foreach (var isegm in OrderedSegmentsWithGroups) { if (isegm is SegmentsGroup group) { foreach (var innerSegment in group.Segments) { totalLength += innerSegment.Length * group.Repeats; } } else if (isegm is Segment segment) { totalLength += segment.Length; } } foreach (var segm in OrderedSegmentsWithGroups) { if (segm is SegmentsGroup group) { for (int i = 0; i < group.Repeats; i++) { foreach (var innerSegment in group.Segments) { int toAngle = (int)((innerSegment.Length / totalLength) * 360d); Rectangle rect = new Rectangle(0, 0, bmp.Width - 2, bmp.Height - 2); g.FillPie(innerSegment.CreateGdiBrush(bmp.Width - 2, bmp.Height - 2), rect, fromAngle, toAngle); Pen pen = new Pen(Color.Gainsboro); g.DrawEllipse(pen, rect); pen.Dispose(); fromAngle += toAngle; } } } else if (segm is Segment segment) { int toAngle = (int)((segment.Length / totalLength) * 360d); Rectangle rect = new Rectangle(0, 0, bmp.Width - 2, bmp.Height - 2); g.FillPie(segment.CreateGdiBrush(bmp.Width - 2, bmp.Height - 2), rect, fromAngle, toAngle); Pen pen = new Pen(Color.Gainsboro); g.DrawEllipse(pen, rect); pen.Dispose(); fromAngle += toAngle; } } } var source = bmp.ToBitmapSource(); bmp.Dispose(); return source; } catch (Exception ex) { LogManager.Log(ex, $"Error occurred while trying to create job pie image for job '{Name}'."); return null; } } /// /// Adds a new solid segment. /// public Segment AddSolidSegment() { return AddSolidSegment(null); } /// /// Adds a new solid segment. /// public Segment AddSolidSegment(System.Windows.Media.Color? color) { return AddSolidSegment(color, 10); } /// /// Adds a new solid segment. /// public Segment AddSolidSegment(double length) { return AddSolidSegment(null, length); } /// /// Adds a new solid segment. /// public Segment AddSolidSegment(System.Windows.Media.Color? color, double length) { Segment segment = new Segment(); segment.Name = "Standard Segment"; if (OrderedSegmentsWithGroups.Count > 0) { segment.SegmentIndex = OrderedSegmentsWithGroups.Max(x => x.SegmentIndex) + 1; } else { segment.SegmentIndex = 1; } segment.Length = length; segment.Job = this; var stop = segment.AddBrushStop(); if (color != null) { stop.Color = color.Value; } Segments.Add(segment); return segment; } /// /// Adds a new gradient segment. /// public Segment AddGradientSegment() { return AddGradientSegment(10); } /// /// Adds a new gradient segment. /// public Segment AddGradientSegment(double length) { var segment = AddSolidSegment(length); //segment.BrushStops.Last().Color = System.Windows.Media.Colors.White; segment.AddBrushStop(); //segment.BrushStops.Last().Color = System.Windows.Media.Colors.White; return segment; } /// /// Gets the duration estimation for this job. /// /// The process parameters. /// public TimeSpan GetEstimatedDuration(ProcessParametersTable processParameters) { if (processParameters.DyeingSpeed == 0) { throw new ArgumentException("Process parameters dying speed cannot be zero."); } return TimeSpan.FromSeconds((LengthIncludingNumberOfUnits + processParameters.DryerBufferLengthMeters) / (processParameters.DyeingSpeed / 100d)); } ///// ///// Gets the duration estimation for this job. ///// ///// //public Task GetEstimatedDuration() //{ // return Task.Factory.StartNew(() => // { // var process = GetRecommendedProcessParameters().Result; // return GetEstimatedDuration(process); // }); //} /// /// Translates the job progress to time. /// /// The progress. /// The process parameters. /// public static TimeSpan TranslateProgressToTime(double progress, ProcessParametersTable processParameters) { return TimeSpan.FromSeconds(progress / (processParameters.DyeingSpeed / 100d)); } /// /// Creates an inter segment. /// /// The length. /// public static Segment CreateInterSegment(double length) { return new Segment() { IsInterSegment = true, Length = length, Name = "Inter Segment", BrushStops = new SynchronizedObservableCollection() { new BrushStop() { ColorSpace = new ColorSpace() { Name = "Volume" }, Color = System.Windows.Media.Colors.White, Red = 255, Green = 255, Blue = 255, L = 100, } }, }; } //public Task GetRecommendedProcessParameters() //{ // return Task.Factory.StartNew(() => // { // try // { // int index = ColorConversion.TangoColorConverter.GetLeastCommonProcessParametersTableIndex(Segments.SelectMany(x => x.BrushStops)); // if (index < Rml.GetActiveProcessGroup().ProcessParametersTables.Count) // { // return Rml.GetActiveProcessGroup().ProcessParametersTables[index]; // } // else // { // return Rml.GetActiveProcessGroup().ProcessParametersTables[0]; // } // } // catch (Exception ex) // { // throw new InvalidOperationException("Could not calculate the recommended process parameters for the job.", ex); // } // }); //} /// /// Creates a PMR job file from the this job based on its database data. /// /// public Task ToJobFile() { return Task.Factory.StartNew(() => { using (ObservablesContext db = ObservablesContext.CreateDefault()) { var job = new JobBuilder(db).Set(Guid).WithUser().WithRML().WithSegments().WithBrushStops().WithSegmentsGroups().Build(); var machine = new MachineBuilder(db).Set(job.MachineGuid).WithConfiguration().Build(); return CreateJobFile(job, machine); } }); } /// /// Creates a PMR job file based on the current state of the object. /// /// public JobFile ToJobFileWhenLoaded() { return CreateJobFile(this, Machine); } private static JobFile CreateJobFile(Job job, Machine machine) { var jobFile = new JobFile(); jobFile.ColorSpaceGuid = job.ColorSpaceGuid.ToStringOrEmpty(); jobFile.Customer = job.Customer != null ? job.Customer.Name : String.Empty; jobFile.Description = job.Description.ToStringOrEmpty(); if (job.HasEmbroideryFile) { jobFile.HasEmbroideryFile = job.HasEmbroideryFile; jobFile.EmbroideryFileData = ByteString.CopyFrom(job.EmbroideryFileData); jobFile.EmbroideryFileName = job.EmbroideryFileName; jobFile.EmbroideryJpeg = ByteString.CopyFrom(job.EmbroideryJpeg); } jobFile.EnableInterSegment = job.EnableInterSegment; jobFile.EnableLubrication = job.EnableLubrication; jobFile.InterSegmentLength = job.InterSegmentLength; jobFile.LengthPercentageFactor = job.LengthPercentageFactor; jobFile.Name = job.Name.ToStringOrEmpty(); jobFile.NumberOfUnits = job.NumberOfUnits; jobFile.RmlGuid = job.RmlGuid; jobFile.SampleUnitsOrMeters = job.SampleUnitsOrMeters; jobFile.SpoolsDistribution = job.SpoolsDistribution; jobFile.SpoolTypeGuid = job.SpoolTypeGuid; jobFile.Type = job.Type; jobFile.WindingMethodGuid = job.WindingMethodGuid; jobFile.ColorCatalogGuid = job.ColorCatalogGuid.ToStringOrEmpty(); jobFile.NumberOfSpools = job.NumberOfSpools; jobFile.Version = job.Version; foreach (var segm in job.OrderedSegmentsWithGroups) { JobFileSegment s = new JobFileSegment(); if (segm is SegmentsGroup group) { s.Repeats = group.Repeats; foreach (var innerSegment in group.Segments) { JobFileSegment innerFileSegment = new JobFileSegment(); innerFileSegment.Length = innerSegment.Length; innerFileSegment.Name = innerSegment.Name.ToStringOrEmpty(); FillFileSegmentStops(innerFileSegment, innerSegment, machine); s.Segments.Add(innerFileSegment); } } else if (segm is Segment segment) { s.Length = segment.Length; s.Name = segment.Name.ToStringOrEmpty(); FillFileSegmentStops(s, segment, machine); } jobFile.Segments.Add(s); } return jobFile; } private static void FillFileSegmentStops(JobFileSegment s, Segment segment, Machine machine) { foreach (var stop in segment.BrushStops.OrderBy(x => x.StopIndex)) { JobFileBrushStop st = new JobFileBrushStop(); stop.MapPropertiesTo(st, MappingFlags.NoReferenceTypes | MappingFlags.NoNullStrings); st.ColorCatalogItemGuid = stop.ColorCatalogsItemGuid.ToStringOrEmpty(); st.BestMatchR = stop.BestMatchR.HasValue ? stop.BestMatchR.Value : 0; st.BestMatchG = stop.BestMatchG.HasValue ? stop.BestMatchG.Value : 0; st.BestMatchB = stop.BestMatchB.HasValue ? stop.BestMatchB.Value : 0; foreach (var idsPack in machine.Configuration.NoneEmptyIdsPacks) { try { var volume = stop.GetVolume(idsPack.PackIndex); st.LiquidVolumes.Add(new JobFileLiquidVolume() { LiquidTypeName = idsPack.LiquidType.Name, Volume = volume, }); } catch (Exception ex) { throw new InvalidOperationException($"Error extracting liquid volume from ids pack {idsPack.PackIndex}", ex); } } s.BrushStops.Add(st); } } public static Task FromJobFile(JobFile jobFile, String machineGuid, String userGuid) { return Task.Factory.StartNew(() => { using (ObservablesContext db = ObservablesContext.CreateDefault()) { Machine machine; var job = new Job(); job.MachineGuid = machineGuid; job.UserGuid = userGuid; job.CreationDate = DateTime.UtcNow; try { machine = new MachineBuilder(db).Set(machineGuid).WithConfiguration().Build(); } catch { throw new ArgumentException("Error loading the machine details."); } if (!String.IsNullOrEmpty(jobFile.ColorSpaceGuid)) { var job_color_space = db.ColorSpaces.SingleOrDefault(x => x.Guid == jobFile.ColorSpaceGuid); if (job_color_space == null) throw new ArgumentException("Could not load the specified job file. Job color space could not be located on database."); job.ColorSpaceGuid = jobFile.ColorSpaceGuid; } if (!String.IsNullOrEmpty(jobFile.ColorCatalogGuid)) { var job_color_catalog = db.ColorCatalogs.SingleOrDefault(x => x.Guid == jobFile.ColorCatalogGuid); if (job_color_catalog == null) throw new ArgumentException("Could not load the specified job file. Job color catalog could not be located on database."); job.ColorCatalogGuid = jobFile.ColorCatalogGuid; } var job_customer = db.Customers.FirstOrDefault(x => x.Name == jobFile.Customer); if (job_customer != null) { job.CustomerGuid = job_customer.Guid; } job.Description = jobFile.Description.ToNullIfEmpty(); if (jobFile.HasEmbroideryFile) { job.HasEmbroideryFile = jobFile.HasEmbroideryFile; job.EmbroideryFileData = jobFile.EmbroideryFileData.ToByteArray(); job.EmbroideryFileName = jobFile.EmbroideryFileName; job.EmbroideryJpeg = jobFile.EmbroideryJpeg.ToByteArray(); } job.EnableInterSegment = jobFile.EnableInterSegment; job.EnableLubrication = jobFile.EnableLubrication; job.InterSegmentLength = jobFile.InterSegmentLength; job.LengthPercentageFactor = jobFile.LengthPercentageFactor; job.Name = jobFile.Name.ToNullIfEmpty(); job.NumberOfUnits = jobFile.NumberOfUnits; job.NumberOfSpools = jobFile.NumberOfSpools; job.Version = jobFile.Version; var job_rml = db.Rmls.SingleOrDefault(x => x.Guid == jobFile.RmlGuid); if (job_rml == null) throw new ArgumentException("Could not load the specified job file. Job media type could not be located on database."); job.RmlGuid = jobFile.RmlGuid; job.SampleUnitsOrMeters = jobFile.SampleUnitsOrMeters; job.SpoolsDistribution = jobFile.SpoolsDistribution; var job_spool_type = db.SpoolTypes.SingleOrDefault(x => x.Guid == jobFile.SpoolTypeGuid); if (job_spool_type == null) throw new ArgumentException("Could not load the specified job file. Job spool type could not be located on database."); job.SpoolTypeGuid = jobFile.SpoolTypeGuid; job.Type = jobFile.Type; var job_winding_method = db.WindingMethods.Single(x => x.Guid == jobFile.WindingMethodGuid); if (job_winding_method == null) throw new ArgumentException("Could not load the specified job file. Job winding method could not be located on database."); job.WindingMethodGuid = jobFile.WindingMethodGuid; for (int i = 0; i < jobFile.Segments.Count; i++) { var segment = jobFile.Segments[i]; if (segment.IsGroup()) { SegmentsGroup group = new SegmentsGroup(); group.JobGuid = job.Guid; group.SegmentIndex = i + 1; group.Repeats = segment.Repeats; job.SegmentsGroups.Add(group); for (int innerSegmentIndex = 0; innerSegmentIndex < segment.Segments.Count; innerSegmentIndex++) { var innerSegment = segment.Segments[innerSegmentIndex]; Segment s = new Segment(); s.JobGuid = job.Guid; s.Name = innerSegment.Name.ToNullIfEmpty(); s.Length = innerSegment.Length; s.SegmentIndex = innerSegmentIndex + 1; group.Segments.Add(s); FillSegmentStops(innerSegment, s, db, machine); } } else { Segment s = new Segment(); s.JobGuid = job.Guid; s.Name = segment.Name.ToNullIfEmpty(); s.Length = segment.Length; s.SegmentIndex = i + 1; job.Segments.Add(s); FillSegmentStops(segment, s, db, machine); } } return job; } }); } private static void FillSegmentStops(JobFileSegment segment, Segment s, ObservablesContext db, Machine machine) { for (int j = 0; j < segment.BrushStops.Count; j++) { var stop = segment.BrushStops[j]; var stop_color_space = db.ColorSpaces.SingleOrDefault(x => x.Guid == stop.ColorSpaceGuid); if (stop_color_space == null) throw new ArgumentException("Could not load the specified job file. Job brush stop color space could not be located on database."); BrushStop st = new BrushStop(); st.StopIndex = stop.StopIndex; st.SegmentGuid = s.Guid; stop.MapPropertiesTo(st, MappingFlags.NoReferenceTypes | MappingFlags.NoNullStrings); foreach (var volume in stop.LiquidVolumes) { var idsPack = machine.Configuration.NoneEmptyIdsPacks.SingleOrDefault(x => x.LiquidType.Name == volume.LiquidTypeName); if (idsPack == null) { throw new InvalidOperationException($"Liquid type '{volume.LiquidTypeName}' is not configured on the target machine."); } st.SetVolume(idsPack.PackIndex, volume.Volume); } if (!String.IsNullOrWhiteSpace(stop.ColorCatalogGuid)) { var stop_color_catalog = db.ColorCatalogs.SingleOrDefault(x => x.Guid == stop.ColorCatalogGuid); if (stop_color_catalog == null) throw new ArgumentException("Could not load the specified job file. Job brush stop color catalog could not be located on database."); stop.ColorCatalogGuid = stop_color_catalog.Guid; } if (!String.IsNullOrWhiteSpace(stop.ColorCatalogItemGuid)) { var stop_color_catalog_item = db.ColorCatalogsItems.SingleOrDefault(x => x.Guid == stop.ColorCatalogItemGuid); if (stop_color_catalog_item == null) throw new ArgumentException("Could not load the specified job file. Job brush stop catalog color could not be located on database."); st.ColorCatalogsItemGuid = stop.ColorCatalogItemGuid; } s.BrushStops.Add(st); } s.UpdateMiddleColorBrush(); } /// /// Removes this entity and all dependent entities from the specified db context. /// /// The context. public override void Delete(ObservablesContext context) { base.Delete(context); Segments.ToList().ForEach(x => x.Delete(context)); SegmentsGroups.ToList().ForEach(x => x.Delete(context)); context.Jobs.Remove(this); } #endregion #region Validation protected override void OnValidating(ObservablesContext context) { base.OnValidating(context); if (String.IsNullOrWhiteSpace(Name)) { InsertError(nameof(Name), "Job name is required"); } if (Name != null && Name.Length > 100) { InsertError(nameof(Name), "The job name exceeds the maximum allowed characters."); } } #endregion } }