fix(back-end): fix 3mf calculator
Some checks failed
Build and Deploy / test-backend (push) Successful in 24s
Build and Deploy / test-frontend (push) Successful in 1m0s
Build and Deploy / build-and-push (push) Failing after 14s
Build and Deploy / deploy (push) Has been skipped

This commit is contained in:
2026-03-04 09:24:21 +01:00
parent 6eb0629136
commit db748fb649
2 changed files with 55 additions and 3 deletions

View File

@@ -146,6 +146,7 @@ public class QuoteSessionController {
Files.copy(inputStream, persistentPath, StandardCopyOption.REPLACE_EXISTING);
}
Path convertedPersistentPath = null;
try {
// Apply Basic/Advanced Logic
applyPrintSettings(settings);
@@ -182,10 +183,21 @@ public class QuoteSessionController {
if (settings.getLayerHeight() != null) processOverrides.put("layer_height", String.valueOf(settings.getLayerHeight()));
if (settings.getInfillDensity() != null) processOverrides.put("sparse_infill_density", settings.getInfillDensity() + "%");
if (settings.getInfillPattern() != null) processOverrides.put("sparse_infill_pattern", settings.getInfillPattern());
Path slicerInputPath = persistentPath;
if ("3mf".equals(ext)) {
String convertedFilename = UUID.randomUUID() + "-converted.stl";
convertedPersistentPath = sessionStorageDir.resolve(convertedFilename).normalize();
if (!convertedPersistentPath.startsWith(sessionStorageDir)) {
throw new IOException("Invalid converted STL storage path");
}
slicerService.convert3mfToPersistentStl(persistentPath.toFile(), convertedPersistentPath);
slicerInputPath = convertedPersistentPath;
}
// 3. Slice (Use persistent path)
PrintStats stats = slicerService.slice(
persistentPath.toFile(),
slicerInputPath.toFile(),
machineProfile,
filamentProfile,
processProfile,
@@ -193,7 +205,7 @@ public class QuoteSessionController {
processOverrides
);
Optional<ModelDimensions> modelDimensions = slicerService.inspectModelDimensions(persistentPath.toFile());
Optional<ModelDimensions> modelDimensions = slicerService.inspectModelDimensions(slicerInputPath.toFile());
// 4. Calculate Quote
QuoteResult result = quoteCalculator.calculate(stats, machine.getPrinterDisplayName(), selectedVariant);
@@ -216,6 +228,9 @@ public class QuoteSessionController {
Map<String, Object> breakdown = new HashMap<>();
breakdown.put("machine_cost", result.getTotalPrice()); // Excludes setup fee which is at session level
breakdown.put("setup_fee", 0);
if (convertedPersistentPath != null) {
breakdown.put("convertedStoredPath", QUOTE_STORAGE_ROOT.relativize(convertedPersistentPath).toString());
}
item.setPricingBreakdown(breakdown);
// Dimensions for shipping/package checks are computed server-side from the uploaded model.
@@ -237,6 +252,9 @@ public class QuoteSessionController {
} catch (Exception e) {
// Cleanup if failed
Files.deleteIfExists(persistentPath);
if (convertedPersistentPath != null) {
Files.deleteIfExists(convertedPersistentPath);
}
throw e;
}
}

View File

@@ -331,6 +331,31 @@ public class SlicerService {
return convertedStlPaths;
}
public Path convert3mfToPersistentStl(File input3mf, Path destinationStl) throws IOException {
Path tempDir = Files.createTempDirectory("slicer_convert_");
try {
List<String> convertedPaths = convert3mfToStlInputPaths(input3mf, tempDir);
if (convertedPaths.isEmpty()) {
throw new ModelProcessingException(
"MODEL_CONVERSION_FAILED",
"Unable to process this 3MF file. Try another format or contact us directly via Request Consultation."
);
}
Path source = Path.of(convertedPaths.get(0));
Path parent = destinationStl.toAbsolutePath().normalize().getParent();
if (parent != null) {
Files.createDirectories(parent);
}
Files.copy(source, destinationStl, java.nio.file.StandardCopyOption.REPLACE_EXISTING);
return destinationStl;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new IOException("Interrupted during 3MF conversion", e);
} finally {
deleteRecursively(tempDir);
}
}
private List<String> convert3mfToStlInputPaths(File input3mf, Path tempDir) throws IOException, InterruptedException {
Path conversionOutputDir = tempDir.resolve("converted-from-3mf");
Files.createDirectories(conversionOutputDir);
@@ -378,7 +403,16 @@ public class SlicerService {
try {
objLog = runAssimpExport(input3mfPath, conversionOutputObjPath, tempDir.resolve("assimp-convert-obj.log"));
if (hasRenderableGeometry(convertedObj)) {
return List.of(convertedObj.toString());
Path stlFromObj = conversionOutputDir.resolve("converted-from-obj.stl");
runAssimpExport(
convertedObj.toString(),
stlFromObj.toString(),
tempDir.resolve("assimp-convert-obj-to-stl.log")
);
if (hasRenderableGeometry(stlFromObj)) {
return List.of(stlFromObj.toString());
}
logger.warning("Assimp OBJ->STL conversion produced empty geometry.");
}
logger.warning("Assimp OBJ conversion produced empty geometry.");
} catch (IOException e) {