using System; using System.Linq; using System.Linq.Expressions; using InABox.Core; namespace Comal.Classes { /// /// An assignment represents an anticipated booking for an employee, much like a diary entry /// /// [UserTracking("Assignments")] [Caption("Assignments")] public class Assignment : Entity, IPersistent, IRemotable, INumericAutoIncrement, IOneToMany, IOneToMany, IOneToMany, ILicense, IJobActivity, IOneToMany, IJobScopedItem { [IntegerEditor(Editable = Editable.Hidden)] [EditorSequence(1)] public int Number { get; set; } [DateEditor] [EditorSequence(2)] public DateTime Date { get; set; } [EntityRelationship(DeleteAction.Cascade)] [EditorSequence(3)] public EmployeeLink EmployeeLink { get; set; } // [EntityRelationship(DeleteAction.Cascade)] // [EditorSequence(4)] // public EquipmentLink Equipment { get; set; } [TextBoxEditor] [EditorSequence(5)] public string Title { get; set; } [MemoEditor] [EditorSequence(6)] public string Description { get; set; } [EditorSequence(7)] public AssignmentActivityLink ActivityLink { get; set; } private class KanbanLookup : LookupDefinitionGenerator { public override Filter DefineFilter(Assignment[] items) { if (items == null || !items.Any()) return LookupFactory.DefineFilter(); return new Filter(x => x.Closed).IsEqualTo(DateTime.MinValue).And(x => x.EmployeeLink.ID) .IsEqualTo(items.First().EmployeeLink.ID); } public override Columns DefineFilterColumns() => Columns.None().Add(x => x.EmployeeLink.ID); } [LookupDefinition(typeof(KanbanLookup))] [EditorSequence(8)] [EntityRelationship(DeleteAction.SetNull)] public KanbanLink Task { get; set; } [EditorSequence(9)] public JobLink JobLink { get; set; } private class JobITPLookup : LookupDefinitionGenerator { public override Filter DefineFilter(Assignment[] items) { if (items.Length == 1) return new Filter(x => x.Job.ID).IsEqualTo(items.First().JobLink.ID); return LookupFactory.DefineFilter(); } public override Columns DefineFilterColumns() => Columns.None().Add(x => x.JobLink.ID); } [LookupDefinition(typeof(JobITPLookup))] [EditorSequence(10)] public JobITPLink ITP { get; set; } [NullEditor] [Obsolete("Replaced with Actual.Start", true)] public TimeSpan Start { get; set; } [NullEditor] [Obsolete("Replaced with Actual.Duration", true)] public TimeSpan Duration { get; set; } [NullEditor] [Obsolete("Replaced with Actual.Finish", true)] public TimeSpan Finish { get; set; } [EditorSequence(11)] [CoreTimeEditor] public TimeBlock Booked { get; set; } [EditorSequence(12)] [CoreTimeEditor] public TimeBlock Actual { get; set; } [TimestampEditor] [RequiredColumn] [EditorSequence(13)] public DateTime Completed { get; set; } [EditorSequence("Processing",1)] public ActualCharge Charge { get; set; } [TimestampEditor] [EditorSequence("Processing",2)] public DateTime Processed { get; set; } [NullEditor] [EntityRelationship(DeleteAction.Cascade)] public LeaveRequestLink LeaveRequestLink { get; set; } [NullEditor] public DeliveryLink Delivery { get; set; } [NullEditor] [EntityRelationship(DeleteAction.SetNull)] public InvoiceLink Invoice { get; set; } [NullEditor] public MeetingDetails Meeting { get; set; } private class JobScopeLookup : LookupDefinitionGenerator { public override Filter DefineFilter(Assignment[] items) { var item = items?.Length == 1 ? items[0] : null; if (item != null) return new Filter(x => x.Job.ID).IsEqualTo(item.JobLink.ID).And(x => x.Status.Approved).IsEqualTo(true); return new Filter(x => x.ID).None(); } public override Columns DefineFilterColumns() => Columns.None().Add(x => x.JobLink.ID); } [LookupDefinition(typeof(JobScopeLookup))] public JobScopeLink JobScope { get; set; } public Expression> AutoIncrementField() { return x => x.Number; } public Filter AutoIncrementFilter() { return null; } public static TimeSpan EffectiveTime(TimeSpan actual, TimeSpan booked) => actual.Ticks != 0L ? actual : booked; public TimeSpan EffectiveStartTime() { return EffectiveTime(Actual.Start, Booked.Start); } public DateTime EffectiveStart() { return Date.Add(EffectiveStartTime()); } public TimeSpan EffectiveFinishTime() { // If we have an actual finish, always use that // otherwise use EffectiveStart() + booked.duration return EffectiveTime( Actual.Finish, EffectiveTime(Actual.Start, Booked.Start) .Add(Booked.Duration) ); } public DateTime EffectiveFinish() { return Date.Add( EffectiveFinishTime() ); } static Assignment() { LinkedProperties.Register(ass => ass.ActivityLink.Charge, chg => chg.Chargeable, ass => ass.Charge.Chargeable); Classes.JobScope.LinkScopeProperties(); } } }