feat(back-end): new stock db and back-office improvements
This commit is contained in:
@@ -135,7 +135,10 @@ export class CalculatorPageComponent implements OnInit {
|
||||
// Assuming index matches.
|
||||
// Need to be careful if items order changed, but usually ID sort or insert order.
|
||||
if (item.colorCode) {
|
||||
this.uploadForm.updateItemColor(index, item.colorCode);
|
||||
this.uploadForm.updateItemColor(index, {
|
||||
colorName: item.colorCode,
|
||||
filamentVariantId: item.filamentVariantId
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
<label>{{ 'CALC.COLOR_LABEL' | translate }}</label>
|
||||
<app-color-selector
|
||||
[selectedColor]="item.color"
|
||||
[selectedVariantId]="item.filamentVariantId ?? null"
|
||||
[variants]="currentMaterialVariants()"
|
||||
(colorSelected)="updateItemColor(i, $event)">
|
||||
</app-color-selector>
|
||||
|
||||
@@ -15,6 +15,7 @@ interface FormItem {
|
||||
file: File;
|
||||
quantity: number;
|
||||
color: string;
|
||||
filamentVariantId?: number;
|
||||
}
|
||||
|
||||
@Component({
|
||||
@@ -58,6 +59,7 @@ export class UploadFormComponent implements OnInit {
|
||||
if (matCode && this.fullMaterialOptions.length > 0) {
|
||||
const found = this.fullMaterialOptions.find(m => m.code === matCode);
|
||||
this.currentMaterialVariants.set(found ? found.variants : []);
|
||||
this.syncItemVariantSelections();
|
||||
} else {
|
||||
this.currentMaterialVariants.set([]);
|
||||
}
|
||||
@@ -166,8 +168,13 @@ export class UploadFormComponent implements OnInit {
|
||||
if (file.size > MAX_SIZE) {
|
||||
hasError = true;
|
||||
} else {
|
||||
// Default color is Black
|
||||
validItems.push({ file, quantity: 1, color: 'Black' });
|
||||
const defaultSelection = this.getDefaultVariantSelection();
|
||||
validItems.push({
|
||||
file,
|
||||
quantity: 1,
|
||||
color: defaultSelection.colorName,
|
||||
filamentVariantId: defaultSelection.filamentVariantId
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,7 +227,9 @@ export class UploadFormComponent implements OnInit {
|
||||
if (item) {
|
||||
const vars = this.currentMaterialVariants();
|
||||
if (vars && vars.length > 0) {
|
||||
const found = vars.find(v => v.colorName === item.color);
|
||||
const found = item.filamentVariantId
|
||||
? vars.find(v => v.id === item.filamentVariantId)
|
||||
: vars.find(v => v.colorName === item.color);
|
||||
if (found) return found.hexColor;
|
||||
}
|
||||
return getColorHex(item.color);
|
||||
@@ -240,10 +249,12 @@ export class UploadFormComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
updateItemColor(index: number, newColor: string) {
|
||||
updateItemColor(index: number, newSelection: string | { colorName: string; filamentVariantId?: number }) {
|
||||
const colorName = typeof newSelection === 'string' ? newSelection : newSelection.colorName;
|
||||
const filamentVariantId = typeof newSelection === 'string' ? undefined : newSelection.filamentVariantId;
|
||||
this.items.update(current => {
|
||||
const updated = [...current];
|
||||
updated[index] = { ...updated[index], color: newColor };
|
||||
updated[index] = { ...updated[index], color: colorName, filamentVariantId };
|
||||
return updated;
|
||||
});
|
||||
}
|
||||
@@ -261,9 +272,14 @@ export class UploadFormComponent implements OnInit {
|
||||
|
||||
setFiles(files: File[]) {
|
||||
const validItems: FormItem[] = [];
|
||||
const defaultSelection = this.getDefaultVariantSelection();
|
||||
for (const file of files) {
|
||||
// Default color is Black or derive from somewhere if possible, but here we just init
|
||||
validItems.push({ file, quantity: 1, color: 'Black' });
|
||||
validItems.push({
|
||||
file,
|
||||
quantity: 1,
|
||||
color: defaultSelection.colorName,
|
||||
filamentVariantId: defaultSelection.filamentVariantId
|
||||
});
|
||||
}
|
||||
|
||||
if (validItems.length > 0) {
|
||||
@@ -274,6 +290,39 @@ export class UploadFormComponent implements OnInit {
|
||||
}
|
||||
}
|
||||
|
||||
private getDefaultVariantSelection(): { colorName: string; filamentVariantId?: number } {
|
||||
const vars = this.currentMaterialVariants();
|
||||
if (vars && vars.length > 0) {
|
||||
const preferred = vars.find(v => !v.isOutOfStock) || vars[0];
|
||||
return {
|
||||
colorName: preferred.colorName,
|
||||
filamentVariantId: preferred.id
|
||||
};
|
||||
}
|
||||
return { colorName: 'Black' };
|
||||
}
|
||||
|
||||
private syncItemVariantSelections(): void {
|
||||
const vars = this.currentMaterialVariants();
|
||||
if (!vars || vars.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const fallback = vars.find(v => !v.isOutOfStock) || vars[0];
|
||||
this.items.update(current => current.map(item => {
|
||||
const byId = item.filamentVariantId != null
|
||||
? vars.find(v => v.id === item.filamentVariantId)
|
||||
: null;
|
||||
const byColor = vars.find(v => v.colorName === item.color);
|
||||
const selected = byId || byColor || fallback;
|
||||
return {
|
||||
...item,
|
||||
color: selected.colorName,
|
||||
filamentVariantId: selected.id
|
||||
};
|
||||
}));
|
||||
}
|
||||
|
||||
patchSettings(settings: any) {
|
||||
if (!settings) return;
|
||||
// settings object matches keys in our form?
|
||||
|
||||
@@ -5,7 +5,7 @@ import { map, catchError, tap } from 'rxjs/operators';
|
||||
import { environment } from '../../../../environments/environment';
|
||||
|
||||
export interface QuoteRequest {
|
||||
items: { file: File, quantity: number, color?: string }[];
|
||||
items: { file: File, quantity: number, color?: string, filamentVariantId?: number }[];
|
||||
material: string;
|
||||
quality: string;
|
||||
notes?: string;
|
||||
@@ -26,6 +26,7 @@ export interface QuoteItem {
|
||||
quantity: number;
|
||||
material?: string;
|
||||
color?: string;
|
||||
filamentVariantId?: number;
|
||||
}
|
||||
|
||||
export interface QuoteResult {
|
||||
@@ -72,9 +73,13 @@ export interface MaterialOption {
|
||||
variants: VariantOption[];
|
||||
}
|
||||
export interface VariantOption {
|
||||
id: number;
|
||||
name: string;
|
||||
colorName: string;
|
||||
hexColor: string;
|
||||
finishType: string;
|
||||
stockSpools: number;
|
||||
stockFilamentGrams: number;
|
||||
isOutOfStock: boolean;
|
||||
}
|
||||
export interface QualityOption {
|
||||
@@ -250,6 +255,7 @@ export class QuoteEstimatorService {
|
||||
const settings = {
|
||||
complexityMode: request.mode === 'easy' ? 'ADVANCED' : request.mode.toUpperCase(),
|
||||
material: request.material,
|
||||
filamentVariantId: item.filamentVariantId,
|
||||
quality: easyPreset ? easyPreset.quality : request.quality,
|
||||
supportsEnabled: request.supportEnabled,
|
||||
color: item.color || '#FFFFFF',
|
||||
@@ -351,7 +357,8 @@ export class QuoteEstimatorService {
|
||||
material: session.materialCode, // Assumption: session has one material for all? or items have it?
|
||||
// Backend model QuoteSession has materialCode.
|
||||
// But line items might have different colors.
|
||||
color: item.colorCode
|
||||
color: item.colorCode,
|
||||
filamentVariantId: item.filamentVariantId
|
||||
})),
|
||||
setupCost: session.setupCostChf || 0,
|
||||
globalMachineCost: sessionData.globalMachineCostChf || 0,
|
||||
|
||||
Reference in New Issue
Block a user