2025-02-16 - Supply Chain Transform Units examples

From Izara Wiki
Jump to navigation Jump to search

Calculate cost of outputUnit from many inputUnits

  • the below values are the smallest unit of a transfromUnits operation
  • the below values can be multiplied by the number of transfromUnits operations being submitted, eg if making 8 shirts and 12 hats all values get multiplied by 4
  • frontend sends to backend each inputUnit used and the valueUse for each input calculatedProperties
  • One outputUnit instance might use valueUse from multiple inputUnit instances
  • outputUnit calculatedProperties.calculation must be performed for each inputUnit instance valueUse
  • the resulting calculation value then needs to be divided by numberOfUnits.numberOfUnits to calculate the final unitTrackedProperty value
let transformConfigInputOutput = {
	inputUnits: {
		{unitTypeId(fabric)}: {
			calculatedProperties:{
				unitTypeTrackedPropertyId(remainingYards): {
					integerOnly: false, // maybe not needed, in unitTypeTrackedProperty.precision
					quantityReductionSetting: "clearPerUnit", // used by frontend to spread valueUse across multiple Units
					valueUse: 5.7 // per transformUnitsObject quantity, maybe allow overwriting on frontend
				},
			},				
		}, 
		{unitTypeId(bagOfButtons)}: {
			calculatedProperties:{
				unitTypeTrackedPropertyId(remainingButtons): {
					integerOnly: false,
					quantityReductionSetting: "clearPerUnit",
					valueUse: 72
				},
			},
		}, 
		//..
	},
	outputUnits: [
		{
			unitTypeId: "shirt",
			numberOfUnits: 2,
			calculatedProperties: {
				unitTypeTrackedPropertyId(shirtCost): {
					calculationType: "calculateValue",
					integerOnly: false, // maybe not needed, in unitTypeTrackedProperty.precision
					combinationEquation: "[yardCost]+[buttonCost]+[stitchCost]", // default is to sum all calculateByProperties
					calculateByProperties: {
						yardCost: {
							calculationType: "calculationPerInputUnit",
							inputUnitValueUseCalcs:{ // used by frontend to calculate default values per inputUnit instances
								inputUnitTypeId(fabric): {
									unitTypeTrackedPropertyId(remainingYards): "[valueUse]*0.8"
								}
							},
							// inputUnitValueUse.fabric.remainingYards in calculation is the value sent by frontend
							calculation: "[inputUnitValueUse:{inputUnitTypeId(fabric)}:{unitTypeTrackedPropertyId(remainingYards)}]*[unitTypeTrackedProperty:{inputUnitTypeId(fabric)}:{unitTypeTrackedPropertyId(costPerYard)}]",
						},
						buttonCost: {
							calculationType: "calculationPerInputUnit",
							inputUnitValueUseCalcs:{ // used by frontend to calculate default values per inputUnit instances
								inputUnitTypeId(fabric): {
									unitTypeTrackedPropertyId(remainingYards): "[valueUse]*0.75"
								}
							},
							calculation: "[inputUnitValueUse:{inputUnitTypeId(bagOfButtons)}:{unitTypeTrackedPropertyId(remainingButtons)}]*([unitTypeTrackedProperty:{inputUnitTypeId(fabric)}:{unitTypeTrackedPropertyId(costPerBag)}]/200)",
							round: "round",
						},
						stitchCost: {
							calculationType: "singleValue",
							defaultValue: "30",
						},
					},
				}, 
				//..
			}
		}, 
		{
			unitTypeId: "hat",
			numberOfUnits: 3,
			calculatedProperties: {
				unitTypeTrackedPropertyId(hatCost): {
					calculationType: "calculateValue",
					integerOnly: false,
					combinationEquation: "[yardCost]+[buttonCost]+[stitchCost]",
					calculateByProperties: {
						yardCost: {
							calculationType: "calculationPerInputUnit",
							inputUnitValueUseCalcs:{ // used by frontend to calculate default values per inputUnit instances
								inputUnitTypeId(fabric): {
									unitTypeTrackedPropertyId(remainingYards): "[valueUse]*0.25"
								}
							},
							calculation: "(inputUnitValueUse:{inputUnitTypeId(fabric)}:{unitTypeTrackedPropertyId(remainingYards)}]*[unitTypeTrackedProperty:{inputUnitTypeId(fabric)}:{unitTypeTrackedPropertyId(costPerYard)}]",
						},
						buttonCost: {
							calculationType: "calculationPerInputUnit",
							inputUnitValueUseCalcs:{ // used by frontend to calculate default values per inputUnit instances
								inputUnitTypeId(fabric): {
									unitTypeTrackedPropertyId(remainingYards): "[valueUse]*0.2"
								}
							},
							calculation: "[inputUnitValueUse:{inputUnitTypeId(bagOfButtons)}:{unitTypeTrackedPropertyId(remainingButtons)}]*([unitTypeTrackedProperty:{inputUnitTypeId(fabric)}:{unitTypeTrackedPropertyId(costPerBag)}]/200)",
							round: "round",
						},
						stitchCost: {
							calculationType: "singleValue",
							defaultValue: "12",
						},
					},
				}, 
				//..
			}
		}, 
		//..
	],
}

