2using System.ComponentModel;
4using System.Xml.Serialization;
5using LotSizingDataModel.Core.Common;
6using LotSizingDataModel.Core.PhysicalModel;
23[XmlType(TypeName =
"distributionDecision")]
28 private int _distributionCenterId;
31 private WarehouseReference _warehouse =
34 private DoubleTimeSeries _deliveredQuantities =
37 private DoubleTimeSeries _backlogLevels =
40 private DoubleTimeSeries _shortageQuantities =
52 SubscribeToObject(_warehouse);
53 SubscribeToObject(_deliveredQuantities);
54 SubscribeToObject(_backlogLevels);
55 SubscribeToObject(_shortageQuantities);
75 int distributionCenterId,
77 WarehouseReference warehouse,
81 if (distributionCenterId <= 0)
83 throw new ArgumentOutOfRangeException(
84 nameof(distributionCenterId),
86 "The distribution-center identifier must be " +
87 "strictly positive.");
92 throw new ArgumentOutOfRangeException(
95 "The item identifier must be strictly positive.");
98 ArgumentNullException.ThrowIfNull(warehouse);
100 if (planningHorizon <= 0)
102 throw new ArgumentOutOfRangeException(
103 nameof(planningHorizon),
105 "The planning horizon must be strictly positive.");
109 distributionCenterId;
120 [XmlAttribute(
"distributionCenterId")]
123 get => _distributionCenterId;
133 throw new ArgumentOutOfRangeException(
136 "The distribution-center identifier " +
137 "cannot be negative.");
141 ref _distributionCenterId,
149 [XmlAttribute(
"itemId")]
160 throw new ArgumentOutOfRangeException(
163 "The item identifier cannot be negative.");
176 [XmlElement(
"warehouse")]
182 ArgumentNullException.ThrowIfNull(value);
191 UnsubscribeFromObject(_warehouse);
197 SubscribeToObject(_warehouse);
199 NotifyDerivedProperties();
210 [XmlElement(
"deliveredQuantities")]
213 get => _deliveredQuantities;
216 ArgumentNullException.ThrowIfNull(value);
219 _deliveredQuantities,
225 UnsubscribeFromObject(
226 _deliveredQuantities);
229 ref _deliveredQuantities,
233 _deliveredQuantities);
235 NotifyDerivedProperties();
249 [XmlElement(
"backlogLevels")]
252 get => _backlogLevels;
255 ArgumentNullException.ThrowIfNull(value);
264 UnsubscribeFromObject(
274 NotifyDerivedProperties();
289 [XmlElement(
"shortageQuantities")]
292 get => _shortageQuantities;
295 ArgumentNullException.ThrowIfNull(value);
304 UnsubscribeFromObject(
305 _shortageQuantities);
308 ref _shortageQuantities,
312 _shortageQuantities);
314 NotifyDerivedProperties();
332 BacklogLevels.PeriodCount ==
334 ShortageQuantities.PeriodCount ==
345 double.IsFinite(quantity) &&
356 double.IsFinite(backlog) &&
367 double.IsFinite(shortage) &&
376 Warehouse.ReferenceId > 0;
425 ValidateNonNegativeFiniteValue(
460 ValidateNonNegativeFiniteValue(
495 ValidateNonNegativeFiniteValue(
520 int distributionCenterId,
522 WarehouseReference warehouse)
524 ArgumentNullException.ThrowIfNull(warehouse);
527 distributionCenterId &&
549 throw new ArgumentOutOfRangeException(
552 "The period count cannot be negative.");
567 NotifyDerivedProperties();
579 NotifyDerivedProperties();
585 double totalDeliveredQuantity =
588 double finalBacklog =
593 double totalShortage =
597 $
"Distribution center {DistributionCenterId}, " +
598 $
"item {ItemId}, warehouse " +
599 $
"{FormatWarehouse(Warehouse)}: " +
600 $
"delivered {totalDeliveredQuantity}; " +
601 $
"final backlog {finalBacklog}; " +
602 $
"shortage {totalShortage}";
605 private void SubscribeToObject(
606 ModelObject modelObject)
608 modelObject.PropertyChanged +=
609 OnNestedPropertyChanged;
612 private void UnsubscribeFromObject(
613 ModelObject modelObject)
615 modelObject.PropertyChanged -=
616 OnNestedPropertyChanged;
619 private void OnNestedPropertyChanged(
621 PropertyChangedEventArgs eventArgs)
623 NotifyDerivedProperties();
626 private void NotifyDerivedProperties()
650 private static bool SameWarehouse(
651 WarehouseReference first,
652 WarehouseReference second)
660 private static string FormatWarehouse(
661 WarehouseReference warehouse)
664 $
"{warehouse.Kind}:{warehouse.ReferenceId}";
667 private static void ValidateNonNegativeFiniteValue(
669 string parameterName)
671 if (!
double.IsFinite(value) ||
674 throw new ArgumentOutOfRangeException(
677 "The value must be finite and non-negative.");
DoubleTimeSeries ShortageQuantities
Gets or sets the quantities of demand that are definitively not fulfilled during each planning period...
DistributionDecision(int distributionCenterId, int itemId, WarehouseReference warehouse, int planningHorizon)
Initializes a distribution decision for a distribution center, an item, a warehouse and a planning ho...
void SetBacklogLevel(int period, double backlog)
Sets the backlog level at the end of a planning period.
int PlanningHorizon
Gets the number of planning periods represented by the delivered-quantity series.
bool HasValidWarehouse
Gets a value indicating whether the warehouse reference is initialized.
DoubleTimeSeries DeliveredQuantities
Gets or sets the quantities delivered to customers during each planning period.
double GetBacklogLevel(int period)
Gets the backlog level at the end of a planning period.
DistributionDecision()
Initializes an empty distribution decision.
double GetDeliveredQuantity(int period)
Gets the quantity delivered during a planning period.
WarehouseReference Warehouse
Gets or sets the warehouse from which the item is delivered.
bool HasValidDeliveredQuantities
Gets a value indicating whether every delivered quantity is finite and non-negative.
DoubleTimeSeries BacklogLevels
Gets or sets the outstanding demand at the end of each planning period.
void SetDeliveredQuantity(int period, double quantity)
Sets the quantity delivered during a planning period.
int ItemId
Gets or sets the identifier of the distributed item.
void ResizeTimeSeries(int periodCount)
Resizes every decision series to the specified planning horizon.
bool HasValidBacklogLevels
Gets a value indicating whether every backlog level is finite and non-negative.
void Clear()
Resets every distribution decision value to zero.
int DistributionCenterId
Gets or sets the identifier of the distribution center.
double GetShortageQuantity(int period)
Gets the shortage quantity for a planning period.
bool HasConsistentPlanningHorizon
Gets a value indicating whether all decision series use the same planning horizon.
bool IsInternallyValid
Gets a value indicating whether the distribution decision is internally consistent.
override string ToString()
bool Matches(int distributionCenterId, int itemId, WarehouseReference warehouse)
Determines whether this decision identifies the specified distribution center, item and warehouse.
bool HasValidShortageQuantities
Gets a value indicating whether every shortage quantity is finite and non-negative.
void SetShortageQuantity(int period, double shortage)
Sets the shortage quantity for a planning period.