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 1m2s
Build and Deploy / build-and-push (push) Failing after 55s
Build and Deploy / deploy (push) Has been skipped

This commit is contained in:
2026-03-03 18:48:59 +01:00
parent e23bca0734
commit 8bd4ea54b2
8 changed files with 72 additions and 7 deletions

View File

@@ -10,6 +10,8 @@ RUN ./gradlew bootJar -x test --no-daemon
# Stage 2: Runtime Environment # Stage 2: Runtime Environment
FROM eclipse-temurin:21-jre-jammy FROM eclipse-temurin:21-jre-jammy
ARG ORCA_VERSION=2.3.1
ARG ORCA_DOWNLOAD_URL
# Install system dependencies for OrcaSlicer (same as before) # Install system dependencies for OrcaSlicer (same as before)
RUN apt-get update && apt-get install -y \ RUN apt-get update && apt-get install -y \
@@ -25,7 +27,12 @@ RUN apt-get update && apt-get install -y \
# Install OrcaSlicer # Install OrcaSlicer
WORKDIR /opt WORKDIR /opt
RUN wget -q https://github.com/SoftFever/OrcaSlicer/releases/download/v2.2.0/OrcaSlicer_Linux_V2.2.0.AppImage -O OrcaSlicer.AppImage \ RUN set -eux; \
ORCA_URL="${ORCA_DOWNLOAD_URL:-}"; \
if [ -z "${ORCA_URL}" ]; then \
ORCA_URL="https://github.com/OrcaSlicer/OrcaSlicer/releases/download/v${ORCA_VERSION}/OrcaSlicer_Linux_V${ORCA_VERSION}.AppImage"; \
fi; \
wget -q "${ORCA_URL}" -O OrcaSlicer.AppImage \
&& 7z x OrcaSlicer.AppImage -o/opt/orcaslicer \ && 7z x OrcaSlicer.AppImage -o/opt/orcaslicer \
&& chmod -R +x /opt/orcaslicer \ && chmod -R +x /opt/orcaslicer \
&& rm OrcaSlicer.AppImage && rm OrcaSlicer.AppImage

View File

