| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221 | using System;using System.Collections.Generic;using System.Linq.Expressions;using InABox.Core;namespace Comal.Classes{    public class KanbanDocumentCount : CoreAggregate<Kanban, KanbanDocument, Guid>    {        public override Expression<Func<KanbanDocument, Guid>> Aggregate => x => x.ID;        public override AggregateCalculation Calculation => AggregateCalculation.Count;        public override Dictionary<Expression<Func<KanbanDocument, object>>, Expression<Func<Kanban, object>>> Links =>            new Dictionary<Expression<Func<KanbanDocument, object>>, Expression<Func<Kanban, object>>> ()            {                { KanbanDocument => KanbanDocument.EntityLink.ID, Kanban => Kanban.ID }            };    }    public class KanbaAssignmentDuration : CoreAggregate<Kanban, Assignment, TimeSpan>    {        public override Expression<Func<Assignment, TimeSpan>> Aggregate => x => x.Actual.Duration;        public override AggregateCalculation Calculation => AggregateCalculation.Sum;        public override Dictionary<Expression<Func<Assignment, object>>, Expression<Func<Kanban, object>>> Links =>            new Dictionary<Expression<Func<Assignment, object>>, Expression<Func<Kanban, object>>>()            {                { Assignment => Assignment.Task.ID, Kanban => Kanban.ID }            };    }    public enum KanbanStatus    {        Open,        InProgress,        Waiting,        Complete    }    [UserTracking("Task Management")]    [Caption("Tasks")]    public class Kanban : Entity, IPersistent, IRemotable, IKanban, IScheduleAction, IOneToMany<Schedule>, INumericAutoIncrement<Kanban>,        IOneToMany<Equipment>, ILicense<TaskManagementLicense>, IExportable, IImportable, IJobScopedItem    {        private bool bChanging;        [NullEditor]        public DeliveryLink Delivery { get; set; }        [IntegerEditor(Editable = Editable.Disabled)]        [EditorSequence(-1)]        public int Number { get; set; }        [TextBoxEditor]        [EditorSequence(0)]        public string Title { get; set; }        [EditorSequence(1)]        public JobLink JobLink { get; set; }        private class JobScopeLookup : LookupDefinitionGenerator<JobScope, Kanban>        {            public override Filter<JobScope> DefineFilter(Kanban[] items)            {                var item = items?.Length == 1 ? items[0] : null;                if (item != null)                    return new Filter<JobScope>(x => x.Job.ID).IsEqualTo(item.JobLink.ID).And(x => x.Status.Approved).IsEqualTo(true);                return new Filter<JobScope>(x => x.ID).None();            }            public override Columns<Kanban> DefineFilterColumns()                => Columns.None<Kanban>().Add(x => x.JobLink.ID);        }        [LookupDefinition(typeof(JobScopeLookup))]        [EditorSequence(2)]        public JobScopeLink JobScope { get; set; }        [RichTextEditor]        [EditorSequence(3)]        public string Description { get; set; }        [NotesEditor]        [EditorSequence(4)]        public string[] Notes { get; set; } = Array.Empty<string>();        [MemoEditor(Visible = Visible.Optional, Editable = Editable.Hidden)]        [EditorSequence(5)]        public string Summary { get; set; }        [EditorSequence(6)]        [Caption("Task Type")]        public KanbanTypeLink Type { get; set; }        [DateEditor]        [EditorSequence(7)]        public DateTime DueDate { get; set; } = DateTime.Today;        // Same lookup right now used for manager and employee.        private class EmployeeLookup : LookupDefinitionGenerator<Employee, Kanban>        {            public override Filter<Employee> DefineFilter(Kanban[] items)            {                var result = LookupFactory.DefineFilter<Employee>();                result.Ands.Add(new Filter<Employee>(x => x.CanAllocateTasks).IsEqualTo(true));                return result;            }            public override Columns<Kanban> DefineFilterColumns()                => Columns.None<Kanban>();        }        [LookupDefinition(typeof(EmployeeLookup))]        [EditorSequence(8)]        [Caption("Assigned To")]        public EmployeeLink EmployeeLink { get; set; }        [EditorSequence(9)]        [Caption("Allocated By")]        [LookupDefinition(typeof(EmployeeLookup))]        public EmployeeLink ManagerLink { get; set; }        [DateTimeEditor(Editable = Editable.Hidden)]        [EditorSequence(10)]        public DateTime Completed { get; set; } = DateTime.MinValue;        [EditorSequence("Other", 1)]        [Caption("Equipment Item")]        public EquipmentLink Equipment { get; set; }        [DateEditor]        [EditorSequence("Other", 2)]        public DateTime StartDate { get; set; } = DateTime.Today;        [DurationEditor]        [EditorSequence("Other", 3)]        public TimeSpan EstimatedTime { get; set; } = TimeSpan.FromHours(1);        [Aggregate(typeof(KanbaAssignmentDuration))]        [EditorSequence("Other", 4)]        public TimeSpan ActualTime { get; set; }        [CheckBoxEditor]        [EditorSequence("Other", 5)]        public bool Private { get; set; }        [EditorSequence("Other", 6)]        [CheckBoxEditor]        public bool Locked { get; set; }        [EditorSequence("Other", 7)]        [LoggableProperty]        [EnumLookupEditor(typeof(KanbanStatus))]        public KanbanStatus Status { get; set; }        [SecondaryIndex]        [NullEditor]        public DateTime Closed { get; set; } = DateTime.MinValue;        [NullEditor]        [Aggregate(typeof(KanbanDocumentCount))]        public int Attachments { get; set; }        [NullEditor]        [Obsolete("Replaced with Status",true)]        public string Category { get; set; }                public Expression<Func<Kanban, int>> AutoIncrementField()        {            return x => x.Number;        }        public Filter<Kanban>? AutoIncrementFilter()        {            return null;        }        [NullEditor]        public ScheduleLink ScheduleLink { get; set; }        private bool IsCompleted(object? value)        {            if (value == null)                return false;            if (value is DateTime dateTime)                return !dateTime.IsEmpty();            if (value is KanbanStatus category)                return category == KanbanStatus.Complete;            return false;        }        protected override void DoPropertyChanged(string name, object? before, object? after)        {            base.DoPropertyChanged(name, before, after);            if (bChanging)                return;            bChanging = true;            if (name.Equals(nameof(Completed))) // set the completed date            {                Status = IsCompleted(after) ? KanbanStatus.Complete : IsCompleted(Status) ? KanbanStatus.InProgress : Status;            }            else if (name.Equals(nameof(Status))) // set the completed date            {                Completed = IsCompleted(after) ? IsCompleted(Completed) ? Completed : DateTime.Now : DateTime.MinValue;            }            else if (name.Equals(nameof(Description)))            {                var summary = after as string;                Summary = CoreUtils.StripHTML(summary);            }            bChanging = false;        }        static Kanban()        {            Classes.JobScope.LinkScopeProperties<Kanban>();        }    }}
 |