Commit f8c86993 authored by Michail Tzanatos's avatar Michail Tzanatos
Browse files

refactor product order management components to enhance related service order...

refactor product order management components to enhance related service order retrieval, and improve UI elements for better clarity and functionality
parent cd1054cb
Loading
Loading
Loading
Loading
Loading
+2 −81
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@
        <span>Edit Order Item's Service Specification Characteristics</span>
    </h4> -->
    <div  *ngIf="productSpec && orderItem" class="service-spec-container">
        <div *ngIf="confSpecCharacteristics.length === 0 && nonConfSpecCharacteristics.length === 0" class="mt-3" [@fadeIn]>
        <div *ngIf="confSpecCharacteristics.length === 0" class="mt-3" [@fadeIn]>
            <i>This product does not contain any configurable characteristics</i>
        </div>

@@ -126,86 +126,7 @@
            
        </div>

        <div formArray = "nonConfSpecFormArray" *ngIf="nonConfSpecCharacteristics.length > 0" [@fadeIn]>
            <h5 class="my-3">
                <span class="fa-stack" style="margin-left:-10px">
                    <i class="fas fa-user-edit fa-stack-1x"></i>
                    <i class="fas fa-ban fa-stack-2x" style="color:Tomato; opacity: 0.5;"></i>
                </span>
                Non Configurable Characteristics
            </h5>
        
            <div *ngFor="let charForm of nonConfSpecFormArray.controls; let i = index; let last = last;" [formGroup]="charForm"
            class="row align-items-center justify-content-center"
            [ngClass]="{'border-bottom':!last, 'align-items-center':charForm.get('valueType').value !=='ARRAY', 'align-items-baseline':charForm.get('valueType').value ==='ARRAY'}">
                <div class="col-lg-6"><b>{{charForm.get('name').value}}</b></div>
                
                <div class="col-lg-6" [ngSwitch]="charForm.get('valueType').value">
    
                    <ng-container *ngSwitchCase="'SET'">
                        <ng-container *ngTemplateOutlet="iterables"></ng-container>
                    </ng-container>

                    <ng-container *ngSwitchCase="'ARRAY'">
                        <ng-container *ngTemplateOutlet="iterables"></ng-container>
                    </ng-container>

                    <ng-container *ngSwitchCase="'ENUM'">
                        <ng-container *ngTemplateOutlet="enumerable"></ng-container>
                    </ng-container>

                    <ng-container *ngSwitchCase="'BINARY'">
                        <ng-container *ngTemplateOutlet="enumerable"></ng-container>
                    </ng-container>

                    <ng-container *ngSwitchCase="'TIMESTAMP'">
                        <mat-form-field [owlDateTimeTrigger]="pickerFrom">
                            <mat-label>Custom Value</mat-label>
                            <input matInput [owlDateTime]="pickerFrom" placeholder="Date Time"
                                [(ngModel)]="charForm.get('value').value[0].value.value"
                                [ngModelOptions]="{standalone: true}">
                            <mat-icon matSuffix>date_range</mat-icon>
                            <!-- <span [owlDateTimeTrigger]="dt1"><i class="fa fa-calendar"></i></span> -->
                            <owl-date-time #pickerFrom></owl-date-time>
                        </mat-form-field>
                    </ng-container>

                    <ng-container *ngSwitchDefault>
                        <mat-form-field>
                            <mat-label>Custom Value</mat-label>
                            <input matInput [(ngModel)]="charForm.get('value').value.value"
                                [ngModelOptions]="{standalone: true}">
                        </mat-form-field>
                    </ng-container>

                    <ng-template #iterables>
                        <mat-form-field>
                            <mat-label>Custom Value</mat-label>
                            <mat-select formControlName="value" [compareWith]="compareFn" multiple>
                                <mat-option
                                    *ngFor="let charValue of nonConfSpecCharacteristics[i].productSpecCharacteristicValue"
                                    [value]="charValue.value">
                                    {{charValue.value.alias}}</mat-option>
                            </mat-select>
                        </mat-form-field>
                    </ng-template>

                    <ng-template #enumerable>
                        <mat-form-field>
                            <mat-label>Custom Value</mat-label>
                            <mat-select formControlName="value" [compareWith]="compareFn">
                                <mat-option
                                    *ngFor="let charValue of nonConfSpecCharacteristics[i].productSpecCharacteristicValue"
                                    [value]="charValue.value">
                                    {{charValue.value.alias}}</mat-option>
                            </mat-select>
                        </mat-form-field>

                    </ng-template>
                </div>
            </div>

        </div>
        
        
    </div>
