diff --git a/backend/src/main/java/com/printcalculator/controller/QuoteController.java b/backend/src/main/java/com/printcalculator/controller/QuoteController.java index 2122ac8..f283338 100644 --- a/backend/src/main/java/com/printcalculator/controller/QuoteController.java +++ b/backend/src/main/java/com/printcalculator/controller/QuoteController.java @@ -7,6 +7,7 @@ import com.printcalculator.model.QuoteResult; import com.printcalculator.model.StlBounds; import com.printcalculator.repository.PrinterMachineRepository; import com.printcalculator.service.QuoteCalculator; +import com.printcalculator.service.ProfileManager; import com.printcalculator.service.SlicerService; import com.printcalculator.service.StlService; import org.springframework.http.ResponseEntity; @@ -29,16 +30,18 @@ public class QuoteController { private final StlService stlService; private final QuoteCalculator quoteCalculator; private final PrinterMachineRepository machineRepo; + private final ProfileManager profileManager; // Defaults (using aliases defined in ProfileManager) private static final String DEFAULT_FILAMENT = "pla_basic"; private static final String DEFAULT_PROCESS = "standard"; - public QuoteController(SlicerService slicerService, StlService stlService, QuoteCalculator quoteCalculator, PrinterMachineRepository machineRepo) { + public QuoteController(SlicerService slicerService, StlService stlService, QuoteCalculator quoteCalculator, PrinterMachineRepository machineRepo, ProfileManager profileManager) { this.slicerService = slicerService; this.stlService = stlService; this.quoteCalculator = quoteCalculator; this.machineRepo = machineRepo; + this.profileManager = profileManager; } @PostMapping("/api/quote") @@ -125,6 +128,7 @@ public class QuoteController { if (slicerMachineProfile == null || slicerMachineProfile.isEmpty()) { slicerMachineProfile = "bambu_a1"; } + slicerMachineProfile = profileManager.resolveMachineProfileName(slicerMachineProfile, nozzleDiameter); // Validate model size against machine volume StlBounds bounds = validateModelSize(tempInput.toFile(), machine); diff --git a/backend/src/main/java/com/printcalculator/controller/QuoteSessionController.java b/backend/src/main/java/com/printcalculator/controller/QuoteSessionController.java index c677efa..7df1aa3 100644 --- a/backend/src/main/java/com/printcalculator/controller/QuoteSessionController.java +++ b/backend/src/main/java/com/printcalculator/controller/QuoteSessionController.java @@ -11,6 +11,7 @@ import com.printcalculator.repository.PrinterMachineRepository; import com.printcalculator.repository.QuoteLineItemRepository; import com.printcalculator.repository.QuoteSessionRepository; import com.printcalculator.service.QuoteCalculator; +import com.printcalculator.service.ProfileManager; import com.printcalculator.service.SlicerService; import com.printcalculator.service.StlService; import org.springframework.http.MediaType; @@ -45,6 +46,7 @@ public class QuoteSessionController { private final SlicerService slicerService; private final StlService stlService; private final QuoteCalculator quoteCalculator; + private final ProfileManager profileManager; private final PrinterMachineRepository machineRepo; private final com.printcalculator.repository.PricingPolicyRepository pricingRepo; private final com.printcalculator.service.StorageService storageService; @@ -58,6 +60,7 @@ public class QuoteSessionController { SlicerService slicerService, StlService stlService, QuoteCalculator quoteCalculator, + ProfileManager profileManager, PrinterMachineRepository machineRepo, com.printcalculator.repository.PricingPolicyRepository pricingRepo, com.printcalculator.service.StorageService storageService) { @@ -66,6 +69,7 @@ public class QuoteSessionController { this.slicerService = slicerService; this.stlService = stlService; this.quoteCalculator = quoteCalculator; + this.profileManager = profileManager; this.machineRepo = machineRepo; this.pricingRepo = pricingRepo; this.storageService = storageService; @@ -163,6 +167,7 @@ public class QuoteSessionController { if (machineProfile == null || machineProfile.isBlank()) { machineProfile = "bambu_a1"; // final fallback (alias handled in ProfileManager) } + machineProfile = profileManager.resolveMachineProfileName(machineProfile, settings.getNozzleDiameter()); String filamentProfile = "Generic " + (settings.getMaterial() != null ? settings.getMaterial().toUpperCase() : "PLA"); // Mapping: "pla_basic" -> "Generic PLA", "petg_basic" -> "Generic PETG" diff --git a/backend/src/main/java/com/printcalculator/service/ProfileManager.java b/backend/src/main/java/com/printcalculator/service/ProfileManager.java index c6bd78a..20ab438 100644 --- a/backend/src/main/java/com/printcalculator/service/ProfileManager.java +++ b/backend/src/main/java/com/printcalculator/service/ProfileManager.java @@ -16,6 +16,7 @@ import java.util.logging.Logger; import java.util.stream.Stream; import java.util.Map; import java.util.HashMap; +import java.math.BigDecimal; @Service public class ProfileManager { @@ -59,6 +60,18 @@ public class ProfileManager { return resolveInheritance(profilePath); } + public String resolveMachineProfileName(String machineName, Double nozzleDiameter) { + String resolvedName = profileAliases.getOrDefault(machineName, machineName); + if (nozzleDiameter == null) return resolvedName; + + String base = resolvedName.replaceAll("\\s*\\d+(?:\\.\\d+)?\\s*nozzle$", "").trim(); + String formatted = BigDecimal.valueOf(nozzleDiameter).stripTrailingZeros().toPlainString(); + String candidate = base + " " + formatted + " nozzle"; + + Path exists = findProfileFile(candidate, "machine"); + return exists != null ? candidate : resolvedName; + } + private Path findProfileFile(String name, String type) { // Check aliases first String resolvedName = profileAliases.getOrDefault(name, name); diff --git a/backend/src/test/java/com/printcalculator/ManualSessionPersistenceTest.java b/backend/src/test/java/com/printcalculator/ManualSessionPersistenceTest.java index adc2200..9470dd4 100644 --- a/backend/src/test/java/com/printcalculator/ManualSessionPersistenceTest.java +++ b/backend/src/test/java/com/printcalculator/ManualSessionPersistenceTest.java @@ -11,6 +11,7 @@ import com.printcalculator.service.SlicerService; import com.printcalculator.service.QuoteCalculator; import com.printcalculator.service.StorageService; import com.printcalculator.service.StlService; +import com.printcalculator.service.ProfileManager; import com.printcalculator.model.PrintStats; import com.printcalculator.model.QuoteResult; import com.printcalculator.entity.PrinterMachine; @@ -63,6 +64,9 @@ public class ManualSessionPersistenceTest { @MockitoBean private StlService stlService; + + @MockitoBean + private ProfileManager profileManager; @MockitoBean private QuoteCalculator quoteCalculator; @@ -113,6 +117,7 @@ public class ManualSessionPersistenceTest { when(stlService.readBounds(any())).thenReturn(new StlBounds(0, 0, 0, 10, 10, 10)); when(stlService.shiftToFitIfNeeded(any(), any(), anyInt(), anyInt(), anyInt())) .thenReturn(new StlShiftResult(null, 0, 0, 0, false)); + when(profileManager.resolveMachineProfileName(any(), any())).thenAnswer(i -> i.getArguments()[0]); when(storageService.loadAsResource(any())).thenReturn(new org.springframework.core.io.ByteArrayResource("dummy".getBytes()){ @Override public File getFile() { return new File("dummy"); }