using Sarand.BusinessMgr.Net.Standard.Base.App; using Sarand.BusinessMgr.Net.Standard.Base.Core; using Sarand.Net.Standard.Base.Bus; using Sarand.Net.Standard.Base.Core; using Sarand.Net.Standard.Base.Utils; using System; using System.Collections.Generic; namespace Sarand.BusinessMgr.Net.Standard.Base.Bus { //======================================================================= public abstract class SbmMovement : SbmHierarchyItem { //------------------------------------------------------------------- // Columns. public enum Column { Hidden, Pos, Id, //Movement. ItemType, ItemType_Desc, ItemId, Type_Desc, Movement, MovementDate, MovementTime, DiaryEntry, Quantity, MovementIdSource, SourceItemType, SourceItemId, SourceItem, SourceItemPos, // Commodity. Commodity_Code, Commodity_DescBrief, // Container. Container_Reference, Container_DescBrief, Container_TagId, Container_Notes, Container_Status, Container_Item_ItemType, Container_Item_ItemId, Container_Item_Quantity, Container_Item_Status, // Location. LocationIdFrom, LocationFrom_CategoryDesc, LocationFrom_Code, LocationFrom_Name, LocationIdTo, LocationTo_CategoryDesc, LocationTo_Code, LocationTo_Name, // Common properties. Notes, Flag, Status, Status_Desc, Status_Ind, CreateOn_Date, UpdateOn_Date, } //------------------------------------------------------------------- /// Properties other than common. public class DataProperties { public Sbm.ItemType ItemType { get; set; } = Sbm.ItemType.Unknown; public SysId ItemId { get; set; } = new SysId(); public Sbm.MovementType MovementType { get; set; } = Sbm.MovementType.Unknown; public DateTime Movement { get; set; } = DateTime.MinValue; public SysId LocationIdFrom { get; set; } = new SysId(); public SysId LocationIdTo { get; set; } = new SysId(); public decimal Quantity { get; set; } = 0.0m; public SysId MovementIdSource { get; set; } = new SysId(); public Sbm.ItemType ItemTypeSource { get; set; } = Sbm.ItemType.Unknown; public SysId ItemIdSource { get; set; } = new SysId(); } // Data. public new class Data : SacsHierarchyItem.Data { // Data members. private readonly DataProperties data = new DataProperties(); // Construction. public Data() { Status = DefaultStatus; } public Sbm.ItemType ItemType { get { return data.ItemType; } set { CheckChanged((int)data.ItemType, (int)value); data.ItemType = value; } } public SysId ItemId { get { return data.ItemId; } set { CheckChanged(data.ItemId, value); data.ItemId = value; } } public Sbm.MovementType MovementType { get { return data.MovementType; } set { CheckChanged((int)data.MovementType, (int)value); data.MovementType = value; } } public DateTime Movement { get { return data.Movement; } set { CheckChanged(data.Movement, value); data.Movement = value; } } public SysId LocationIdFrom { get { return data.LocationIdTo; } set { CheckChanged(data.LocationIdTo, value); data.LocationIdTo = value; } } public SysId LocationIdTo { get { return data.LocationIdTo; } set { CheckChanged(data.LocationIdTo, value); data.LocationIdTo = value; } } public decimal Quantity { get { return data.Quantity; } set { CheckChanged(data.Quantity, value); data.Quantity = value; } } public SysId MovementIdSource { get { return data.MovementIdSource; } set { CheckChanged(data.MovementIdSource, value); data.MovementIdSource = value; } } public Sbm.ItemType ItemTypeSource { get { return data.ItemTypeSource; } set { CheckChanged((int)data.ItemTypeSource, (int)value); data.ItemTypeSource = value; } } public SysId ItemIdSource { get { return data.ItemIdSource; } set { CheckChanged(data.ItemIdSource, value); data.ItemIdSource = value; } } internal void PopulateFrom(Data data) { ItemType = data.ItemType; ItemId = data.ItemId; MovementType = data.MovementType; Movement = data.Movement; LocationIdFrom = data.LocationIdFrom; LocationIdTo = data.LocationIdTo; Quantity = data.Quantity; MovementIdSource = data.MovementIdSource; ItemTypeSource = data.ItemTypeSource; ItemIdSource = data.ItemIdSource; base.PopulateFrom(data); } public Data Clone() { Data data = new Data(); data.PopulateFrom(this); return data; } } public new class ErrField : SacsHierarchyItem.ErrField { // Identifies the field that has invalid data. public ValidValue ItemType { get; set; } = ValidValue.Valid; public ValidValue ItemId { get; set; } = ValidValue.Valid; public ValidValue MovementType { get; set; } = ValidValue.Valid; public ValidValue Movement { get; set; } = ValidValue.Valid; public ValidValue LocationIdFrom { get; set; } = ValidValue.Valid; public ValidValue LocationIdTo { get; set; } = ValidValue.Valid; public ValidValue Quantity { get; set; } = ValidValue.Valid; public ValidValue MovementIdSource { get; set; } = ValidValue.Valid; public ValidValue ItemTypeSource { get; set; } = ValidValue.Valid; public ValidValue ItemIdSource { get; set; } = ValidValue.Valid; } //------------------------------------------------------------------- // Data members. private readonly Data data = new Data(); public static readonly Byte Flag_DiaryEntry = 0x01; //------------------------------------------------------------------- // Construction. protected SbmMovement(SysId id, Sbm.ItemType itemType, SysId itemId, Sbm.MovementType movementType) : base(id) { base.SetData(data); ItemType = itemType; ItemId = itemId; MovementType = movementType; Status = DefaultStatus; } //------------------------------------------------------------------- // Movement status. private static readonly List movementStatuses = new List() { SaStatus.Awaiting, SaStatus.Actioned, SaStatus.Cancelled, }; public static SaStatus DefaultStatus { get { return SaStatus.Current; } } public static List MovementStatuses { get { return new List(movementStatuses); } } public static DataValue.TriStateType GetStatusTriState(SaStatus status) { switch (status) { case SaStatus.Actioned: return DataValue.TriStateType.Green; case SaStatus.Awaiting: return DataValue.TriStateType.Amber; case SaStatus.Cancelled: return DataValue.TriStateType.Red; case SaStatus.Deleted: return DataValue.TriStateType.Purple; } return DataValue.TriStateType.Unknown; } //------------------------------------------------------------------- // Utilities. public SbmItemId GetItemId() { return new SbmItemId(Sbm.ItemType.Movement, Id); } //------------------------------------------------------------------- // Properties. public Data GetData() { return data.Clone(); } public void SetData(Data data) { // Properties that cannot be changed if previously specified. if (SysId.IsValid(Id) && SysId.ToInt(Id) != SysId.ToInt(data.Id)) throw new NotSupportedException($"{SysUtil.Fn} Id cannot be changed"); // Populate individual properties to ensure that 'Changed' indicator is kept up to date. this.data.PopulateFrom(data); } //------------------------------------------------------------------- // Attributes. public Sbm.ItemType ItemType { get { return data.ItemType; } set { data.ItemType = value; } } public SysId ItemId { get { return data.ItemId; } set { data.ItemId = value; } } public Sbm.MovementType MovementType { get { return data.MovementType; } set { data.MovementType = value; } } public DateTime Movement { get { return data.Movement; } set { data.Movement = value; } } public SysId LocationIdFrom { get { return data.LocationIdTo; } set { data.LocationIdTo = value; } } public SysId LocationIdTo { get { return data.LocationIdTo; } set { data.LocationIdTo = value; } } public decimal Quantity { get { return data.Quantity; } set { data.Quantity = value; } } public SysId MovementIdSource { get { return data.MovementIdSource; } set { data.MovementIdSource = value; } } public Sbm.ItemType ItemTypeSource { get { return data.ItemTypeSource; } set { data.ItemTypeSource = value; } } public SysId ItemIdSource { get { return data.ItemIdSource; } set { data.ItemIdSource = value; } } //------------------------------------------------------------------- // Flags. public bool DiaryEntry { get { return GetFlag(Flag_DiaryEntry); } set { SetFlag(Flag_DiaryEntry, value); } } //------------------------------------------------------------------- // A s s o c i a t e d D a t a E l e m e n t s //------------------------------------------------------------------- public virtual bool HasMovements() { return true; } //------------------------------------------------------------------- // P a r a m s //------------------------------------------------------------------- /// Parameters - used to define the filters that should be applied to a List of Movements // List parameters. public enum StatusCat { Any, AwaitingOnly, ActionedOnly, /// Awaiting or Actioned. AwaitingOrActioned, CancelledOnly, NotDeleted, DeletedOnly } /// /// Item list parameters. /// public new class Params : SacsHierarchyItem.Params { // List filtering. public HashSet IdsIncluded { get; } = new HashSet(); public HashSet IdsExcluded { get; } = new HashSet(); // Movement. public Sbm.ItemType ItemType { get; set; } public Sbm.ItemType ItemTypeSource { get; set; } public HashSet ItemIds { get; set; } public HashSet ItemIdsSource { get; set; } public Sbm.ItemType ContainerItemType { get; set; } public SysId ContainerItemId { get; set; } public HashSet ItemIdSource { get; set; } public bool ExcludeProvisionalContainers { get; set; } = true; public Sbm.MovementType MovementType { get; set; } public DateTime MovementFrom { get; set; } public DateTime MovementTo { get; set; } public SysId LocationId { get; set; } public SysId LocationIdFrom { get; set; } public SysId LocationIdTo { get; set; } public bool RestrictToSalesStockLocations { get; set; } public bool RestrictToCalculateStockLocations { get; set; } public bool IncludeRequirementsForTransactions { get; set; } public SysId MovementIdSource { get; set; } /// Movement status. public StatusCat StatusCat { get; set; } = StatusCat.NotDeleted; } //------------------------------------------------------------------- } //======================================================================= // M o v e m e n t D a t a L i s t //======================================================================= public static class SbmMovementList { //------------------------------------------------------------------- /// Sort the list by movement date. public enum SortMode { MovementSortAscend, MovementSortDescend }; public static int CompareMovementByMovementDate(SbmMovement movement1, SbmMovement movement2, bool ascending) { if (movement1 != null || movement2 != null) return -1; return movement1.Movement.CompareTo(movement2.Movement) * (ascending ? 1 : -1); } public static void Sort(this List values, SortMode movementSort) { if (movementSort == SortMode.MovementSortAscend) values.Sort( delegate (SbmMovement movement1, SbmMovement movement2) { return CompareMovementByMovementDate(movement1, movement2, true); } ); else if (movementSort == SortMode.MovementSortDescend) values.Sort( delegate (SbmMovement movement1, SbmMovement movement2) { return CompareMovementByMovementDate(movement1, movement2, false); } ); } //------------------------------------------------------------------- // Finding. public static bool Find(this List values, SbmMovement movement) { if (movement == null) return false; return values.Exists(item => item == movement); } public static bool FindById(this List values, SysId id) { if (!SysId.IsValid(id)) return false; return values.Exists(item => item.Id.Equals(id)); } public static bool FindByDateStatus(this List values, DateTime movementOn, SaStatus saStatus, int iPos) { if (!DateUtil.IsValid(movementOn)) return false; return values.Exists(item => item.Movement.Date.Equals(movementOn.Date) && item.Status.Equals(saStatus)); } public static bool FindByStatus(this List values, SaStatus saStatus) { //if (saStatus == null) return false; return values.Exists(item => item.Status.Equals(saStatus)); } //------------------------------------------------------------------- // Calculate quantity: public static decimal GetQuantityByStatus(this List values, SaStatus saStatus) { decimal quantity = 0.0m; foreach (SbmMovement movementItem in values) { if (movementItem.ItemType == Sbm.ItemType.Commodity && movementItem.Status == saStatus) quantity += movementItem.Quantity; } return quantity; } //------------------------------------------------------------------- // Count items in the list: public static int GetCountByStatus(this List values, SaStatus saStatus) { int iCount = 0; foreach (SbmMovement movementItem in values) { if (movementItem.Status == saStatus) iCount++; } return iCount; } //------------------------------------------------------------------- } //======================================================================= }