+20 −38
Original line number Diff line number Diff line
@@ -44,10 +44,8 @@ export class EditOrdersProductSpecCharacteristicsComponent implements OnInit {
  productSpec: ProductSpecification
  
  confSpecFormArray = new UntypedFormArray([])
  nonConfSpecFormArray = new UntypedFormArray([])

  confSpecCharacteristics: ProductSpecificationCharacteristicRes[] = []
  nonConfSpecCharacteristics: ProductSpecificationCharacteristicRes[] = []

  ngOnInit() {  }

@@ -63,69 +61,53 @@ export class EditOrdersProductSpecCharacteristicsComponent implements OnInit {

  initValuesForm() {
    this.confSpecFormArray = new UntypedFormArray([])
    this.nonConfSpecFormArray = new UntypedFormArray([])

    const confSpecFA = this.confSpecFormArray as UntypedFormArray
    const nonConfSpecFA = this.nonConfSpecFormArray as UntypedFormArray

    this.confSpecCharacteristics = this.productSpec.productSpecCharacteristic.filter(specChar => {return specChar.configurable && this.orderItem.product.productCharacteristic.some( item => item.name === specChar.name) } )
    this.confSpecCharacteristics.sort(this.sortingService.ascStringSortingFunctionByNameProperty())
    
    if (this.isAdminUser) {
      this.nonConfSpecCharacteristics = this.productSpec.productSpecCharacteristic.filter(specChar => {return !specChar.configurable && this.orderItem.product.productCharacteristic.some( item => item.name === specChar.name) })
      this.nonConfSpecCharacteristics.sort(this.sortingService.ascStringSortingFunctionByNameProperty())
    }
    

    this.confSpecCharacteristics.forEach ( (confSpecChar) => {
      confSpecFA.push(this.updateFormArrayItem(confSpecChar, this.confSpecCharacteristics))
    })

    this.nonConfSpecCharacteristics.forEach((nonConfSpecChar) => {
      nonConfSpecFA.push(this.updateFormArrayItem(nonConfSpecChar, this.nonConfSpecCharacteristics))
    })    
    
  }

  updateFormArrayItem( specChar: ProductSpecificationCharacteristicRes, specCharList: ProductSpecificationCharacteristicRes[]): UntypedFormGroup {
      
    const orderedServiceCharacteristic = this.orderItem.product.productCharacteristic.find(char => char.name === specChar.name);
    const orderedServiceCharacteristic = this.orderItem.product.productCharacteristic.find(char => char.name === specChar.name)

    let charValueArray = orderedServiceCharacteristic ? orderedServiceCharacteristic.value : null;
    let charValueArray = orderedServiceCharacteristic.value
    
    if (['SET', 'ARRAY', 'ENUMERABLE'].includes(specChar.valueType)) {
      
      if (typeof charValueArray === 'string') {
        try {
          charValueArray = JSON.parse(charValueArray);
        } catch (e) {
          console.error('Error parsing JSON for characteristic:', specChar.name, e);
          charValueArray = []; 
        }
      }

      
      if (!Array.isArray(charValueArray)) {
        charValueArray = [];
      }
    if (['SET', 'ARRAY', 'ENUMERABLE'].includes(this.orderItem.product.productCharacteristic.find(char => char.name === specChar.name).valueType)) {
      charValueArray = JSON.parse(orderedServiceCharacteristic.value['value'] as unknown as string)
    }
  
    return new UntypedFormGroup({
      name: new UntypedFormControl(specChar.name),
      valueType: new UntypedFormControl(specChar.valueType),
      value: new UntypedFormControl(charValueArray)
    });
    })
  }

  addToArrayCharacteristicValue(characteristic: ProductSpecificationCharacteristicRes) {
    this.confSpecFormArray.value.concat(this.nonConfSpecFormArray.value).find(char => char.name === characteristic.name).value.push(
      {
    const charControl = this.confSpecFormArray.value.find(char => char.name === characteristic.name);
    if (charControl) {
      charControl.value.push({
        value: '',
        alias: ''
      });
    }
    )
  }

  deleteFromArrayCharacteristicValue(characteristic: ProductSpecificationCharacteristicRes, index) {
    this.confSpecFormArray.value.concat(this.nonConfSpecFormArray.value).find(char => char.name === characteristic.name).value.splice(index, 1)
    const charControl = this.confSpecFormArray.value.find(char => char.name === characteristic.name);
    if (charControl) {
      charControl.value.splice(index, 1);
    }
  }

  compareFn( optionOne, optionTwo ) : boolean {
@@ -140,7 +122,7 @@ export class EditOrdersProductSpecCharacteristicsComponent implements OnInit {
  submitDialog() {
    // console.log(this.confSpecFormArray.value)
    // console.log(this.nonConfSpecFormArray.value)
    const editedCharsFA = this.confSpecFormArray.value.concat(this.nonConfSpecFormArray.value)
    const editedCharsFA = this.confSpecFormArray.value;
    // console.log(editedCharsFA)

    let newServiceCharacteristics = []
+16 −17
Original line number Diff line number Diff line
@@ -48,7 +48,7 @@
                                            <div>
                                                Order Item #{{orderItemIndex+1}}
                                                <div>
                                                    <b [ngClass]="orderStateClassSelector(orderItem?.state)" class="ml-1" >{{orderItem.state}}</b>
                                                    <!-- <b [ngClass]="orderStateClassSelector(orderItem?.state)" class="ml-1" >{{orderItem.state}}</b> -->
                                                    <!-- <b class="ml-1 badge" *ngIf="orderItem.id === activeListItem">{{orderItem.state}}</b> -->
                                                </div>
                                            </div>
@@ -106,6 +106,16 @@
                                    role="tabpanel" [@fadeIn]>
                                    <div class="card mat-elevation-z1 bg-light">
                                        <div class="card-body">
                                            <div *ngIf="relatedServiceOrder" class="alert alert-info d-flex justify-content-between align-items-center mb-4" [@fadeIn]>
                                                <div>
                                                    <i class="fas fa-cogs mr-2"></i>
                                                    A related Service Order has been created.
                                                </div>
                                                <a [routerLink]="['/services/service_order', relatedServiceOrder.id]" class="btn btn-sm btn-light text-info font-weight-bold">
                                                    View Service Order #{{relatedServiceOrder.id}} 
                                                    <i class="fas fa-arrow-right ml-1"></i>
                                                </a>
                                            </div>
                                            <form [formGroup]="editForm">
                                                <div class="row justify-content-center">
                                                    <div class="col-lg-3">
@@ -334,11 +344,11 @@
                                                                <p>{{orderItem?.productOffering.name}}</p>
                                                            </div>
                                                            <div class="col-lg-4">
                                                                <h6>State</h6>
                                                                <!-- <h6>State</h6>
                                                                <div class="d-flex">
                                                                    <p [ngClass]="orderItemStateClassSelector(orderItem?.state)"
                                                                        style="font-size: .8rem;">{{orderItem?.state}}</p>
                                                                </div>
                                                                </div> -->
                                                            </div>
                                                            <div class="col-lg-4">
                                                                <h6>Product Type</h6>
@@ -427,7 +437,7 @@
                                                        </div>
                                                    </mat-expansion-panel>

                                                    <mat-expansion-panel expanded="true" class="no-shadow">
                                                    <!-- <mat-expansion-panel expanded="true" class="no-shadow">
                                                        <mat-expansion-panel-header>
                                                            <mat-panel-title>
                                                                Realizing Services
@@ -473,21 +483,10 @@
                                                                </div>
                                                            </a>
                                                        </div>
                                                    </mat-expansion-panel>

                                                        <!-- <mat-expansion-panel expanded="true" class="no-shadow">
                                                            <mat-expansion-panel-header>
                                                                <mat-panel-title>
                                                                    Service relationships overview
                                                                </mat-panel-title>
                                                            </mat-expansion-panel-header>
                                                            <div class="row">
                                                                <div class="col-md-12" [@fadeIn] *ngIf="currentItemRelationshipsUrl[orderItemIndex]">                                                  
                                                                    <img [src]="currentItemRelationshipsUrl[orderItemIndex]" alt="Relationship graph not available" class="img-fluid">
                                                                </div>                                                            
                                                            </div>
                                                    </mat-expansion-panel> -->

                                                        

                                                </mat-accordion>

                                            </div>
+76 −6
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import { relative } from 'path';
import { TerminateProductOrderItemsComponent } from './terminate-product-order-items/terminate-product-order-items.component';
import { EditProductOrderItemsComponent } from './edit-product-order-items/edit-product-order-items.component';
import { EditOrdersProductSpecCharacteristicsComponent } from './edit-product-order-items/edit-orders-product-spec-characteristics/edit-orders-product-spec-characteristics.component';
import { ServiceOrderService } from 'src/app/openApis/serviceOrderingManagement/services';

@Component({
  selector: 'app-preview-product-order',
@@ -42,7 +43,8 @@ export class PreviewProductOrderComponent implements OnInit {
    private authService: AuthService,
    private dialog: MatDialog,
    private sortingService: SortingService,
    public appService: AppService
    public appService: AppService,
    private serviceOrderService: ServiceOrderService
  ) { }

  staticListItems = ["Main Order Properties", "Related Parties"]
@@ -53,6 +55,8 @@ export class PreviewProductOrderComponent implements OnInit {
  
  availablePriorities = ['low', 'normal', 'high']

  relatedServiceOrder: any = null;


  productOrder: ProductOrder
  orderID: string
@@ -154,6 +158,10 @@ export class PreviewProductOrderComponent implements OnInit {
            this.activeListItem = this.activatedRoute.snapshot.queryParams.item
            
          }

          if (['ACKNOWLEDGED', 'INPROGRESS', 'COMPLETED', 'PARTIAL'].includes(this.productOrder.state)) {
            this.retrieveRelatedServiceOrder(this.productOrder.id);
          }
        } else {
          this.productOrderNotFound = true
        }
@@ -161,20 +169,82 @@ export class PreviewProductOrderComponent implements OnInit {
    )
  }

  retrieveRelatedServiceOrder(productOrderId: string) {
    const params: any = {
      'orderItem.service.serviceCharacteristic.value.value': productOrderId
    };

    this.serviceOrderService.listServiceOrder(params as any).subscribe(
      (orders: any[]) => {
        if (orders && orders.length > 0) {
          
          orders.sort((a, b) => {
            return new Date(b.orderDate).getTime() - new Date(a.orderDate).getTime();
          });

          this.findFirstValidOrder(orders, 0, productOrderId);

        } else {
          this.relatedServiceOrder = null;
        }
      },
      (error) => {
        console.warn("Could not retrieve related Service Order list", error);
        this.relatedServiceOrder = null;
      }
    );
  }

  findFirstValidOrder(candidates: any[], index: number, targetId: string) {
    if (index >= candidates.length) {
      this.relatedServiceOrder = null;
      return;
    }

    const candidateId = candidates[index].id;

    this.serviceOrderService.retrieveServiceOrder({ id: candidateId }).subscribe(
      (fullOrder: any) => {
        
        const isMatch = fullOrder.orderItem?.some(item => 
          item.service?.serviceCharacteristic?.some(char => 
            char.name === '_PRODUCT_ORDER_ID_' && char.value?.value === targetId
          )
        );

        if (isMatch) {
          this.relatedServiceOrder = fullOrder;
        } else {
          this.findFirstValidOrder(candidates, index + 1, targetId);
        }
      },
      (error) => {
        console.warn(`Failed to fetch details for candidate ${candidateId}`, error);
        this.findFirstValidOrder(candidates, index + 1, targetId);
      }
    );
  }

  retrieveProductInventory(serviceId:string) {
    return this.inventoryService.retrieveService({id:serviceId})
  }

  orderItemStateClassSelector(state:'feasibilityChecked' | 'designed' | 'reserved' | 'inactive' | 'active' | 'terminated') {
  orderItemStateClassSelector(state:'INITIAL' | 'ACKNOWLEDGED' | 'REJECTED' | 'PENDING' | 'HELD' | 'INPROGRESS' | 'CANCELLED' | 'COMPLETED' | 'FAILED' | 'ASSESSINGCANCELLATION' | 'PENDINGCANCELLATION') {
    let cssClass: string = 'badge'
    switch (state) {
      case 'active':
      case 'INITIAL':
        cssClass += ' badge-primary'
        break;
      case 'COMPLETED':
        cssClass += ' badge-success'
        break;
      case 'inactive':
      case 'PENDING':
      case 'HELD':
        cssClass += ' badge-secondary'
        break;
      case 'terminated':
      case 'CANCELLED':
      case 'FAILED':
      case 'REJECTED':
        cssClass += ' badge-danger'
        break;
      default:
@@ -339,7 +409,7 @@ export class PreviewProductOrderComponent implements OnInit {
            productOrderItem: []
          }
          this.selection.selected.forEach( selectedOrderItem => {
            this.productOrder.productOrderItem.find(item => item.id === selectedOrderItem.id).action = "MODIFY"
            this.productOrder.productOrderItem.find(item => item.id === selectedOrderItem.id).action = "DELETE"
            // this.productOrder.productOrderItem.find(item => item.id === selectedOrderItem.id).service.state = "TERMINATED"
          })

+1 −1
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@
<div mat-dialog-content>
    Are you sure you want to terminate services allocated with the selected Order Items?
    <ul class="mt-2">
        <li *ngFor="let orderItem of data"><dfn>{{orderItem.productOffering.productSpecification.name}}</dfn></li>
        <li *ngFor="let orderItem of data"><dfn>{{orderItem.productOffering.name}}</dfn></li>
    </ul>
</div>

Loading