2using System.Collections.Generic;
60 throw new ArgumentNullException(nameof(code));
62 throw new ArgumentNullException(nameof(path));
64 throw new ArgumentNullException(nameof(message));
76 public string Code {
get; }
82 public string Path {
get; }
93 $
"[{Severity}] {Code} at {Path}: {Message}";
109 ArgumentNullException.ThrowIfNull(supplyChain);
111 var issues =
new List<ValidationIssue>();
113 ValidateRoot(supplyChain, issues);
114 ValidateLogicalSubsystem(supplyChain, issues);
115 ValidatePhysicalSubsystem(supplyChain, issues);
116 ValidateProductionRoutings(supplyChain, issues);
117 ValidateProductionCharacteristics(supplyChain, issues);
121 ValidateInventories(supplyChain, issues);
122 ValidateTransportCharacteristics(supplyChain, issues);
123 ValidateDemands(supplyChain, issues);
124 ValidateDistributionCenterSourcings(
127 ValidateSupplierDeliveries(supplyChain, issues);
129 return issues.AsReadOnly();
161 if (errors.Length == 0)
166 string message =
string.Join(
168 errors.Select(error => error.ToString()));
170 throw new InvalidOperationException(
171 "The supply-chain model is invalid." +
172 Environment.NewLine +
176 private static void ValidateRoot(
178 ICollection<ValidationIssue> issues)
185 "supplyChain.planningHorizon",
186 "The planning horizon must be strictly positive.");
189 if (supplyChain.
Items.Count == 0)
195 "The supply chain must contain at least one item.");
204 "At least one period-dependent object does not " +
205 "use the global planning horizon.");
209 private static void ValidateLogicalSubsystem(
210 SupplyChain supplyChain,
211 ICollection<ValidationIssue> issues)
213 ValidateIdentifiedCollection(
221 var requirementKeys =
222 new HashSet<string>(StringComparer.Ordinal);
232 $
"supplyChain.componentRequirements[{index}]";
235 $
"{requirement.ParentItemId}:" +
236 $
"{requirement.ComponentItemId}";
238 if (!requirementKeys.Add(key))
244 "The same parent-item/component-item " +
245 "requirement is defined more than once.");
250 requirement.ParentItemId))
255 path +
".parentItemId",
256 $
"Item {requirement.ParentItemId} does not exist.");
261 requirement.ComponentItemId))
266 path +
".componentItemId",
267 $
"Item {requirement.ComponentItemId} does not exist.");
270 if (requirement.ParentItemId ==
271 requirement.ComponentItemId)
277 "An item cannot be its own component.");
280 if (requirement.Quantity <= 0)
286 "A component quantity must be strictly positive.");
290 ValidateBillOfMaterialsCycles(
295 private static void ValidateBillOfMaterialsCycles(
296 SupplyChain supplyChain,
297 ICollection<ValidationIssue> issues)
299 Dictionary<int, List<int>> graph =
300 supplyChain.ComponentRequirements
303 requirement.ParentItemId)
309 requirement.ComponentItemId)
312 var states =
new Dictionary<int, int>();
314 foreach (
int itemId
in supplyChain.
Items.Select(
325 "supplyChain.componentRequirements",
326 "The bill of materials contains at least " +
327 "one circular dependency.");
334 private static bool ContainsCycle(
336 IReadOnlyDictionary<
int, List<int>> graph,
337 IDictionary<int, int> states)
339 if (states.TryGetValue(itemId, out
int state))
346 if (graph.TryGetValue(
348 out List<int>? components))
350 foreach (
int componentId
in components)
367 private static void ValidatePhysicalSubsystem(
368 SupplyChain supplyChain,
369 ICollection<ValidationIssue> issues)
371 ValidateIdentifiedCollection(
375 "supplyChain.plants",
379 ValidateIdentifiedCollection(
381 warehouse => warehouse.Id,
382 warehouse => warehouse.Name,
383 "supplyChain.standaloneWarehouses",
384 "standalone warehouse",
387 ValidateIdentifiedCollection(
389 supplier => supplier.Id,
390 supplier => supplier.Name,
391 "supplyChain.suppliers",
395 ValidateIdentifiedCollection(
398 center => center.Name,
399 "supplyChain.distributionCenters",
400 "distribution center",
403 ValidateIdentifiedCollection(
405 resource => resource.Id,
406 resource => resource.Name,
407 "supplyChain.transportResources",
408 "transport resource",
411 foreach (Plant plant
in supplyChain.
Plants)
414 $
"supplyChain.plants[id={plant.Id}]";
421 plantPath +
".workCenters",
422 "A plant must contain at least one work center.");
425 ValidateIdentifiedCollection(
427 workCenter => workCenter.Id,
428 workCenter => workCenter.Name,
429 plantPath +
".workCenters",
433 ValidateWarehouseDecisionModel(
435 plantPath +
".warehouse",
439 foreach (WorkCenter workCenter
442 ValidateWorkCenterDecisionModel(
445 $
".workCenters[id={workCenter.Id}]",
454 ValidateWarehouseDecisionModel(
456 "supplyChain.standaloneWarehouses" +
457 $
"[id={warehouse.Id}]",
462 foreach (TransportResource resource
466 "supplyChain.transportResources" +
467 $
"[id={resource.Id}]";
469 ValidateTransportResourceDecisionModel(
476 var laneIds =
new HashSet<int>();
477 var laneKeys =
new HashSet<string>(StringComparer.Ordinal);
480 string path = $
"supplyChain.transportLanes[id={lane.Id}]";
481 if (lane.
Id < 0 || !laneIds.Add(lane.
Id)) AddError(issues,
"TRN005", path,
"Invalid or duplicate lane identifier.");
482 ValidateWarehouseReference(supplyChain, lane.
Origin, path +
".origin", issues);
483 ValidateWarehouseReference(supplyChain, lane.
Destination, path +
".destination", issues);
484 if (SameWarehouse(lane.
Origin, lane.
Destination)) AddError(issues,
"TRN002", path,
"The origin and destination warehouses must be different.");
485 if (!laneKeys.Add(WarehouseKey(lane.
Origin) +
"->" + WarehouseKey(lane.
Destination)))
486 AddError(issues,
"TRN004", path,
"Duplicate directed transport lane.");
488 var assignments =
new HashSet<(int, int)>();
491 string path = $
"supplyChain.transportAssignments[lane={assignment.LaneId},resource={assignment.TransportResourceId}]";
493 AddError(issues,
"TRN006", path,
"An assignment references a missing lane or resource.");
495 AddError(issues,
"TRN007", path,
"Duplicate lane-resource assignment.");
496 if (assignment.
LeadTime < 0) AddError(issues,
"TRN003", path,
"A transport lead time cannot be negative.");
499 AddError(issues,
"TRN008",
"supplyChain.transportFormatVersion",
"Unsupported transport format version.");
505 ArgumentNullException.ThrowIfNull(supplyChain);
506 var issues =
new List<ValidationIssue>();
514 private static void ValidateProductionRoutings(
516 ICollection<ValidationIssue> issues)
518 var routingIds =
new HashSet<int>();
528 $
"supplyChain.productionRoutings[{index}]";
536 "A production-routing identifier must be " +
537 "strictly positive.");
540 if (!routingIds.Add(routing.
Id))
546 $
"Production-routing identifier {routing.Id} " +
558 $
"Item {routing.ItemId} does not exist.");
572 $
"Plant {routing.PlantId} does not exist.");
581 "A production lead time cannot be negative.");
589 path +
".workCenters",
590 "A production routing must use at least " +
595 new HashSet<string>(StringComparer.Ordinal);
597 foreach (WorkCenterReference reference
601 WorkCenterKey(reference);
603 if (!workCenterKeys.Add(key))
608 path +
".workCenters",
609 "The same work center is referenced more " +
610 "than once by the routing.");
618 path +
".workCenters",
619 "Every referenced work center must belong " +
620 "to the routing plant.");
623 if (ResolveWorkCenter(
630 path +
".workCenters",
631 $
"Work center {key} does not exist.");
634 bool characteristicExists =
637 characteristic.ItemId ==
640 characteristic.WorkCenter,
643 if (!characteristicExists)
648 path +
".workCenters",
649 $
"No production characteristic is defined " +
650 $
"for item {routing.ItemId} and work " +
655 ValidatePlanningHorizon(
665 private static void ValidateProductionCharacteristics(
666 SupplyChain supplyChain,
667 ICollection<ValidationIssue> issues)
670 new HashSet<string>(StringComparer.Ordinal);
677 ProductionCharacteristic characteristic =
681 "supplyChain.productionCharacteristics" +
692 $
"Item {characteristic.ItemId} does not exist.");
700 path +
".workCenter",
701 "A production characteristic must reference " +
708 $
"{characteristic.ItemId}:" +
717 "A production characteristic is duplicated " +
718 "for this item and work center.");
721 WorkCenter? workCenter =
726 if (workCenter is
null)
731 path +
".workCenter",
732 "The referenced work center does not exist.");
736 .RequiresCapacityConstrainedWorkCenter &&
743 "Unit-capacity consumption or setup time is " +
744 "defined, but the referenced work center has " +
745 "no capacity constraint.");
748 ValidatePlanningHorizon(
758 private static void ValidateInventories(
759 SupplyChain supplyChain,
760 ICollection<ValidationIssue> issues)
763 new HashSet<string>(StringComparer.Ordinal);
769 Inventory inventory =
773 $
"supplyChain.inventories[{index}]";
783 $
"Item {inventory.ItemId} does not exist.");
786 ValidateWarehouseReference(
793 $
"{inventory.ItemId}:" +
802 "An inventory is duplicated for this item " +
812 path +
".initialInventory",
813 "Initial inventory must be finite and " +
822 path +
".inventoryBalanceRule",
823 "Every inventory must contain an inventory-" +
833 "The dependencies between the inventory " +
834 "constraints and costs are invalid.");
837 Warehouse? warehouse =
843 inventory.UnitCapacityConsumption is not
null ||
844 inventory.SetupTime is not
null;
846 bool hasApplicableCapacity =
847 inventory.CapacityConstraint is not
null ||
850 if (usesCapacity && !hasApplicableCapacity)
856 "Unit-capacity consumption or setup time is " +
857 "defined, but neither the inventory nor its " +
858 "warehouse has a capacity constraint.");
861 ValidatePlanningHorizon(
871 private static void ValidateTransportCharacteristics(
872 SupplyChain supplyChain,
873 ICollection<ValidationIssue> issues)
876 new HashSet<string>(StringComparer.Ordinal);
883 TransportCharacteristic characteristic =
887 "supplyChain.transportCharacteristics" +
898 $
"Item {characteristic.ItemId} does not exist.");
901 TransportResource? resource =
902 FindTransportResource(
906 if (resource is
null)
911 path +
".transportResourceId",
912 "The referenced transport resource does not exist.");
916 $
"{characteristic.ItemId}:" +
917 $
"{characteristic.TransportResourceId}";
925 "A transport characteristic is duplicated " +
926 "for this item and transport resource.");
935 path +
".additionalCapacity",
936 "Item-specific additional capacity requires " +
937 "an item-specific capacity constraint.");
946 path +
".additionalCapacityCost",
947 "An additional-capacity cost requires an " +
948 "additional-capacity constraint.");
952 characteristic.UnitCapacityConsumption is not
null ||
953 characteristic.SetupTime is not
null;
955 bool hasApplicableCapacity =
956 characteristic.CapacityConstraint is not
null ||
959 if (usesCapacity && !hasApplicableCapacity)
965 "Unit-capacity consumption or setup time is " +
966 "defined, but neither the characteristic nor " +
967 "the transport resource has a capacity constraint.");
970 ValidatePlanningHorizon(
980 private static void ValidateDemands(
981 SupplyChain supplyChain,
982 ICollection<ValidationIssue> issues)
985 new HashSet<string>(StringComparer.Ordinal);
988 index < supplyChain.
Demands.Count;
995 $
"supplyChain.demands[{index}]";
1005 $
"Item {demand.ItemId} does not exist.");
1008 if (!DistributionCenterExists(
1015 path +
".distributionCenterId",
1016 "The referenced distribution center does not exist.");
1020 $
"{demand.DistributionCenterId}:" +
1029 "A demand is duplicated for this distribution " +
1030 "center and item.");
1038 path +
".quantities",
1039 "Demand quantities must be finite and non-negative.");
1048 path +
".quantities",
1049 "The demand time series does not use the global " +
1050 "planning horizon.");
1055 private static void ValidateDistributionCenterSourcings(
1056 SupplyChain supplyChain,
1057 ICollection<ValidationIssue> issues)
1060 new HashSet<string>(StringComparer.Ordinal);
1067 DistributionCenterSourcing sourcing =
1071 "supplyChain.distributionCenterSourcings" +
1082 $
"Item {sourcing.ItemId} does not exist.");
1085 if (!DistributionCenterExists(
1092 path +
".distributionCenterId",
1093 "The referenced distribution center does not exist.");
1096 ValidateWarehouseReference(
1099 path +
".warehouse",
1103 $
"{sourcing.DistributionCenterId}:" +
1104 $
"{sourcing.ItemId}:" +
1113 "A sourcing relationship is duplicated.");
1116 bool inventoryExists =
1125 if (!inventoryExists)
1130 path +
".warehouse",
1131 "The sourcing relationship references an " +
1132 "item-warehouse inventory that does not exist.");
1149 "No demand is defined for this distribution " +
1150 "center and item.");
1159 "A backlog or shortage cost is defined without " +
1160 "the corresponding constraint.");
1163 ValidatePlanningHorizon(
1173 private static void ValidateSupplierDeliveries(
1174 SupplyChain supplyChain,
1175 ICollection<ValidationIssue> issues)
1178 new HashSet<string>(StringComparer.Ordinal);
1184 SupplierDelivery delivery =
1188 $
"supplyChain.supplierDeliveries[{index}]";
1190 if (!SupplierExists(
1197 path +
".supplierId",
1198 "The referenced supplier does not exist.");
1209 $
"Item {delivery.ItemId} does not exist.");
1212 ValidateWarehouseReference(
1215 path +
".warehouse",
1219 $
"{delivery.SupplierId}:" +
1220 $
"{delivery.ItemId}:" +
1229 "A supplier-delivery relationship is duplicated.");
1238 "A supplier-delivery lead time cannot be negative.");
1241 bool inventoryExists =
1250 if (!inventoryExists)
1255 path +
".warehouse",
1256 "The delivery references an item-warehouse " +
1257 "inventory that does not exist.");
1267 path +
".purchasePrice",
1268 "The purchase-price time series does not use " +
1269 "the global planning horizon.");
1274 private static void ValidateWarehouseDecisionModel(
1275 Warehouse warehouse,
1278 ICollection<ValidationIssue> issues)
1286 "The warehouse additional-capacity configuration " +
1290 ValidatePlanningHorizon(
1299 private static void ValidateWorkCenterDecisionModel(
1300 WorkCenter workCenter,
1303 ICollection<ValidationIssue> issues)
1311 "The work-center additional-capacity configuration " +
1315 ValidatePlanningHorizon(
1324 private static void ValidateTransportResourceDecisionModel(
1325 TransportResource resource,
1328 ICollection<ValidationIssue> issues)
1336 "The transport-resource additional-capacity " +
1337 "configuration is invalid.");
1340 ValidatePlanningHorizon(
1349 private static void ValidatePlanningHorizon(
1351 bool hasActiveParameters,
1353 bool internallyConsistent,
1355 ICollection<ValidationIssue> issues)
1357 if (!internallyConsistent)
1363 "The active time series do not all use the same " +
1364 "planning horizon.");
1367 if (hasActiveParameters &&
1368 localHorizon != globalHorizon)
1374 $
"The local planning horizon ({localHorizon}) " +
1375 $
"does not match the global planning horizon " +
1376 $
"({globalHorizon}).");
1380 private static void ValidateWarehouseReference(
1381 SupplyChain supplyChain,
1382 WarehouseReference? reference,
1384 ICollection<ValidationIssue> issues)
1386 if (reference is
null)
1392 "A warehouse reference is required.");
1402 path +
".referenceId",
1403 "A warehouse reference identifier must be " +
1404 "strictly positive.");
1407 if (ResolveWarehouse(
1415 $
"Warehouse {WarehouseKey(reference)} does not exist.");
1419 private static void ValidateIdentifiedCollection<T>(
1420 IEnumerable<T> values,
1421 Func<T, int> idSelector,
1422 Func<T, string> nameSelector,
1425 ICollection<ValidationIssue> issues)
1428 var identifiers =
new HashSet<int>();
1432 foreach (T value
in values)
1434 int id = idSelector(value);
1435 string name = nameSelector(value);
1446 $
"A {entityName} identifier must be " +
1447 "strictly positive.");
1450 if (!identifiers.Add(
id))
1456 $
"{entityName} identifier {id} is duplicated.");
1459 if (
string.IsNullOrWhiteSpace(name))
1464 entityPath +
".name",
1465 $
"A {entityName} name is required.");
1472 private static bool ItemExists(
1473 SupplyChain supplyChain,
1476 return supplyChain.
Items.Any(
1477 item => item.Id == itemId);
1480 private static bool SupplierExists(
1481 SupplyChain supplyChain,
1485 supplier => supplier.Id == supplierId);
1488 private static bool DistributionCenterExists(
1489 SupplyChain supplyChain,
1490 int distributionCenterId)
1494 center.Id == distributionCenterId);
1497 private static Plant? FindPlant(
1498 SupplyChain supplyChain,
1501 return supplyChain.
Plants.FirstOrDefault(
1502 plant => plant.
Id == plantId);
1505 private static TransportResource? FindTransportResource(
1506 SupplyChain supplyChain,
1507 int transportResourceId)
1511 resource.
Id == transportResourceId);
1514 private static WorkCenter? ResolveWorkCenter(
1515 SupplyChain supplyChain,
1516 WorkCenterReference? reference)
1518 if (reference is
null)
1534 private static Warehouse? ResolveWarehouse(
1535 SupplyChain supplyChain,
1536 WarehouseReference? reference)
1538 if (reference is
null)
1544 return reference.Kind
switch
1546 WarehouseReferenceKind.StandaloneWarehouse =>
1547 supplyChain.StandaloneWarehouses
1553 WarehouseReferenceKind.PlantWarehouse =>
1565 private static bool SameWarehouse(
1566 WarehouseReference? first,
1567 WarehouseReference? second)
1570 if (first is
null || second is
null)
1572 return first is
null && second is
null;
1575 return first.Kind == second.Kind &&
1579 private static bool SameWorkCenter(
1580 WorkCenterReference? first,
1581 WorkCenterReference? second)
1584 if (first is
null || second is
null)
1586 return first is
null && second is
null;
1589 return first.PlantId == second.PlantId &&
1593 private static string WarehouseKey(
1594 WarehouseReference? reference)
1596 return reference is
null
1598 : $
"{reference.Kind}:{reference.ReferenceId}";
1601 private static string WorkCenterKey(
1602 WorkCenterReference? reference)
1604 return reference is
null
1606 : $
"{reference.PlantId}:" +
1607 $
"{reference.WorkCenterId}";
1610 private static void AddError(
1611 ICollection<ValidationIssue> issues,
1624 private static void AddWarning(
1625 ICollection<ValidationIssue> issues,
int Id
Gets or sets the numerical identifier of the entity.
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.
WarehouseReference Destination
Gets or sets the destination warehouse.
WarehouseReference Origin
Gets or sets the origin warehouse.
int PlanningHorizon
Gets the planning horizon represented by the first active period-dependent parameter.
bool HasConsistentPlanningHorizon
Gets a value indicating whether all active parameters use the same planning horizon.
bool HasValidCapacityConfiguration
Gets a value indicating whether the dependencies between the capacity-related parameters are respecte...
bool HasDecisionParameters
Gets a value indicating whether at least one decision-model parameter is active.
CapacityConstraint? CapacityConstraint
Gets or sets the maximum regular capacity available for the transport resource during each planning p...
bool HasValidCapacityConfiguration
Gets a value indicating whether the dependencies between the warehouse-capacity parameters are respec...
int PlanningHorizon
Gets the planning horizon represented by the first active period-dependent parameter.
bool HasDecisionParameters
Gets a value indicating whether the warehouse contains at least one global decision-model parameter.
CapacityConstraint? CapacityConstraint
Gets or sets the maximum global storage capacity of the warehouse during each planning period.
bool HasConsistentPlanningHorizon
Gets a value indicating whether all active parameters use the same planning horizon.
int ReferenceId
Gets or sets the referenced identifier.
bool HasConsistentPlanningHorizon
Gets a value indicating whether every active parameter uses the same planning horizon.
CapacityConstraint? CapacityConstraint
Gets or sets the maximum regular capacity available during each planning period.
bool HasValidCapacityConfiguration
Gets a value indicating whether the dependencies between capacity-related parameters are respected.
int PlanningHorizon
Gets the planning horizon represented by the first active period-dependent parameter.
bool HasDecisionParameters
Gets a value indicating whether at least one decision-model parameter is active.
int PlantId
Gets or sets the identifier of the plant owning the referenced work center.
int WorkCenterId
Gets or sets the identifier of the referenced work center.
int ItemId
Gets or sets the identifier of the requested item.
int PlanningHorizon
Gets the number of periods represented by the demand.
int DistributionCenterId
Gets or sets the identifier of the distribution center issuing the demand.
bool HasValidQuantities
Checks whether all currently stored demand quantities are finite and non-negative.
int DistributionCenterId
Gets or sets the identifier of the distribution center that can obtain the item from the referenced i...
bool HasConsistentPlanningHorizon
Gets a value indicating whether all active parameters use the same planning horizon.
WarehouseReference Warehouse
Gets or sets the warehouse holding the inventory from which the distribution center can obtain the it...
bool HasDecisionParameters
Gets a value indicating whether at least one decision-model parameter is active.
int ItemId
Gets or sets the identifier of the item contained in the referenced inventory.
bool HasValidDecisionConfiguration
Gets a value indicating whether the dependencies between service constraints and costs are respected.
int PlanningHorizon
Gets the planning horizon represented by the first active period-dependent parameter.
int PlanningHorizon
Gets the planning horizon represented by the first active period-dependent parameter.
bool HasConsistentPlanningHorizon
Gets a value indicating whether all active parameters use the same planning horizon.
bool HasDecisionParameters
Gets a value indicating whether at least one optional decision-model parameter is active.
int ItemId
Gets or sets the identifier of the item stored in the warehouse.
bool HasValidDecisionConfiguration
Gets a value indicating whether the direct dependencies between the inventory parameters are respecte...
WarehouseReference Warehouse
Gets or sets the warehouse storing the item.
InventoryBalanceRule InventoryBalanceRule
Gets or sets the inventory-balance rule.
double InitialInventory
Gets or sets the initial inventory level.
bool HasDecisionParameters
Gets a value indicating whether at least one production decision parameter is active.
WorkCenterReference WorkCenter
Gets or sets the referenced work center.
bool HasConsistentPlanningHorizon
Gets a value indicating whether all active parameters use the same planning horizon.
int PlanningHorizon
Gets the planning horizon represented by the first active period-dependent parameter.
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...
List< WorkCenterReference > WorkCenters
Gets or sets the work centers used by this routing.
bool HasConsistentPlanningHorizon
Gets a value indicating whether all active routing parameters use the same planning horizon.
int ItemId
Gets or sets the identifier of the item manufactured through this routing.
int LeadTime
Gets or sets the production lead time.
int PlanningHorizon
Gets the planning horizon represented by the first active period-dependent routing parameter.
int Id
Gets or sets the routing identifier.
bool HasLotSizingConstraints
Gets a value indicating whether at least one lot-sizing constraint is active.
int PlantId
Gets or sets the identifier of the plant in which this routing is available.
int PlanningHorizon
Gets the planning horizon represented by the purchase-price time series.
int SupplierId
Gets or sets the identifier of the supplier.
int ItemId
Gets or sets the identifier of the delivered item.
bool HasDecisionParameters
Gets a value indicating whether this delivery contains at least one decision-model parameter.
int LeadTime
Gets or sets the supplier-delivery lead time.
WarehouseReference Warehouse
Gets or sets the warehouse receiving the item.
int PlanningHorizon
Gets the planning horizon represented by the first active period-dependent parameter.
AdditionalCapacity? AdditionalCapacity
Gets or sets the maximum additional transport capacity available specifically for this item.
CapacityConstraint? CapacityConstraint
Gets or sets the maximum transport capacity available specifically for this item during each planning...
AdditionalCapacityCost? AdditionalCapacityCost
Gets or sets the unit cost of additional transport capacity allocated to this item.
bool HasConsistentPlanningHorizon
Gets a value indicating whether all active parameters use the same planning horizon.
bool HasDecisionParameters
Gets a value indicating whether at least one decision-model parameter is active.
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.
Represents the complete supply-chain data model.
List< Inventory > Inventories
Gets the item-warehouse inventories.
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.
List< ProductionCharacteristic > ProductionCharacteristics
Gets the item-work-center production characteristics.
List< TransportLane > TransportLanes
int PlanningHorizon
Gets or sets the number of periods in the global planning horizon.
bool HasConsistentPlanningHorizon
Gets a value indicating whether all active time series use the global planning horizon.
List< TransportCharacteristic > TransportCharacteristics
Gets the item-transport-resource characteristics.
List< ProductionRouting > ProductionRoutings
Gets the production routings.
List< StandaloneWarehouse > StandaloneWarehouses
Gets the warehouses that are not attached to a plant.
List< Plant > Plants
Gets the plants in the supply chain.
int TransportFormatVersion
List< ComponentRequirement > ComponentRequirements
Gets the bill-of-material component requirements.
List< Item > Items
Gets the items present in the supply chain.
List< TransportAssignment > TransportAssignments
List< DistributionCenter > DistributionCenters
Gets the distribution centers in the supply chain.
List< Supplier > Suppliers
Gets the suppliers in the supply chain.
List< Demand > Demands
Gets the demands expressed by distribution centers.
static void AppendIssues(SupplyChain supplyChain, ICollection< SupplyChainValidator.ValidationIssue > issues)
Represents one issue detected during validation.
string Message
Gets the human-readable description of the issue.
string Code
Gets the stable technical code identifying the validation rule.
override string ToString()
string Path
Gets the logical path of the model element concerned by the validation issue.
ValidationIssue(ValidationSeverity severity, string code, string path, string message)
Initializes a new validation issue.
ValidationSeverity Severity
Gets the severity of the validation issue.
Validates the structural, referential and decision-model consistency of a complete supply chain.
IReadOnlyList< ValidationIssue > ValidateTransportReadiness(SupplyChain supplyChain)
Advisory transport readiness diagnostics, independent of structural validity.
ValidationSeverity
Indicates the severity of a supply-chain validation issue.
@ Warning
Indicates a non-blocking validation warning.
@ Error
Indicates a validation error that makes the model invalid.
bool IsValid(SupplyChain supplyChain)
Determines whether a supply chain contains no validation error.
void ThrowIfInvalid(SupplyChain supplyChain)
Validates the model and throws an exception when at least one validation error is detected.
IReadOnlyList< ValidationIssue > Validate(SupplyChain supplyChain)
Validates a complete supply-chain model.
@ StandaloneWarehouse
The reference identifies a standalone warehouse through its own warehouse identifier e.