@@ -4,6 +4,13 @@
@if (error()) { @if (error()) {
<app-alert type="error">{{ errorKey() | translate }}</app-alert> <app-alert type="error">{{ errorKey() | translate }}</app-alert>
@if (isZeroQuoteError()) {
<div class="error-action">
<app-button variant="outline" (click)="onConsult()">
{{ "QUOTE.CONSULT" | translate }}
</app-button>
</div>
}
} }
</div> </div>
@@ -65,6 +72,16 @@
(proceed)="onProceed()" (proceed)="onProceed()"
(itemChange)="onItemChange($event)" (itemChange)="onItemChange($event)"
></app-quote-result> ></app-quote-result>
} @else if (isZeroQuoteError()) {
<app-card class="zero-result-card">
<h3>{{ "CALC.ZERO_RESULT_TITLE" | translate }}</h3>
<p>{{ "CALC.ZERO_RESULT_HELP" | translate }}</p>
<div class="zero-result-action">
<app-button variant="outline" (click)="onConsult()">
{{ "QUOTE.CONSULT" | translate }}
</app-button>
</div>
</app-card>
} @else { } @else {
<app-card> <app-card>
<h3>{{ "CALC.BENEFITS_TITLE" | translate }}</h3> <h3>{{ "CALC.BENEFITS_TITLE" | translate }}</h3>

View File

@@ -9,6 +9,12 @@
margin: 0 auto; margin: 0 auto;
} }
.error-action {
display: flex;
justify-content: center;
margin-top: calc(var(--space-4) * -1);
}
.content-grid { .content-grid {
display: grid; display: grid;
grid-template-columns: 1fr; grid-template-columns: 1fr;
@@ -82,6 +88,15 @@
line-height: 2; line-height: 2;
} }
.zero-result-card p {
color: var(--color-text-muted);
line-height: 1.6;
}
.zero-result-action {
margin-top: var(--space-4);
}
.loader-content { .loader-content {
text-align: center; text-align: center;
max-width: 300px; max-width: 300px;

View File

@@ -1,5 +1,6 @@
import { import {
Component, Component,
computed,
signal, signal,
ViewChild, ViewChild,
ElementRef, ElementRef,
@@ -12,6 +13,7 @@ import { map } from 'rxjs/operators';
import { AppCardComponent } from '../../shared/components/app-card/app-card.component'; import { AppCardComponent } from '../../shared/components/app-card/app-card.component';
import { AppAlertComponent } from '../../shared/components/app-alert/app-alert.component'; import { AppAlertComponent } from '../../shared/components/app-alert/app-alert.component';
import { AppButtonComponent } from '../../shared/components/app-button/app-button.component';
import { UploadFormComponent } from './components/upload-form/upload-form.component'; import { UploadFormComponent } from './components/upload-form/upload-form.component';
import { QuoteResultComponent } from './components/quote-result/quote-result.component'; import { QuoteResultComponent } from './components/quote-result/quote-result.component';
import { import {
@@ -31,6 +33,7 @@ import { LanguageService } from '../../core/services/language.service';
TranslateModule, TranslateModule,
AppCardComponent, AppCardComponent,
AppAlertComponent, AppAlertComponent,
AppButtonComponent,
UploadFormComponent, UploadFormComponent,
QuoteResultComponent, QuoteResultComponent,
SuccessStateComponent, SuccessStateComponent,
@@ -47,6 +50,9 @@ export class CalculatorPageComponent implements OnInit {
result = signal<QuoteResult | null>(null); result = signal<QuoteResult | null>(null);
error = signal<boolean>(false); error = signal<boolean>(false);
errorKey = signal<string>('CALC.ERROR_GENERIC'); errorKey = signal<string>('CALC.ERROR_GENERIC');
isZeroQuoteError = computed(
() => this.error() && this.errorKey() === 'CALC.ERROR_ZERO_PRICE',
);
orderSuccess = signal(false); orderSuccess = signal(false);
@@ -318,7 +324,10 @@ export class CalculatorPageComponent implements OnInit {
private currentRequest: QuoteRequest | null = null; private currentRequest: QuoteRequest | null = null;
onConsult() { onConsult() {
if (!this.currentRequest) return; if (!this.currentRequest) {
this.router.navigate(['/', this.languageService.selectedLang(), 'contact']);
return;
}
const req = this.currentRequest; const req = this.currentRequest;
let details = `Richiesta Preventivo:\n`; let details = `Richiesta Preventivo:\n`;
@@ -349,7 +358,16 @@ export class CalculatorPageComponent implements OnInit {
} }
private isInvalidQuote(result: QuoteResult): boolean { private isInvalidQuote(result: QuoteResult): boolean {
return !Number.isFinite(result.totalPrice) || result.totalPrice <= 0; const invalidPrice =
!Number.isFinite(result.totalPrice) || result.totalPrice <= 0;
const invalidWeight =
!Number.isFinite(result.totalWeight) || result.totalWeight <= 0;
const invalidTime =
!Number.isFinite(result.totalTimeHours) ||
!Number.isFinite(result.totalTimeMinutes) ||
(result.totalTimeHours <= 0 && result.totalTimeMinutes <= 0);
return invalidPrice || invalidWeight || invalidTime;
} }
private setQuoteError(key: string): void { private setQuoteError(key: string): void {

View File

@@ -91,7 +91,9 @@
"NOTES_PLACEHOLDER": "Spezifische Anweisungen...", "NOTES_PLACEHOLDER": "Spezifische Anweisungen...",
"SETUP_NOTE": "* Beinhaltet {{cost}} als Einrichtungskosten", "SETUP_NOTE": "* Beinhaltet {{cost}} als Einrichtungskosten",
"SHIPPING_NOTE": "** Versandkosten ausgeschlossen, werden im nächsten Schritt berechnet", "SHIPPING_NOTE": "** Versandkosten ausgeschlossen, werden im nächsten Schritt berechnet",
"ERROR_ZERO_PRICE": "Etwas ist schiefgelaufen. Versuche ein anderes Format oder kontaktiere uns." "ERROR_ZERO_PRICE": "Bei der Berechnung ist etwas schiefgelaufen. Versuche ein anderes Format oder kontaktiere uns direkt über \"Beratung anfragen\".",
"ZERO_RESULT_TITLE": "Ungültiges Ergebnis",
"ZERO_RESULT_HELP": "Die Berechnung hat ungültige Werte (0) geliefert. Versuche ein anderes Dateiformat oder kontaktiere uns direkt über \"Beratung anfragen\"."
}, },
"SHOP": { "SHOP": {
"TITLE": "Technische Lösungen", "TITLE": "Technische Lösungen",

View File

@@ -91,7 +91,9 @@
"NOTES_PLACEHOLDER": "Specific instructions...", "NOTES_PLACEHOLDER": "Specific instructions...",
"SETUP_NOTE": "* Includes {{cost}} as setup cost", "SETUP_NOTE": "* Includes {{cost}} as setup cost",
"SHIPPING_NOTE": "** Shipping costs excluded, calculated at the next step", "SHIPPING_NOTE": "** Shipping costs excluded, calculated at the next step",
"ERROR_ZERO_PRICE": "Something went wrong. Try another format or contact us." "ERROR_ZERO_PRICE": "Something went wrong during the calculation. Try another format or contact us directly via Request Consultation.",
"ZERO_RESULT_TITLE": "Invalid Result",
"ZERO_RESULT_HELP": "The calculation returned invalid zero values. Try another file format or contact us directly via Request Consultation."
}, },
"SHOP": { "SHOP": {
"TITLE": "Technical solutions", "TITLE": "Technical solutions",

View File

@@ -116,7 +116,9 @@
"FALLBACK_MATERIAL": "PLA (fallback)", "FALLBACK_MATERIAL": "PLA (fallback)",
"FALLBACK_QUALITY_STANDARD": "Standard", "FALLBACK_QUALITY_STANDARD": "Standard",
"ERR_FILE_TOO_LARGE": "Certains fichiers dépassent la limite de 200MB et n'ont pas été ajoutés.", "ERR_FILE_TOO_LARGE": "Certains fichiers dépassent la limite de 200MB et n'ont pas été ajoutés.",
"ERROR_ZERO_PRICE": "Quelque chose s'est mal passé. Essayez un autre format ou contactez-nous." "ERROR_ZERO_PRICE": "Un problème est survenu pendant le calcul. Essayez un autre format ou contactez-nous directement via Demander une consultation.",
"ZERO_RESULT_TITLE": "Résultat invalide",
"ZERO_RESULT_HELP": "Le calcul a renvoyé des valeurs nulles invalides. Essayez un autre format de fichier ou contactez-nous directement via Demander une consultation."
}, },
"QUOTE": { "QUOTE": {
"PROCEED_ORDER": "Procéder à la commande", "PROCEED_ORDER": "Procéder à la commande",

View File

@@ -116,7 +116,9 @@
"FALLBACK_MATERIAL": "PLA (fallback)", "FALLBACK_MATERIAL": "PLA (fallback)",
"FALLBACK_QUALITY_STANDARD": "Standard", "FALLBACK_QUALITY_STANDARD": "Standard",
"ERR_FILE_TOO_LARGE": "Alcuni file superano il limite di 200MB e non sono stati aggiunti.", "ERR_FILE_TOO_LARGE": "Alcuni file superano il limite di 200MB e non sono stati aggiunti.",
"ERROR_ZERO_PRICE": "Qualcosa è andato storto. Prova con un altro formato oppure contattaci." "ERROR_ZERO_PRICE": "Qualcosa è andato storto nel calcolo. Prova un altro formato o contattaci direttamente con Richiedi Consulenza.",
"ZERO_RESULT_TITLE": "Risultato non valido",
"ZERO_RESULT_HELP": "Il calcolo ha restituito valori non validi (0). Prova con un altro formato file oppure contattaci direttamente con Richiedi Consulenza."
}, },
"QUOTE": { "QUOTE": {
"PROCEED_ORDER": "Procedi con l'ordine", "PROCEED_ORDER": "Procedi con l'ordine",