Loading src/app/p_product/admin/productCatalogManagement/edit-product-specs/assign-service-specification/assign-service-specification.component.ts +97 −33 Original line number Diff line number Diff line Loading @@ -43,7 +43,7 @@ export class AssignServiceSpecificationComponent implements OnInit { @ViewChild(MatSort, {static: true}) sort: MatSort; specInputCtrl = new UntypedFormControl(); nonSelectedSpecs: ProductSpecification[] nonSelectedSpecs: ProductSpecification[] = []; filteredSpecs$: Observable<ProductSpecification[]> selectedSpecs: ProductSpecification[] = [] Loading Loading @@ -160,21 +160,19 @@ export class AssignServiceSpecificationComponent implements OnInit { }); dialogRef.afterClosed().subscribe(result => { // result === true (Yes), result === false (No), result === undefined (Cancel) if (result === true) { this.executeAssignment(true); } else if (result === false) { this.executeAssignment(false); } console.log(result); this.executeAssignment(result); }); } else { } else { this.executeAssignment(false); } } executeAssignment(importCharacteristics: boolean) { const serviceRefs: any[] = []; const newProductCharacteristics: any[] = []; let tempCharacteristics = [...(this.data.productSpec.productSpecCharacteristic || [])]; this.selectedSpecs.forEach(spec => { const sourceSpec = spec as any; Loading @@ -186,43 +184,109 @@ export class AssignServiceSpecificationComponent implements OnInit { '@type': type }); if (importCharacteristics && type === 'CustomerFacingServiceSpecification') { // If user said YES, we manually prepare the chars to add if (importCharacteristics) { const serviceChars = sourceSpec.serviceSpecCharacteristic || []; const configurableChars = serviceChars.filter(char => char.configurable === true); const mappedChars = configurableChars.map(char => ({ name: char.name, description: char.description, valueType: char.valueType, configurable: char.configurable, minCardinality: char.minCardinality, maxCardinality: char.maxCardinality, productSpecCharacteristicValue: char.serviceSpecCharacteristicValue, '@type': 'ProductSpecCharacteristic' configurableChars.forEach(sourceChar => { const cleanValues = (sourceChar.serviceSpecCharacteristicValue || []).map(val => ({ valueType: val.valueType, isDefault: val.isDefault, value: val.value, unitOfMeasure: val.unitOfMeasure, valueFrom: val.valueFrom, valueTo: val.valueTo, rangeInterval: val.rangeInterval, alias: val.alias })); newProductCharacteristics.push(...mappedChars); const newCharObj = { name: sourceChar.name, description: sourceChar.description, valueType: sourceChar.valueType, configurable: sourceChar.configurable, minCardinality: sourceChar.minCardinality, maxCardinality: sourceChar.maxCardinality, productSpecCharacteristicValue: cleanValues, '@type': 'ProductSpecCharacteristic' }; // if characteristic already exists by name, overwrite it anyway const existingCharIndex = tempCharacteristics.findIndex(c => c.name === sourceChar.name); if (existingCharIndex > -1) { tempCharacteristics[existingCharIndex] = { ...newCharObj, uuid: tempCharacteristics[existingCharIndex].uuid }; } else { tempCharacteristics.push(newCharObj); } }); } }); const existingChars = this.data.productSpec.productSpecCharacteristic || []; const finalCharacteristics = [...existingChars, ...newProductCharacteristics]; const updateRelationshipsObj: ProductSpecificationUpdate = { const payloadStep1: ProductSpecificationUpdate = { serviceSpecification: serviceRefs, productSpecCharacteristic: finalCharacteristics productSpecCharacteristic: tempCharacteristics }; // console.log(updateRelationshipsObj); this.productSpecService.patchProductSpecification({ id: this.data.productSpec.id, productSpecification: updateRelationshipsObj productSpecification: payloadStep1 }).subscribe( (updatedSpec) => { // If user said NO, and we have CFSS, we need to check if backend added them // and remove them (patching the list without them) if (!importCharacteristics) { this.removeUnwantedCharacteristics(updatedSpec); } else { this.toast.success('Product Specification updated successfully'); this.dialogRef.close('updated'); } }, error => { console.error('Update failed', error); this.toast.error('Failed to update Product Specification'); } ); } removeUnwantedCharacteristics(spec: ProductSpecification) { // identify characteristics to remove (from CFSS) if user clicks no const unwantedNames: string[] = []; this.selectedSpecs.forEach(s => { const sourceSpec = s as any; if (sourceSpec['@type'] === 'CustomerFacingServiceSpecification') { const chars = sourceSpec.serviceSpecCharacteristic || []; chars.filter(c => c.configurable).forEach(c => unwantedNames.push(c.name)); } }); const currentChars = spec.productSpecCharacteristic || []; const newSpecCharacteristicArray = currentChars.filter(c => !unwantedNames.includes(c.name)); // If there is nothing to change, just close if (newSpecCharacteristicArray.length === currentChars.length) { this.dialogRef.close('updated'); return; } const updateCharacteristicObj: ProductSpecificationUpdate = { productSpecCharacteristic: newSpecCharacteristicArray } this.productSpecService.patchProductSpecification({ id: spec.id, productSpecification: updateCharacteristicObj }).subscribe( data => {}, error => this.toast.error('Failed to update Product Specification', error), () => {this.dialogRef.close('updated')} error => { this.toast.warning('Service assigned, but failed to clean up auto-assigned characteristics.'); this.dialogRef.close('updated'); }, () => { this.dialogRef.close('updated'); } ) } Loading src/app/p_product/admin/productCatalogManagement/edit-product-specs/assign-service-specification/confirm-characteristic-assignment/confirm-characteristic-assignment.component.html +1 −2 Original line number Diff line number Diff line Loading @@ -8,7 +8,6 @@ </p> </mat-dialog-content> <mat-dialog-actions align="end"> <button (click)="onCancel()" class="btn btn-danger">Cancel</button> <button (click)="onYes()" class="btn btn-success ml-2">Yes, Import Characteristics</button> <button (click)="onNo()" class="btn btn-primary ml-2">No, just link Service Specification</button> <button (click)="onYes()" class="btn btn-success mt-2">Yes, Import Characteristics</button> </mat-dialog-actions> No newline at end of file src/app/p_product/admin/productCatalogManagement/edit-product-specs/assign-service-specification/confirm-characteristic-assignment/confirm-characteristic-assignment.component.ts +2 −6 Original line number Diff line number Diff line Loading @@ -12,15 +12,11 @@ export class ConfirmCharacteristicAssignmentComponent { public dialogRef: MatDialogRef<ConfirmCharacteristicAssignmentComponent> ) {} onCancel(): void { this.dialogRef.close(); // Returns undefined } onNo(): void { this.dialogRef.close(false); // Returns false this.dialogRef.close(false); } onYes(): void { this.dialogRef.close(true); // Returns true this.dialogRef.close(true); } } No newline at end of file Loading
src/app/p_product/admin/productCatalogManagement/edit-product-specs/assign-service-specification/assign-service-specification.component.ts +97 −33 Original line number Diff line number Diff line Loading @@ -43,7 +43,7 @@ export class AssignServiceSpecificationComponent implements OnInit { @ViewChild(MatSort, {static: true}) sort: MatSort; specInputCtrl = new UntypedFormControl(); nonSelectedSpecs: ProductSpecification[] nonSelectedSpecs: ProductSpecification[] = []; filteredSpecs$: Observable<ProductSpecification[]> selectedSpecs: ProductSpecification[] = [] Loading Loading @@ -160,21 +160,19 @@ export class AssignServiceSpecificationComponent implements OnInit { }); dialogRef.afterClosed().subscribe(result => { // result === true (Yes), result === false (No), result === undefined (Cancel) if (result === true) { this.executeAssignment(true); } else if (result === false) { this.executeAssignment(false); } console.log(result); this.executeAssignment(result); }); } else { } else { this.executeAssignment(false); } } executeAssignment(importCharacteristics: boolean) { const serviceRefs: any[] = []; const newProductCharacteristics: any[] = []; let tempCharacteristics = [...(this.data.productSpec.productSpecCharacteristic || [])]; this.selectedSpecs.forEach(spec => { const sourceSpec = spec as any; Loading @@ -186,43 +184,109 @@ export class AssignServiceSpecificationComponent implements OnInit { '@type': type }); if (importCharacteristics && type === 'CustomerFacingServiceSpecification') { // If user said YES, we manually prepare the chars to add if (importCharacteristics) { const serviceChars = sourceSpec.serviceSpecCharacteristic || []; const configurableChars = serviceChars.filter(char => char.configurable === true); const mappedChars = configurableChars.map(char => ({ name: char.name, description: char.description, valueType: char.valueType, configurable: char.configurable, minCardinality: char.minCardinality, maxCardinality: char.maxCardinality, productSpecCharacteristicValue: char.serviceSpecCharacteristicValue, '@type': 'ProductSpecCharacteristic' configurableChars.forEach(sourceChar => { const cleanValues = (sourceChar.serviceSpecCharacteristicValue || []).map(val => ({ valueType: val.valueType, isDefault: val.isDefault, value: val.value, unitOfMeasure: val.unitOfMeasure, valueFrom: val.valueFrom, valueTo: val.valueTo, rangeInterval: val.rangeInterval, alias: val.alias })); newProductCharacteristics.push(...mappedChars); const newCharObj = { name: sourceChar.name, description: sourceChar.description, valueType: sourceChar.valueType, configurable: sourceChar.configurable, minCardinality: sourceChar.minCardinality, maxCardinality: sourceChar.maxCardinality, productSpecCharacteristicValue: cleanValues, '@type': 'ProductSpecCharacteristic' }; // if characteristic already exists by name, overwrite it anyway const existingCharIndex = tempCharacteristics.findIndex(c => c.name === sourceChar.name); if (existingCharIndex > -1) { tempCharacteristics[existingCharIndex] = { ...newCharObj, uuid: tempCharacteristics[existingCharIndex].uuid }; } else { tempCharacteristics.push(newCharObj); } }); } }); const existingChars = this.data.productSpec.productSpecCharacteristic || []; const finalCharacteristics = [...existingChars, ...newProductCharacteristics]; const updateRelationshipsObj: ProductSpecificationUpdate = { const payloadStep1: ProductSpecificationUpdate = { serviceSpecification: serviceRefs, productSpecCharacteristic: finalCharacteristics productSpecCharacteristic: tempCharacteristics }; // console.log(updateRelationshipsObj); this.productSpecService.patchProductSpecification({ id: this.data.productSpec.id, productSpecification: updateRelationshipsObj productSpecification: payloadStep1 }).subscribe( (updatedSpec) => { // If user said NO, and we have CFSS, we need to check if backend added them // and remove them (patching the list without them) if (!importCharacteristics) { this.removeUnwantedCharacteristics(updatedSpec); } else { this.toast.success('Product Specification updated successfully'); this.dialogRef.close('updated'); } }, error => { console.error('Update failed', error); this.toast.error('Failed to update Product Specification'); } ); } removeUnwantedCharacteristics(spec: ProductSpecification) { // identify characteristics to remove (from CFSS) if user clicks no const unwantedNames: string[] = []; this.selectedSpecs.forEach(s => { const sourceSpec = s as any; if (sourceSpec['@type'] === 'CustomerFacingServiceSpecification') { const chars = sourceSpec.serviceSpecCharacteristic || []; chars.filter(c => c.configurable).forEach(c => unwantedNames.push(c.name)); } }); const currentChars = spec.productSpecCharacteristic || []; const newSpecCharacteristicArray = currentChars.filter(c => !unwantedNames.includes(c.name)); // If there is nothing to change, just close if (newSpecCharacteristicArray.length === currentChars.length) { this.dialogRef.close('updated'); return; } const updateCharacteristicObj: ProductSpecificationUpdate = { productSpecCharacteristic: newSpecCharacteristicArray } this.productSpecService.patchProductSpecification({ id: spec.id, productSpecification: updateCharacteristicObj }).subscribe( data => {}, error => this.toast.error('Failed to update Product Specification', error), () => {this.dialogRef.close('updated')} error => { this.toast.warning('Service assigned, but failed to clean up auto-assigned characteristics.'); this.dialogRef.close('updated'); }, () => { this.dialogRef.close('updated'); } ) } Loading
src/app/p_product/admin/productCatalogManagement/edit-product-specs/assign-service-specification/confirm-characteristic-assignment/confirm-characteristic-assignment.component.html +1 −2 Original line number Diff line number Diff line Loading @@ -8,7 +8,6 @@ </p> </mat-dialog-content> <mat-dialog-actions align="end"> <button (click)="onCancel()" class="btn btn-danger">Cancel</button> <button (click)="onYes()" class="btn btn-success ml-2">Yes, Import Characteristics</button> <button (click)="onNo()" class="btn btn-primary ml-2">No, just link Service Specification</button> <button (click)="onYes()" class="btn btn-success mt-2">Yes, Import Characteristics</button> </mat-dialog-actions> No newline at end of file
src/app/p_product/admin/productCatalogManagement/edit-product-specs/assign-service-specification/confirm-characteristic-assignment/confirm-characteristic-assignment.component.ts +2 −6 Original line number Diff line number Diff line Loading @@ -12,15 +12,11 @@ export class ConfirmCharacteristicAssignmentComponent { public dialogRef: MatDialogRef<ConfirmCharacteristicAssignmentComponent> ) {} onCancel(): void { this.dialogRef.close(); // Returns undefined } onNo(): void { this.dialogRef.close(false); // Returns false this.dialogRef.close(false); } onYes(): void { this.dialogRef.close(true); // Returns true this.dialogRef.close(true); } } No newline at end of file