notes

  • fabric has costPerYard property
  • each fabric unit has yard unitTypeTrackedProperty and each outputUnit will specify how many yards from which fabric Unit it uses
  • bagOfButtons has costPerBag property
  • each bagOfButtons has 200 buttons in it, so divide costPerBag/200 to get per button cost
  • each 2 shirts uses 80% of the transformUnits operations remainingYards used
    • valueUse: 5.7, 80% = 4.56, per shirt: 2.28 yards
  • each 3 hats uses 20% of the transformUnits operations remainingYards used
    • valueUse: 5.7, 20% = 1.14, per hat: 0.38 yards
  • each 2 shirts uses 75% of the transformUnits operations remainingButtons used
    • valueUse: 72, 75% = 54, per shirt: 27 buttons
  • each 3 hats uses 25% of the transformUnits operations remainingButtons used
    • valueUse: 72, 25% = 18, per shirt: 6 buttons

Initial state

  • fabricA has 7 remainingYards, costPerYard = 3
  • fabricB has 100 remainingYards, costPerYard = 2.5
  • bagOfButtonsA has 5 remainingButtons, costPerBag = 480
  • bagOfButtonsB has 2 remainingButtons, costPerBag = 485
  • bagOfButtonsB has 200 remainingButtons, costPerBag = 495


Request from Frontend

let transformUnitsOperation = {
	numberOfOperations: 2, 
	outputUnits: [ // count should match total outputUnits.numberOfUnits * numberOfOperations
		{ // 1 shirt Unit
			unitTypeId: "shirt",
			inputUnits: {
				{unitTypeId(fabric)}:{
					calculatedPropertyValueUse:{
						unitTypeTrackedPropertyId(remainingYards): [
							unitId(fabricA): 2.28
						],
					}
				},
				{unitTypeId(bagOfButtons)}:{
					calculatedPropertyValueUse:{
						unitTypeTrackedPropertyId(remainingButtons): [
							unitId(bagOfButtonsA): 5,
							unitId(bagOfButtonsB): 2,
							unitId(bagOfButtonsC): 20
						]
					}
				}
			},
			singleValues: { stitchCost: 30 }
		},
		{ 
			unitTypeId: "shirt",
			inputUnits: {
				{unitTypeId(fabric)}:{
					calculatedPropertyValueUse:{
						unitTypeTrackedPropertyId(remainingYards): [
							unitId(fabricA): 2.28
						],
					}
				},
				// bagOfButtons same as above
			},
			singleValues: { stitchCost: 30 }

		},			
		{ 
			unitTypeId: "shirt",
			inputUnits: {
				{unitTypeId(fabric)}:{
					calculatedPropertyValueUse:{
						unitTypeTrackedPropertyId(remainingYards): [
							unitId(fabricA): 2.28
						],
					}
				},
				// bagOfButtons same as above
			},
			singleValues: { stitchCost: 30 }
		},	
		{ 
			unitTypeId: "shirt",
			inputUnits: {
				{unitTypeId(fabric)}:{
					calculatedPropertyValueUse:{
						unitTypeTrackedPropertyId(remainingYards): [
							unitId(fabricA): 0.16
							unitId(fabricB): 2.12
						],
					}
				},
				// bagOfButtons same as above
		},
			singleValues: { stitchCost: 30 }
		},			
				
		{ // 1 hat Unit
			unitTypeId: "hat",
			inputUnits: {
				{unitTypeId(fabric)}:{
					calculatedPropertyValueUse:{
						unitTypeTrackedPropertyId(remainingYards): [
							unitId(fabricB): 0.38
						],
					}
				},
				{unitTypeId(bagOfButtons)}:{
					calculatedPropertyValueUse:{
						unitTypeTrackedPropertyId(remainingButtons): [
							unitId(bagOfButtonsC): 6
						]
					}
				}
			
			},
			singleValues: { stitchCost: 12 }
		},
		{
			unitTypeId: "hat",
			// inputUnits same as above
		},		
		{
			unitTypeId: "hat",
			// inputUnits same as above
		},		
		{
			unitTypeId: "hat",
			// inputUnits same as above
		},		
		{
			unitTypeId: "hat",
			// inputUnits same as above
		},		
		{
			unitTypeId: "hat",
			// inputUnits same as above
		},		

		// total 4 shirts and 6 hats

	]
}

Calculation

inputUnits

  • reduce by total amount used
  • fabricA usage is 2.28+2.28+2.28+0.16 = 7, this reduces remainingYards to 0 (would trigger this Unit to being inactive if fabric>remainingYards.inactiveIfZero=true)
  • fabricB usage is 2.12, this reduces remainingYards to 99.84

outputUnits

Example, first shirt:

  • yardCost: fabricA uses 2.28 * costPerYard 3 = 6.84
  • buttonCost:
    • bagOfButtonsA uses 5 * ( costPerBag 480 / 200) = 12
    • bagOfButtonsB uses 2 * ( costPerBag 485 / 200) = 2.425
    • bagOfButtonsB uses 20 * ( costPerBag 495 / 200) = 49.5
      • total buttonCost = 63.925
  • stitchCost = 30
  • combinationEquation: "[yardCost]+[buttonCost]+[stitchCost]"
  • 6.84+63.925+30 = 100.765
  • final value entered into unitTrackedProperty shirtCost is 100.765