LotSizingDataModel.Core 2.0.1
Core domain model, shared abstractions and XML-serializable entities.
Loading...
Searching...
No Matches
CostAnalyzer.cs
Go to the documentation of this file.
1using System;
2using System.Collections.Generic;
7
9
10/// <summary>
11/// Calculates the costs and revenues associated with
12/// supply-chain activities.
13///
14/// Global resource costs and item-specific activity costs
15/// are calculated separately to prevent global fixed costs
16/// from being counted several times.
17/// </summary>
18public sealed class CostAnalyzer
19{
20 /// <summary>
21 /// Initializes a cost analyzer and creates
22 /// a new supply-chain index.
23 /// </summary>
24 public CostAnalyzer(SupplyChain supplyChain)
25 : this(
27 supplyChain ??
28 throw new ArgumentNullException(
29 nameof(supplyChain))))
30 {
31 }
32
33 /// <summary>
34 /// Initializes a cost analyzer using an existing index.
35 /// </summary>
37 {
38 Index = index ??
39 throw new ArgumentNullException(nameof(index));
40
42 Queries = new SupplyChainQueries(index);
43 }
44
45 /// <summary>
46 /// Gets the analyzed supply chain.
47 /// </summary>
48 public SupplyChain SupplyChain { get; }
49
50 /// <summary>
51 /// Gets the entity index used by the analyzer.
52 /// </summary>
53 public SupplyChainIndex Index { get; }
54
55 /// <summary>
56 /// Gets the query service used to resolve relationships.
57 /// </summary>
59
60 /// <summary>
61 /// Rebuilds the underlying entity index.
62 /// </summary>
63 public void RebuildIndex()
64 {
65 Index.Rebuild();
66 }
67
68 #region Production costs
69
70 /// <summary>
71 /// Calculates the global cost of using a work center
72 /// during one planning period.
73 ///
74 /// This cost must be calculated only once for the work
75 /// center and period, regardless of the number of items
76 /// produced on the work center.
77 /// </summary>
79 WorkCenterReference workCenterReference,
80 int period,
81 bool resourceActivated,
82 double additionalCapacityUsed)
83 {
84 ArgumentNullException.ThrowIfNull(
85 workCenterReference);
86
87 ValidatePeriod(period);
88
89 ValidateQuantity(
90 additionalCapacityUsed,
91 nameof(additionalCapacityUsed));
92
93 ValidateResourceActivation(
94 resourceActivated,
95 additionalCapacityUsed);
96
97 WorkCenter workCenter =
98 Index.GetRequiredWorkCenter(
99 workCenterReference);
100
101 double fixedUsageCost =
102 resourceActivated
103 ? GetCostValue(
104 workCenter.FixedUsageCost?[period],
105 nameof(workCenter.FixedUsageCost))
106 : 0.0;
107
108 double additionalCapacityCost =
109 Multiply(
110 additionalCapacityUsed,
111 GetCostValue(
112 workCenter.AdditionalCapacityCost?[period],
113 nameof(workCenter.AdditionalCapacityCost)),
114 "work-center additional-capacity cost");
115
116 return new CostBreakdown(
117 fixedUsageCost: fixedUsageCost,
118 additionalCapacityCost:
119 additionalCapacityCost);
120 }
121
122 /// <summary>
123 /// Calculates the item-specific production cost on a
124 /// work center during one planning period.
125 ///
126 /// The global work-center cost is not included.
127 /// </summary>
129 int itemId,
130 WorkCenterReference workCenterReference,
131 int period,
132 double productionQuantity,
133 bool setupActivated)
134 {
135 ArgumentNullException.ThrowIfNull(
136 workCenterReference);
137
138 ValidatePeriod(period);
139
140 ValidateQuantity(
141 productionQuantity,
142 nameof(productionQuantity));
143
144 ProductionCharacteristic characteristic =
145 Queries.GetRequiredProductionCharacteristic(
146 itemId,
147 workCenterReference);
148
149 double fixedSetupCost =
150 setupActivated
151 ? GetCostValue(
152 characteristic.FixedSetupCost?[period],
153 nameof(characteristic.FixedSetupCost))
154 : 0.0;
155
156 double unitUsageCost =
157 Multiply(
158 productionQuantity,
159 GetCostValue(
160 characteristic.UnitUsageCost?[period],
161 nameof(characteristic.UnitUsageCost)),
162 "production unit-usage cost");
163
164 return new CostBreakdown(
165 fixedSetupCost: fixedSetupCost,
166 unitUsageCost: unitUsageCost);
167 }
168
169 #endregion
170
171 #region Storage costs
172
173 /// <summary>
174 /// Calculates the global cost of using a warehouse
175 /// during one planning period.
176 ///
177 /// This cost must be calculated only once for the
178 /// warehouse and period.
179 /// </summary>
181 WarehouseReference warehouseReference,
182 int period,
183 bool warehouseActivated,
184 double additionalCapacityUsed)
185 {
186 ArgumentNullException.ThrowIfNull(
187 warehouseReference);
188
189 ValidatePeriod(period);
190
191 ValidateQuantity(
192 additionalCapacityUsed,
193 nameof(additionalCapacityUsed));
194
195 ValidateResourceActivation(
196 warehouseActivated,
197 additionalCapacityUsed);
198
199 Warehouse warehouse =
200 Index.GetRequiredWarehouse(
201 warehouseReference);
202
203 double fixedUsageCost =
204 warehouseActivated
205 ? GetCostValue(
206 warehouse.FixedUsageCost?[period],
207 nameof(warehouse.FixedUsageCost))
208 : 0.0;
209
210 double additionalCapacityCost =
211 Multiply(
212 additionalCapacityUsed,
213 GetCostValue(
214 warehouse.AdditionalCapacityCost?[period],
215 nameof(warehouse.AdditionalCapacityCost)),
216 "warehouse additional-capacity cost");
217
218 return new CostBreakdown(
219 fixedUsageCost: fixedUsageCost,
220 additionalCapacityCost:
221 additionalCapacityCost);
222 }
223
224 /// <summary>
225 /// Calculates the item-specific storage cost during
226 /// one planning period.
227 ///
228 /// The global warehouse cost is not included.
229 /// </summary>
231 int itemId,
232 WarehouseReference warehouseReference,
233 int period,
234 double inventoryQuantity,
235 bool setupActivated,
236 double itemAdditionalCapacityUsed,
237 double safetyStockViolationQuantity)
238 {
239 ArgumentNullException.ThrowIfNull(
240 warehouseReference);
241
242 ValidatePeriod(period);
243
244 ValidateQuantity(
245 inventoryQuantity,
246 nameof(inventoryQuantity));
247
248 ValidateQuantity(
249 itemAdditionalCapacityUsed,
250 nameof(itemAdditionalCapacityUsed));
251
252 ValidateQuantity(
253 safetyStockViolationQuantity,
254 nameof(safetyStockViolationQuantity));
255
256 Inventory inventory =
257 Queries.GetRequiredInventory(
258 itemId,
259 warehouseReference);
260
261 double fixedSetupCost =
262 setupActivated
263 ? GetCostValue(
264 inventory.FixedSetupCost?[period],
265 nameof(inventory.FixedSetupCost))
266 : 0.0;
267
268 double unitUsageCost =
269 Multiply(
270 inventoryQuantity,
271 GetCostValue(
272 inventory.UnitUsageCost?[period],
273 nameof(inventory.UnitUsageCost)),
274 "inventory unit-usage cost");
275
276 double additionalCapacityCost =
277 Multiply(
278 itemAdditionalCapacityUsed,
279 GetCostValue(
280 inventory.AdditionalCapacityCost?[period],
281 nameof(inventory.AdditionalCapacityCost)),
282 "item-specific storage additional-capacity cost");
283
284 double safetyStockViolationCost =
285 Multiply(
286 safetyStockViolationQuantity,
287 GetCostValue(
288 inventory.SafetyStockViolationCost?[period],
289 nameof(inventory.SafetyStockViolationCost)),
290 "safety-stock violation cost");
291
292 return new CostBreakdown(
293 additionalCapacityCost:
294 additionalCapacityCost,
295 fixedSetupCost: fixedSetupCost,
296 unitUsageCost: unitUsageCost,
297 safetyStockViolationCost:
298 safetyStockViolationCost);
299 }
300
301 #endregion
302
303 #region Transport costs
304
305 /// <summary>
306 /// Calculates the global cost of using a transport
307 /// resource during one planning period.
308 ///
309 /// This cost must be calculated only once for the
310 /// transport resource and period.
311 /// </summary>
313 int transportResourceId,
314 int period,
315 bool resourceActivated,
316 double additionalCapacityUsed)
317 {
318 ValidatePeriod(period);
319
320 ValidateQuantity(
321 additionalCapacityUsed,
322 nameof(additionalCapacityUsed));
323
324 ValidateResourceActivation(
325 resourceActivated,
326 additionalCapacityUsed);
327
328 TransportResource resource =
329 Index.GetRequiredTransportResource(
330 transportResourceId);
331
332 double fixedUsageCost =
333 resourceActivated
334 ? GetCostValue(
335 resource.FixedUsageCost?[period],
336 nameof(resource.FixedUsageCost))
337 : 0.0;
338
339 double additionalCapacityCost =
340 Multiply(
341 additionalCapacityUsed,
342 GetCostValue(
343 resource.AdditionalCapacityCost?[period],
344 nameof(resource.AdditionalCapacityCost)),
345 "transport-resource additional-capacity cost");
346
347 return new CostBreakdown(
348 fixedUsageCost: fixedUsageCost,
349 additionalCapacityCost:
350 additionalCapacityCost);
351 }
352
353 /// <summary>
354 /// Calculates the item-specific transport cost during
355 /// one planning period.
356 ///
357 /// The global transport-resource cost is not included.
358 /// </summary>
360 int itemId,
361 int transportResourceId,
362 int period,
363 double transportedQuantity,
364 bool setupActivated,
365 double itemAdditionalCapacityUsed)
366 {
367 ValidatePeriod(period);
368
369 ValidateQuantity(
370 transportedQuantity,
371 nameof(transportedQuantity));
372
373 ValidateQuantity(
374 itemAdditionalCapacityUsed,
375 nameof(itemAdditionalCapacityUsed));
376
377 TransportCharacteristic characteristic =
378 Queries.GetRequiredTransportCharacteristic(
379 itemId,
380 transportResourceId);
381
382 double fixedSetupCost =
383 setupActivated
384 ? GetCostValue(
385 characteristic.FixedSetupCost?[period],
386 nameof(characteristic.FixedSetupCost))
387 : 0.0;
388
389 double unitUsageCost =
390 Multiply(
391 transportedQuantity,
392 GetCostValue(
393 characteristic.UnitUsageCost?[period],
394 nameof(characteristic.UnitUsageCost)),
395 "transport unit-usage cost");
396
397 double additionalCapacityCost =
398 Multiply(
399 itemAdditionalCapacityUsed,
400 GetCostValue(
401 characteristic.AdditionalCapacityCost?[period],
402 nameof(characteristic.AdditionalCapacityCost)),
403 "item-specific transport additional-capacity cost");
404
405 return new CostBreakdown(
406 additionalCapacityCost:
407 additionalCapacityCost,
408 fixedSetupCost: fixedSetupCost,
409 unitUsageCost: unitUsageCost);
410 }
411
412 #endregion
413
414 #region Distribution costs and revenue
415
416 /// <summary>
417 /// Calculates the distribution penalties and sales revenue
418 /// associated with a sourcing relationship.
419 /// </summary>
422 int period,
423 double soldQuantity,
424 double backlogQuantity,
425 double shortageQuantity)
426 {
427 ArgumentNullException.ThrowIfNull(sourcing);
428
429 ValidatePeriod(period);
430
431 ValidateQuantity(
432 soldQuantity,
433 nameof(soldQuantity));
434
435 ValidateQuantity(
436 backlogQuantity,
437 nameof(backlogQuantity));
438
439 ValidateQuantity(
440 shortageQuantity,
441 nameof(shortageQuantity));
442
443 Index.GetRequiredItem(sourcing.ItemId);
444
445 Index.GetRequiredDistributionCenter(
446 sourcing.DistributionCenterId);
447
448 Index.GetRequiredWarehouse(
449 sourcing.Warehouse);
450
451 double backlogCost =
452 Multiply(
453 backlogQuantity,
454 GetCostValue(
455 sourcing.BacklogCost?[period],
456 nameof(sourcing.BacklogCost)),
457 "backlog cost");
458
459 double shortageCost =
460 Multiply(
461 shortageQuantity,
462 GetCostValue(
463 sourcing.ShortageCost?[period],
464 nameof(sourcing.ShortageCost)),
465 "shortage cost");
466
467 double revenue =
468 Multiply(
469 soldQuantity,
470 GetCostValue(
471 sourcing.SellingPrice?[period],
472 nameof(sourcing.SellingPrice)),
473 "sales revenue");
474
475 return new CostBreakdown(
476 backlogCost: backlogCost,
477 shortageCost: shortageCost,
478 revenue: revenue);
479 }
480
481 #endregion
482
483 #region Purchase costs
484
485 /// <summary>
486 /// Calculates the purchase cost associated with a supplier
487 /// delivery during one planning period.
488 /// </summary>
490 SupplierDelivery delivery,
491 int period,
492 double purchasedQuantity)
493 {
494 ArgumentNullException.ThrowIfNull(delivery);
495
496 ValidatePeriod(period);
497
498 ValidateQuantity(
499 purchasedQuantity,
500 nameof(purchasedQuantity));
501
502 Index.GetRequiredSupplier(delivery.SupplierId);
503 Index.GetRequiredItem(delivery.ItemId);
504
505 Index.GetRequiredWarehouse(
506 delivery.Warehouse);
507
508 double purchaseCost =
509 Multiply(
510 purchasedQuantity,
511 GetCostValue(
512 delivery.PurchasePrice?[period],
513 nameof(delivery.PurchasePrice)),
514 "purchase cost");
515
516 return new CostBreakdown(
517 purchaseCost: purchaseCost);
518 }
519
520 #endregion
521
522 #region Aggregation
523
524 /// <summary>
525 /// Aggregates several cost calculations.
526 /// </summary>
528 IEnumerable<CostBreakdown> costs)
529 {
530 ArgumentNullException.ThrowIfNull(costs);
531
532 CostBreakdown total =
534
535 foreach (CostBreakdown cost in costs)
536 {
537 if (cost is null)
538 {
539 throw new ArgumentException(
540 "The cost collection cannot contain null.",
541 nameof(costs));
542 }
543
544 total = total.Add(cost);
545 }
546
547 return total;
548 }
549
550 #endregion
551
552 #region Validation and calculation helpers
553
554 private void ValidatePeriod(int period)
555 {
556 if (period < 1 ||
558 {
559 throw new ArgumentOutOfRangeException(
560 nameof(period),
561 period,
562 $"The period must be between 1 and " +
563 $"{SupplyChain.PlanningHorizon}.");
564 }
565 }
566
567 private static void ValidateResourceActivation(
568 bool resourceActivated,
569 double additionalCapacityUsed)
570 {
571 if (!resourceActivated &&
572 additionalCapacityUsed > 0.0)
573 {
574 throw new InvalidOperationException(
575 "Additional capacity cannot be used when " +
576 "the resource is not activated.");
577 }
578 }
579
580 private static void ValidateQuantity(
581 double quantity,
582 string parameterName)
583 {
584 if (!double.IsFinite(quantity) ||
585 quantity < 0.0)
586 {
587 throw new ArgumentOutOfRangeException(
588 parameterName,
589 quantity,
590 "The quantity must be finite and non-negative.");
591 }
592 }
593
594 private static double GetCostValue(
595 double? cost,
596 string parameterName)
597 {
598 double value = cost ?? 0.0;
599
600 if (!double.IsFinite(value) ||
601 value < 0.0)
602 {
603 throw new InvalidOperationException(
604 $"The cost parameter '{parameterName}' must " +
605 "be finite and non-negative.");
606 }
607
608 return value;
609 }
610
611 private static double Multiply(
612 double quantity,
613 double unitCost,
614 string calculationName)
615 {
616 double result =
617 quantity * unitCost;
618
619 if (!double.IsFinite(result))
620 {
621 throw new InvalidOperationException(
622 $"The {calculationName} exceeds the " +
623 "supported numerical range.");
624 }
625
626 return result;
627 }
628
629 #endregion
630
631 /// <summary>
632 /// Represents a detailed cost and revenue calculation.
633 /// </summary>
634 public sealed class CostBreakdown
635 {
636 /// <summary>
637 /// Gets an empty cost breakdown.
638 /// </summary>
639 public static CostBreakdown Empty { get; } =
640 new();
641
642 /// <summary>
643 /// Initializes a detailed cost and revenue breakdown.
644 /// </summary>
645 /// <param name="fixedUsageCost">
646 /// Fixed resource-usage cost.
647 /// </param>
648 /// <param name="additionalCapacityCost">
649 /// Cost of additional capacity.
650 /// </param>
651 /// <param name="fixedSetupCost">
652 /// Fixed setup cost.
653 /// </param>
654 /// <param name="unitUsageCost">
655 /// Quantity-dependent resource-usage cost.
656 /// </param>
657 /// <param name="safetyStockViolationCost">
658 /// Cost caused by a safety-stock violation.
659 /// </param>
660 /// <param name="backlogCost">
661 /// Cost associated with backlogged demand.
662 /// </param>
663 /// <param name="shortageCost">
664 /// Cost associated with lost or unsatisfied demand.
665 /// </param>
666 /// <param name="purchaseCost">
667 /// Cost of purchased quantities.
668 /// </param>
669 /// <param name="revenue">
670 /// Revenue generated by sales.
671 /// </param>
673 double fixedUsageCost = 0.0,
674 double additionalCapacityCost = 0.0,
675 double fixedSetupCost = 0.0,
676 double unitUsageCost = 0.0,
677 double safetyStockViolationCost = 0.0,
678 double backlogCost = 0.0,
679 double shortageCost = 0.0,
680 double purchaseCost = 0.0,
681 double revenue = 0.0)
682 {
683 ValidateCost(
684 fixedUsageCost,
685 nameof(fixedUsageCost));
686
687 ValidateCost(
688 additionalCapacityCost,
689 nameof(additionalCapacityCost));
690
691 ValidateCost(
692 fixedSetupCost,
693 nameof(fixedSetupCost));
694
695 ValidateCost(
696 unitUsageCost,
697 nameof(unitUsageCost));
698
699 ValidateCost(
700 safetyStockViolationCost,
701 nameof(safetyStockViolationCost));
702
703 ValidateCost(
704 backlogCost,
705 nameof(backlogCost));
706
707 ValidateCost(
708 shortageCost,
709 nameof(shortageCost));
710
711 ValidateCost(
712 purchaseCost,
713 nameof(purchaseCost));
714
715 ValidateCost(
716 revenue,
717 nameof(revenue));
718
719 FixedUsageCost = fixedUsageCost;
720
722 additionalCapacityCost;
723
724 FixedSetupCost = fixedSetupCost;
725 UnitUsageCost = unitUsageCost;
726
728 safetyStockViolationCost;
729
730 BacklogCost = backlogCost;
731 ShortageCost = shortageCost;
732 PurchaseCost = purchaseCost;
733 Revenue = revenue;
734
735 TotalCost = SumFinite(
736 fixedUsageCost,
737 additionalCapacityCost,
738 fixedSetupCost,
739 unitUsageCost,
740 safetyStockViolationCost,
741 backlogCost,
742 shortageCost,
743 purchaseCost);
744
746
747 if (!double.IsFinite(NetCost))
748 {
749 throw new InvalidOperationException(
750 "The net cost exceeds the supported " +
751 "numerical range.");
752 }
753 }
754
755 /// <summary>
756 /// Gets the fixed resource-usage cost.
757 /// </summary>
758 public double FixedUsageCost { get; }
759
760 /// <summary>
761 /// Gets the additional-capacity cost.
762 /// </summary>
763 public double AdditionalCapacityCost { get; }
764
765 /// <summary>
766 /// Gets the fixed setup cost.
767 /// </summary>
768 public double FixedSetupCost { get; }
769
770 /// <summary>
771 /// Gets the unit resource-usage cost.
772 /// </summary>
773 public double UnitUsageCost { get; }
774
775 /// <summary>
776 /// Gets the safety-stock violation cost.
777 /// </summary>
778 public double SafetyStockViolationCost { get; }
779
780 /// <summary>
781 /// Gets the backlog cost.
782 /// </summary>
783 public double BacklogCost { get; }
784
785 /// <summary>
786 /// Gets the shortage cost.
787 /// </summary>
788 public double ShortageCost { get; }
789
790 /// <summary>
791 /// Gets the purchase cost.
792 /// </summary>
793 public double PurchaseCost { get; }
794
795 /// <summary>
796 /// Gets the sales revenue.
797 /// </summary>
798 public double Revenue { get; }
799
800 /// <summary>
801 /// Gets the sum of all costs before revenue.
802 /// </summary>
803 public double TotalCost { get; }
804
805 /// <summary>
806 /// Gets total costs minus sales revenue.
807 ///
808 /// A negative value represents a positive margin.
809 /// </summary>
810 public double NetCost { get; }
811
812 /// <summary>
813 /// Gets the margin, defined as revenue minus costs.
814 /// </summary>
815 public double Margin => -NetCost;
816
817 /// <summary>
818 /// Gets a value indicating whether the calculation
819 /// contains neither cost nor revenue.
820 /// </summary>
821 public bool IsEmpty =>
822 TotalCost == 0.0 &&
823 Revenue == 0.0;
824
825 /// <summary>
826 /// Returns a new breakdown containing the sum of
827 /// the current calculation and another calculation.
828 /// </summary>
830 CostBreakdown other)
831 {
832 ArgumentNullException.ThrowIfNull(other);
833
834 return new CostBreakdown(
835 fixedUsageCost:
836 AddFinite(
838 other.FixedUsageCost),
839
840 additionalCapacityCost:
841 AddFinite(
844
845 fixedSetupCost:
846 AddFinite(
848 other.FixedSetupCost),
849
850 unitUsageCost:
851 AddFinite(
853 other.UnitUsageCost),
854
855 safetyStockViolationCost:
856 AddFinite(
859
860 backlogCost:
861 AddFinite(
863 other.BacklogCost),
864
865 shortageCost:
866 AddFinite(
868 other.ShortageCost),
869
870 purchaseCost:
871 AddFinite(
873 other.PurchaseCost),
874
875 revenue:
876 AddFinite(
877 Revenue,
878 other.Revenue));
879 }
880
881 /// <inheritdoc/>
882 public override string ToString()
883 {
884 return
885 $"Total cost: {TotalCost}; " +
886 $"revenue: {Revenue}; " +
887 $"net cost: {NetCost}; " +
888 $"margin: {Margin}";
889 }
890
891 private static void ValidateCost(
892 double cost,
893 string parameterName)
894 {
895 if (!double.IsFinite(cost) ||
896 cost < 0.0)
897 {
898 throw new ArgumentOutOfRangeException(
899 parameterName,
900 cost,
901 "The cost must be finite and non-negative.");
902 }
903 }
904
905 private static double AddFinite(
906 double first,
907 double second)
908 {
909 double result = first + second;
910
911 if (!double.IsFinite(result))
912 {
913 throw new InvalidOperationException(
914 "The aggregated cost exceeds the " +
915 "supported numerical range.");
916 }
917
918 return result;
919 }
920
921 private static double SumFinite(
922 params double[] values)
923 {
924 double total = 0.0;
925
926 foreach (double value in values)
927 {
928 total = AddFinite(
929 total,
930 value);
931 }
932
933 return total;
934 }
935 }
936}
Represents a detailed cost and revenue calculation.
double FixedUsageCost
Gets the fixed resource-usage cost.
double Margin
Gets the margin, defined as revenue minus costs.
bool IsEmpty
Gets a value indicating whether the calculation contains neither cost nor revenue.
CostBreakdown(double fixedUsageCost=0.0, double additionalCapacityCost=0.0, double fixedSetupCost=0.0, double unitUsageCost=0.0, double safetyStockViolationCost=0.0, double backlogCost=0.0, double shortageCost=0.0, double purchaseCost=0.0, double revenue=0.0)
Initializes a detailed cost and revenue breakdown.
double UnitUsageCost
Gets the unit resource-usage cost.
double SafetyStockViolationCost
Gets the safety-stock violation cost.
double NetCost
Gets total costs minus sales revenue.
double AdditionalCapacityCost
Gets the additional-capacity cost.
static CostBreakdown Empty
Gets an empty cost breakdown.
double TotalCost
Gets the sum of all costs before revenue.
CostBreakdown Add(CostBreakdown other)
Returns a new breakdown containing the sum of the current calculation and another calculation.
CostBreakdown CalculateDistributionCost(DistributionCenterSourcing sourcing, int period, double soldQuantity, double backlogQuantity, double shortageQuantity)
Calculates the distribution penalties and sales revenue associated with a sourcing relationship.
CostBreakdown Aggregate(IEnumerable< CostBreakdown > costs)
Aggregates several cost calculations.
CostBreakdown CalculateTransportActivityCost(int itemId, int transportResourceId, int period, double transportedQuantity, bool setupActivated, double itemAdditionalCapacityUsed)
Calculates the item-specific transport cost during one planning period.
CostAnalyzer(SupplyChainIndex index)
Initializes a cost analyzer using an existing index.
CostBreakdown CalculateWorkCenterResourceCost(WorkCenterReference workCenterReference, int period, bool resourceActivated, double additionalCapacityUsed)
Calculates the global cost of using a work center during one planning period.
CostBreakdown CalculatePurchaseCost(SupplierDelivery delivery, int period, double purchasedQuantity)
Calculates the purchase cost associated with a supplier delivery during one planning period.
CostBreakdown CalculateTransportResourceCost(int transportResourceId, int period, bool resourceActivated, double additionalCapacityUsed)
Calculates the global cost of using a transport resource during one planning period.
SupplyChain SupplyChain
Gets the analyzed supply chain.
CostBreakdown CalculateWarehouseResourceCost(WarehouseReference warehouseReference, int period, bool warehouseActivated, double additionalCapacityUsed)
Calculates the global cost of using a warehouse during one planning period.
SupplyChainIndex Index
Gets the entity index used by the analyzer.
CostBreakdown CalculateProductionActivityCost(int itemId, WorkCenterReference workCenterReference, int period, double productionQuantity, bool setupActivated)
Calculates the item-specific production cost on a work center during one planning period.
void RebuildIndex()
Rebuilds the underlying entity index.
CostBreakdown CalculateInventoryActivityCost(int itemId, WarehouseReference warehouseReference, int period, double inventoryQuantity, bool setupActivated, double itemAdditionalCapacityUsed, double safetyStockViolationQuantity)
Calculates the item-specific storage cost during one planning period.
CostAnalyzer(SupplyChain supplyChain)
Initializes a cost analyzer and creates a new supply-chain index.
SupplyChainQueries Queries
Gets the query service used to resolve relationships.
Provides fast access to the entities contained in a supply chain.
SupplyChain SupplyChain
Gets the indexed supply chain.
A transport resource with its own shared capacities and costs.
AdditionalCapacityCost? AdditionalCapacityCost
Gets or sets the cost of using one unit of additional transport capacity during each planning period.
FixedUsageCost? FixedUsageCost
Gets or sets the fixed cost incurred when the transport resource is used during a planning period.
Represents a warehouse in the supply chain.
Definition Warehouse.cs:19
FixedUsageCost? FixedUsageCost
Gets or sets the fixed cost incurred when the warehouse is used during a planning period.
AdditionalCapacityCost? AdditionalCapacityCost
Gets or sets the cost of using one unit of global additional warehouse capacity.
Represents a serializable reference to a warehouse.
Represents a production work center belonging to a plant.
Definition WorkCenter.cs:15
FixedUsageCost? FixedUsageCost
Gets or sets the fixed cost incurred when the work center is used during a planning period.
AdditionalCapacityCost? AdditionalCapacityCost
Gets or sets the cost of using one unit of additional capacity during each planning period.
Represents a serializable reference to a work center.
Provides high-level read-only queries over a supply-chain model.
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...
SellingPrice? SellingPrice
Gets or sets the unit selling price of the item supplied by the warehouse to the distribution center ...
ShortageCost? ShortageCost
Gets or sets the unit cost applied to each item unit permanently lost as shortage.
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.
BacklogCost? BacklogCost
Gets or sets the unit cost applied to each item unit remaining in backlog during a planning period.
Represents the inventory of an item in a warehouse.
Definition Inventory.cs:20
FixedSetupCost? FixedSetupCost
Gets or sets the fixed preparation cost associated with storing this item.
AdditionalCapacityCost? AdditionalCapacityCost
Gets or sets the cost of using one unit of additional storage capacity for this item.
SafetyStockViolationCost? SafetyStockViolationCost
Gets or sets the cost incurred for each unit missing from the required safety-stock level.
UnitUsageCost? UnitUsageCost
Gets or sets the cost of storing one unit of the item during each planning period.
Represents the production characteristics of an item on a specific work center.
UnitUsageCost? UnitUsageCost
Gets or sets the cost of producing one unit of the item on the work center during each planning perio...
FixedSetupCost? FixedSetupCost
Gets or sets the fixed cost incurred when the work center is prepared to produce the item during a pl...
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.
PurchasePrice? PurchasePrice
Gets or sets the unit purchase price of the item for each planning period.
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.
UnitUsageCost? UnitUsageCost
Gets or sets the cost of transporting one unit of the item during each planning period.
FixedSetupCost? FixedSetupCost
Gets or sets the fixed cost incurred when the transport resource is prepared for this item.
AdditionalCapacityCost? AdditionalCapacityCost
Gets or sets the unit cost of additional transport capacity allocated to this item.
Represents the complete supply-chain data model.
int PlanningHorizon
Gets or sets the number of periods in the global planning horizon.