2using System.Collections.Generic;
4using System.Xml.Serialization;
25[XmlRoot(
"supplyChain")]
26[XmlType(TypeName =
"supplyChain")]
31 private int _planningHorizon;
33 _periodicOperatingExpenditureBudget;
66 [XmlAttribute(
"planningHorizon")]
69 get => _planningHorizon;
76 [XmlElement(
"periodicOperatingExpenditureBudget")]
80 get => _periodicOperatingExpenditureBudget;
84 _periodicOperatingExpenditureBudget,
90 if (_periodicOperatingExpenditureBudget is not
null)
92 _periodicOperatingExpenditureBudget.PropertyChanged -=
93 OnFinancialParameterPropertyChanged;
96 _periodicOperatingExpenditureBudget = value;
98 if (_periodicOperatingExpenditureBudget is not
null)
102 _periodicOperatingExpenditureBudget
106 _periodicOperatingExpenditureBudget.PropertyChanged +=
107 OnFinancialParameterPropertyChanged;
121 [XmlElement(
"objectivePolicy")]
124 get => _objectivePolicy;
127 if (ReferenceEquals(_objectivePolicy, value))
132 value?.EnsureValid();
133 _objectivePolicy = value;
138 #region Logical subsystem
144 [XmlArrayItem(
"item")]
145 public List<Item>
Items {
get; } =
new();
150 [XmlArray(
"componentRequirements")]
151 [XmlArrayItem(
"componentRequirement")]
159 #region Physical subsystem
167 [XmlArrayItem(
"plant")]
168 public List<Plant>
Plants {
get; } =
new();
173 [XmlArray(
"standaloneWarehouses")]
174 [XmlArrayItem(
"standaloneWarehouse")]
183 [XmlArray(
"suppliers")]
184 [XmlArrayItem(
"supplier")]
190 [XmlArray(
"distributionCenters")]
191 [XmlArrayItem(
"distributionCenter")]
202 [XmlArray(
"transportResources")]
203 [XmlArrayItem(
"transportResource")]
211 #region Logical-physical relationships
216 [XmlArray(
"productionRoutings")]
217 [XmlArrayItem(
"productionRouting")]
226 [XmlArray(
"productionCharacteristics")]
227 [XmlArrayItem(
"productionCharacteristic")]
236 [XmlArray(
"inventories")]
237 [XmlArrayItem(
"inventory")]
243 [XmlArray(
"transportCharacteristics")]
244 [XmlArrayItem(
"transportCharacteristic")]
253 [XmlArray(
"demands")]
254 [XmlArrayItem(
"demand")]
259 [XmlArray(
"salesOptions")]
260 [XmlArrayItem(
"salesOption")]
267 [XmlArray(
"distributionCenterSourcings")]
268 [XmlArrayItem(
"distributionCenterSourcing")]
269 public List<DistributionCenterSourcing>
278 [XmlArray(
"supplierDeliveries")]
279 [XmlArrayItem(
"supplierDelivery")]
287 #region Calculated properties
306 yield
return warehouse;
316 Plants.SelectMany(plant => plant.WorkCenters);
327 GetPlanningHorizonAwareObjects().All(
329 modelObject.PlanningHorizon == 0 ||
330 modelObject.PlanningHorizon ==
345 existing => existing.
Id == item.
Id,
347 $
"An item with identifier {item.Id} already exists.");
362 existing.ComponentItemId ==
365 "A component requirement already exists for " +
366 "this parent-item/component-item pair.");
378 existing => existing.
Id == plant.
Id,
380 $
"A plant with identifier {plant.Id} already exists.");
392 existing => existing.
Id == warehouse.
Id,
394 "A standalone warehouse with identifier " +
395 $
"{warehouse.Id} already exists.");
406 existing => existing.
Id == supplier.
Id,
408 $
"A supplier with identifier {supplier.Id} already exists.");
421 existing.
Id == distributionCenter.
Id,
423 "A distribution center with identifier " +
424 $
"{distributionCenter.Id} already exists.");
437 existing.
Id == transportResource.
Id,
439 "A transport resource with identifier " +
440 $
"{transportResource.Id} already exists.");
452 existing => existing.
Id == routing.
Id,
454 "A production routing with identifier " +
455 $
"{routing.Id} already exists.");
473 "A production characteristic already exists " +
474 "for this item and work center.");
491 "An inventory already exists for this item " +
506 existing.TransportResourceId ==
509 "A transport characteristic already exists " +
510 "for this item and transport resource.");
523 existing.DistributionCenterId ==
526 "A demand already exists for this item " +
527 "and distribution center.");
539 existing.DistributionCenterId ==
542 "A sales option already exists for this item " +
543 "and distribution center.");
558 existing.ItemId == sourcing.
ItemId &&
563 "A sourcing relationship already exists for " +
564 "this distribution center, item and warehouse.");
578 existing.ItemId == delivery.
ItemId &&
583 "A supplier delivery already exists for this " +
584 "supplier, item and warehouse.");
589 #region Planning-horizon management
604 throw new ArgumentOutOfRangeException(
607 "The planning horizon cannot be negative.");
612 in GetPlanningHorizonAwareObjects())
617 bool horizonChanged =
618 _planningHorizon != periodCount;
621 _planningHorizon = periodCount;
642 in GetPlanningHorizonAwareObjects())
655 private IEnumerable<IPlanningHorizonAware>
656 GetPlanningHorizonAwareObjects()
670 yield
return workCenter;
677 yield
return warehouse;
680 foreach (TransportResource resource
683 yield
return resource;
686 foreach (ProductionSetupFamily setupFamily
689 yield
return setupFamily;
692 foreach (ProductionRouting routing
695 yield
return routing;
698 foreach (ProductionCharacteristic characteristic
701 yield
return characteristic;
706 yield
return inventory;
709 foreach (TransportCharacteristic characteristic
712 yield
return characteristic;
715 foreach (Demand demand
in Demands)
721 yield
return salesOption;
728 foreach (DistributionCenterSourcing sourcing
731 yield
return sourcing;
734 foreach (SupplierDelivery delivery
737 yield
return delivery;
743 #region Private helpers
745 private void OnFinancialParameterPropertyChanged(
747 System.ComponentModel.PropertyChangedEventArgs e)
761 private void AddUnique<T>(
764 Func<T, bool> duplicatePredicate,
766 string duplicateMessage)
769 ArgumentNullException.ThrowIfNull(value);
772 if (collection.Any(duplicatePredicate))
774 throw new InvalidOperationException(
779 SynchronizeNewObject(value);
781 collection.Add(value);
783 OnPropertyChanged(propertyName);
792 private void SynchronizeNewObject(
object value)
805 if (value is Plant plant)
807 plant.Warehouse.ResizeTimeSeries(
810 foreach (WorkCenter workCenter
811 in plant.WorkCenters)
821 if (value is IPlanningHorizonAware
822 planningHorizonAware)
824 planningHorizonAware.ResizeTimeSeries(
829 private static bool SameWarehouse(
830 WarehouseReference? first,
831 WarehouseReference? second)
834 if (first is
null || second is
null)
836 return first is
null && second is
null;
839 return first.Kind == second.Kind &&
843 private static bool SameWorkCenter(
844 WorkCenterReference? first,
845 WorkCenterReference? second)
848 if (first is
null || second is
null)
850 return first is
null && second is
null;
853 return first.PlantId == second.PlantId &&
int Id
Gets or sets the numerical identifier of the entity.
Base class for model objects that notify listeners when one of their properties changes.
Represents the maximum modeled operating expenditure allowed in each planning period.
Declares the business objective policy independently from any particular mathematical scalarization i...
Represents a bill-of-materials relationship between two items.
int ParentItemId
Gets or sets the identifier of the item being manufactured.
int ComponentItemId
Gets or sets the identifier of the required component.
Represents a finished or semi-finished item handled by the supply chain.
Represents a distribution center in the supply chain.
Represents a production plant.
List< WorkCenter > WorkCenters
Gets or sets the work centers belonging to the plant.
PlantWarehouse Warehouse
Gets or sets the warehouse attached to the plant.
Represents a standalone warehouse that is not attached to a plant.
int Id
Gets or sets the numerical identifier of the standalone warehouse.
Represents a supplier in the supply chain.
A transport resource with its own shared capacities and costs.
int ReferenceId
Gets or sets the referenced identifier.
Represents a production work center belonging to a plant.
void ResizeTimeSeries(int periodCount)
Resizes every active period-dependent parameter.
int WorkCenterId
Gets or sets the identifier of the referenced work center.
Represents the demand for an item issued by a distribution center.
int ItemId
Gets or sets the identifier of the requested item.
int DistributionCenterId
Gets or sets the identifier of the distribution center issuing the demand.
Represents the ability of a distribution center to source a given item from a given warehouse invento...
int DistributionCenterId
Gets or sets the identifier of the distribution center that can obtain the item from the referenced i...
WarehouseReference Warehouse
Gets or sets the warehouse holding the inventory from which the distribution center can obtain the it...
int ItemId
Gets or sets the identifier of the item contained in the referenced inventory.
Represents the inventory of an item in a warehouse.
int ItemId
Gets or sets the identifier of the item stored in the warehouse.
WarehouseReference Warehouse
Gets or sets the warehouse storing the item.
Represents the production characteristics of an item on a specific work center.
WorkCenterReference WorkCenter
Gets or sets the referenced work center.
int ItemId
Gets or sets the identifier of the item manufactured on the referenced work center.
Represents a production routing used to manufacture an item in a plant through one or more work cente...
int Id
Gets or sets the routing identifier.
Represents optional additional sales beyond mandatory demand.
Represents the ability of a supplier to deliver a given item to a given warehouse inventory.
int SupplierId
Gets or sets the identifier of the supplier.
int ItemId
Gets or sets the identifier of the delivered item.
WarehouseReference Warehouse
Gets or sets the warehouse receiving the item.
Represents the transport characteristics of an item for a specific transport resource.
int ItemId
Gets or sets the identifier of the item transported by the referenced transport resource.
int TransportResourceId
Gets or sets the identifier of the transport resource associated with the item.
List< Inventory > Inventories
Gets the item-warehouse inventories.
PeriodicOperatingExpenditureBudget? PeriodicOperatingExpenditureBudget
Gets or sets the period operating-expenditure budget.
void AddInventory(Inventory inventory)
Adds an inventory relationship.
void AddPlant(Plant plant)
Adds a plant and synchronizes its time-dependent data with the global planning horizon.
List< TransportResource > TransportResources
Gets the transport resources in the supply chain.
List< SupplierDelivery > SupplierDeliveries
Gets the supplier delivery possibilities.
List< DistributionCenterSourcing > DistributionCenterSourcings
Gets the warehouse sourcing options available to distribution centers.
void AddSalesOption(SalesOption salesOption)
Adds an optional additional-sales relationship.
List< ProductionSetupFamily > ProductionSetupFamilies
void AddDemand(Demand demand)
Adds a demand relationship.
void AddTransportCharacteristic(TransportCharacteristic characteristic)
Adds an item-transport-resource characteristic.
List< ProductionCharacteristic > ProductionCharacteristics
Gets the item-work-center production characteristics.
List< SalesOption > SalesOptions
Gets optional additional-sales opportunities.
int PlanningHorizon
Gets or sets the number of periods in the global planning horizon.
void AddSupplierDelivery(SupplierDelivery delivery)
Adds a supplier delivery relationship.
bool HasConsistentPlanningHorizon
Gets a value indicating whether all active time series use the global planning horizon.
void ResizeTimeSeries(int periodCount)
Changes the global planning horizon and resizes every active time series contained in the supply chai...
void SynchronizePlanningHorizon()
Forces every active time series to use the current global planning horizon.
void AddDistributionCenter(DistributionCenter distributionCenter)
Adds a distribution center.
List< TransportCharacteristic > TransportCharacteristics
Gets the item-transport-resource characteristics.
CashFlowPolicy? CashFlowPolicy
Gets or sets optional cash-flow and solvency semantics.
void AddProductionRouting(ProductionRouting routing)
Adds a production routing.
List< ProductionRouting > ProductionRoutings
Gets the production routings.
IEnumerable< WorkCenter > WorkCenters
Enumerates every work center in the supply chain.
List< StandaloneWarehouse > StandaloneWarehouses
Gets the warehouses that are not attached to a plant.
List< Plant > Plants
Gets the plants in the supply chain.
void AddSupplier(Supplier supplier)
Adds a supplier.
SupplyChain(int planningHorizon)
Initializes an empty supply chain with the specified planning horizon.
void AddItem(Item item)
Adds an item and rejects duplicate item identifiers.
IEnumerable< Warehouse > Warehouses
Enumerates every warehouse in the supply chain, including plant warehouses and standalone warehouses.
List< ComponentRequirement > ComponentRequirements
Gets the bill-of-material component requirements.
void AddStandaloneWarehouse(StandaloneWarehouse warehouse)
Adds a standalone warehouse.
List< Item > Items
Gets the items present in the supply chain.
void AddComponentRequirement(ComponentRequirement requirement)
Adds a bill-of-material component requirement.
void AddProductionCharacteristic(ProductionCharacteristic characteristic)
Adds an item-work-center production characteristic.
void AddDistributionCenterSourcing(DistributionCenterSourcing sourcing)
Adds a distribution-center sourcing relationship.
OptimizationObjectivePolicy? ObjectivePolicy
Gets or sets the explicit business objective policy. Null preserves the historical single economic ob...
List< DistributionCenter > DistributionCenters
Gets the distribution centers in the supply chain.
List< Supplier > Suppliers
Gets the suppliers in the supply chain.
SupplyChain()
Initializes an empty supply chain.
List< Demand > Demands
Gets the demands expressed by distribution centers.
void AddTransportResource(TransportResource transportResource)
Adds a transport resource.
Defines a model object containing data indexed by planning period.
void ResizeTimeSeries(int periodCount)
Resizes every time-dependent series contained in the object.
@ StandaloneWarehouse
The reference identifies a standalone warehouse through its own warehouse identifier e.