Creación de los servicios de reserva y actualización de Order Hub para utilizar los nuevos archivos

Aprenda a crear los servicios create-reservation y reservation-action y a actualizar Order Hub para utilizar los nuevos archivos. En esta lección, realiza varios cambios en los archivos, incluyendo la copia de los cambios de archivo exportados desde IBM Carbon UI Builder.

Procedimiento

Cree el servicio y actualice los archivos de Order Hub para utilizar los nuevos archivos.

Crear un servicio para llamar a la API Create reservation desde Sterling™ Intelligent Promising Inventory Visibility para crear reservas.

  1. Vaya a src-custom/app/features/create-reservation y cree una carpeta denominada services.
  2. Cree un servicio en src-custom/app/features/create-reservation/services.
  3. Ejecute el mandato siguiente:
    ng g s create-reservation

    Esto creará un nuevo servicio en la carpeta services . Este servicio se puede utilizar para añadir llamadas de API.

  4. Copie el contenido siguiente en el archivo create-reservation.service.ts :
    import { Injectable } from '@angular/core';
    import { BucCommBEHttpWrapperService } from '@buc/svc-angular';
    import { Observable, throwError } from 'rxjs';
    
    @Injectable({
      providedIn: 'root'
    })
    export class CreateReservationService {
      private resourceDomain: string = 'inventory';
      private options: any;
      private domain: any;
      public reservationRef: any;
      public itemData: any
    
      constructor(private http: BucCommBEHttpWrapperService) {
        this.domain = BucCommBEHttpWrapperService.getPathPrefix(this.resourceDomain);
        this.options = BucCommBEHttpWrapperService.getRequestOptions(this.resourceDomain);
      }
    
      createReservation(tenantId, input): Observable<any> {
        if (tenantId === undefined || tenantId === null || tenantId === '') {
          return throwError(new Error('Missing required  parameter: tenantId'));
        }
    
        let path = '/{tenant}/v1/reservations';
        path = path.replace('{tenant}', tenantId);
        const url = this.domain + path;
        const obsToReturn$ = this.http.post(url, this.resourceDomain, null, input, this.options);
        return obsToReturn$;
      }
    
      getReservation(tenantId, referenceId): Observable<any> {
        if (tenantId === undefined || tenantId === null || tenantId === '') {
          return throwError(new Error('Missing required  parameter: tenantId'));
        }
        let path = '/{tenant}/v1/reservations?reference={referenceId}';
        path = path.replace('{tenant}', tenantId).replace('{referenceId}', referenceId);
        const url = this.domain + path;
        const obsToReturn$ = this.http.get(url, this.resourceDomain, null, this.options);
        return obsToReturn$;
      }
    
    }
    

Crear un servicio de acciones de reserva.

  1. Cree otro servicio en la misma carpeta services .
  2. Ejecute el mandato siguiente:
    ng g s reservation-action

    Esto creará un nuevo servicio en la carpeta services . Este servicio se puede utilizar para añadir todas las acciones del menú de desbordamiento.

  3. Copie el contenido siguiente en el archivo reservation-action.service.ts :
    import { Injectable } from '@angular/core';
    import { Router } from '@angular/router';
    import { BucNotificationService, ActionProcessorService } from '@buc/common-components';
    import { TranslateService } from '@ngx-translate/core';
    import { CustomConstants } from '../custom-constants';
    import { map } from 'rxjs/operators';
    import { ActionParams } from '@buc/inventory-shared/lib/actions/paramtypes';
    import { CreateReservationService } from './create-reservation.service';
    
    @Injectable({
      providedIn: 'root'
    })
    export class ReservationActionService {
    
      constructor(    
        public actionSvc: ActionProcessorService,
        public translate: TranslateService,
        public bucNotificationService: BucNotificationService,
        public router: Router,
        public createReservationSvc: CreateReservationService) { 
          actionSvc.select<ActionParams>(CustomConstants.ACTION_IDS_CREATE_RESERVATION).pipe(
            map(res => {
              this.executeActionDetails(res.params);
            })
          ).subscribe();
      }
    
      async executeActionDetails(params: ActionParams) {
        this.createReservationSvc.itemData = params.data?.item;
      }
    }
    

Añada el servicio de acción de reserva al código de Order Hub:

  1. Abra el archivo src-custom/app/app-customization.impl.ts para editarlo.
  2. Actualice la matriz de importaciones para incluir módulos para añadir el servicio reservation-action :
               BucActionsModule.forChild(
                [ 
                  {
                  name: CustomConstants.ACTION_IDS_CREATE_RESERVATION,
                  action: ReservationActionService
                }
                ]
              )
  3. Como resultado, la matriz de importaciones debe tener el código siguiente:
        static readonly imports = [
            RouterModule.forChild(customRoutes),
               BucCommonComponentsModule,
               BucFeatureComponentsModule,
               BucIconsModule,
               SharedModule,
               BucActionsModule.forChild(
                [ 
                  {
                  name: CustomConstants.ACTION_IDS_CREATE_RESERVATION,
                  action: ReservationActionService
                }
                ]
              )
      ];
  4. Actualice la importación con el código siguiente:
    import { CustomConstants } from './features/create-reservation/custom-constants';
    import { ReservationActionService } from './features/create-reservation/services/reservation-action.service';
    import { BucActionsModule } from '@buc/common-components';

Añadir una acción nueva para la reserva de creación:

  1. Abra el archivo src-custom/app/features/search/inventory-table/inventory-table.component.ts para editarlo.
  2. Añada la importación siguiente:
    import { CustomConstants } from '../../create-reservation/custom-constants';
  3. Añada el método siguiente al final:
        private _setCreateReservation(itemData) {
          this.actionService.dispatch<ActionParams>(
            CustomConstants.ACTION_IDS_CREATE_RESERVATION,
            {
              searchCriteria: this.searchCriteria,
              data: itemData,
              pageNumber: 1,
              initialLoad: true,
              dataMap: [itemData],
              ctxSvc: this.ctxSvc,
            }
          );
        }
  4. En el método onOverflowMenuClick , añada la siguiente constante en la matriz de elementos:
    CustomConstants.ACTION_CREATE_RESERVATION
  5. Como resultado, el método onOverflowMenuClick debe parecerse al código siguiente:
      onOverflowMenuClick(item: any) {
        this.itemData = item.key;
        this.overflowMenuId = item.key.itemDescriptiveKey;
        const items = [
          Constants.ACTION_SET_SAFETY_STOCKS,
          Constants.ACTION_SET_FULFILLMENT_OPTIONS,
          Constants.ACTION_TRANSFER_INVENTORY,
          Constants.ACTION_ADJUST_INVENTORY,
          CustomConstants.ACTION_CREATE_RESERVATION
        ];
        if (item.key.type.bundle) {
          this.removeOverflowMenuActions(items);
        } else {
          this._setOverflowMenu(item.key.type.modelItem);
    
        }
      }
  6. En el método onOverflowMenuActionSelected , añada un caso nuevo:
        case CustomConstants.ACTION_CREATE_RESERVATION:
          this._setCreateReservation({ item: this.itemData });
          break;
  7. Como resultado, el método onOverflowMenuActionSelected debe parecerse al código siguiente:
      protected onOverflowMenuActionSelected(id: string) {
        switch (id) {
        case Constants.ACTION_IDS_VIEW_DETAILS:
          this._details({ item: this.itemData });
          break;
        case Constants.ACTION_SET_SAFETY_STOCKS:
          this._setSafetyStockMultiple();
          break;
        case Constants.ACTION_SET_FULFILLMENT_OPTIONS:
          this._setFulfillmentOptionsMultiple();
          break;
        case Constants.ACTION_TRANSFER_INVENTORY:
          this._moveInventory({ data: { itemData: this.itemData } });
          break;
        case Constants.ACTION_ADJUST_INVENTORY:
          this._setAdjustInventoryMultiple();
          break;
        case CustomConstants.ACTION_CREATE_RESERVATION:
          this._setCreateReservation({ item: this.itemData });
          break;
          
        }
       
      }
  8. En el método _setOverflowMenu , añada un nuevo ID de acción en la matriz actionIds :
    CustomConstants.ACTION_CREATE_RESERVATION
  9. Como resultado, el método _setOverflowMenu debe parecerse al código siguiente:
      private _setOverflowMenu(modelItemSelected = false) {
        this.getActionResourceIds();
    
        let actionIds = [];
        if (this.searchCriteria.filterCriteria.locationType !== Constants.VALUE_CONSIDERALLNODES) {
          actionIds = [
            Constants.ACTION_IDS_VIEW_DETAILS,
            Constants.ACTION_SET_SAFETY_STOCKS,
            Constants.ACTION_SET_FULFILLMENT_OPTIONS,
            Constants.ACTION_TRANSFER_INVENTORY,
            CustomConstants.ACTION_CREATE_RESERVATION
          ];
          if (!modelItemSelected) {
            actionIds.splice(1, 0, Constants.ACTION_ADJUST_INVENTORY);
          }
          if (this.isSafetyStockRuleEnabled) {
            const index = actionIds.indexOf(Constants.ACTION_SET_SAFETY_STOCKS);
            if (index !== -1) {
              actionIds.splice(index, 1);
            }
          }
        } else {
          actionIds = [Constants.ACTION_IDS_VIEW_DETAILS];
        }
        const tableConfiguration = this.getTableConfiguration();
        tableConfiguration.setActiveOverflowMenuActions(actionIds);
        this.setOverflowMenuResourceIds(this.actionResourceIds, actionIds);
        this.overflowMenu = tableConfiguration.getOverflowMenuActions();
      }
Copiar archivos de IBM Carbon UI Builder:
Nota: Puede haber diferencias menores entre el HTML de ejemplo proporcionado en esta guía de aprendizaje y el HTML que exporta desde IBM Carbon UI Builder. Esto se espera porque IBM Carbon UI Builder es una herramienta en línea que se actualiza regularmente.
  1. Vaya a src-custom/app/features/create-reservation y cree una carpeta denominada components.
  2. Cree los archivos siguientes dentro de la carpeta components :
    • create-reservation-form.component.ts
    • create-reservation-form.component.html
    • create-reservation-form.component.scss
    • create-reservation-form.module.ts
  3. Abra el formulario en IBM Carbon UI Builder y pulse Exportar. Asegúrese de que la pestaña Angular esté seleccionada.
  4. Copie el contenido de src/app/components/create-reservation-form/create-reservation-form.component.ts del código IBM Carbon UI Builder en el archivo create-reservation-form.component.ts recién creado.
    Botón Copiar
  5. Abra el archivo create-reservation-form.component.html recién creado para editarlo.
  6. Añada el siguiente código:
    <form [formGroup]="createReservationForm">
    </form>
  7. Después de la primera línea del código recién añadido, copie el contenido de src/app/components/create-reservation-form/create-reservation-form.component.html del código de IBM Carbon UI Builder en el archivo.
    Botón Copiar

    Puesto que se utiliza el módulo de formularios reactivos, se necesita un formGroup para el envío de formularios y se necesita formControlName para cada campo.

    Por tanto:
    1. Añada los siguientes formControlName para cada campo: formControlName = reference para los campos de entrada reference .
      Después de añadir formControlName , debería parecerse al siguiente fragmento de código:
      <input ibmText name="reference" formControlName="reference" placeholder=""
      />
    2. De forma similar, se necesita un formControlName para todos y cada uno de los campos del formulario.

      Sustituya todos los parámetros (event) del archivo por ($event).

      De este modo se resuelven los errores siguientes: Property 'value' does not exist on type EventTarget in TypeScript.

    3. Cambie el suceso (selected) del nodo de envío y el grupo de distribución como se indica a continuación en cada uno de sus fragmentos de código ibm-dropdown :
      En el desplegable del nodo de envío, indicado por el fragmento de código ibm-dropdown con formControlName="shippingNode", cambie el suceso (selected) por:
      (selected)="onSelectShippingNode($event)"
      En el desplegable del grupo de distribución, indicado por el fragmento de código ibm-dropdown con formControlName="dg", cambie el suceso (selected) por:
      (selected)="onSelectDistributionGroup($event)"

      Estos métodos son necesarios para capturar sucesos cuando se selecciona el nodo de envío o el desplegable de grupo de distribución.

      Por ejemplo:
      actualizaciones de ibm-dropdown
    Después de añadir todos los valores de control, el archivo create-reservation-form.component.html se parece al código siguiente:
    <form [formGroup]="createReservationForm">
        <ibm-accordion [align]="accordion165433494446278754849833236715917Align">
            <ibm-accordion-item
                [title]="accordionItem36327672493936585592059716298563Title"
                (selected)="accordionItem36327672493936585592059716298563Selected.emit($event)"
            >
                <div ibmGrid>
                    <div ibmRow>
                        <div ibmCol>
                            <ibm-label helperText="">
                                Reference
                                <input ibmText name="reference" formControlName="reference" placeholder="" />
                            </ibm-label>
                        </div>
                        <div ibmCol>
                            <ibm-label helperText="">
                                Segment type
                                <input ibmText name="segmentType"formControlName="segmentType" placeholder="" />
                            </ibm-label>
                        </div>
                    </div>
                    <div ibmRow class="margin-top">
                        <div ibmCol>
                            <ibm-label helperText="">
                                Time to expire
                                <input ibmText name="timeToExpire" formControlName="timeToExpire"  placeholder="" />
                            </ibm-label>
                        </div>
                        <div ibmCol>
                            <ibm-dropdown
                                [label]="demandTypeLabel"
                                [helperText]="demandTypeHelperText"
                                [placeholder]="demandTypePlaceholder"
                                [theme]="demandTypeTheme"
                                [invalid]="demandTypeInvalid"
                                [invalidText]="demandTypeInvalidText"
                                [size]="demandTypeSize"
                                [warn]="demandTypeWarn"
                                [warnText]="demandTypeWarnText"
                                [disabled]="demandTypeDisabled"
                                [dropUp]="demandTypeDropUp"
                                [selectionFeedback]="demandTypeSelectionFeedback"
                                [type]="demandTypeType"
                                (selected)="demandTypeSelected.emit($event)"
                                (close)="demandTypeClose.emit($event)"
                                formControlName="demandType"
                            >
                                <ibm-dropdown-list [items]="demandTypeItems"></ibm-dropdown-list>
                            </ibm-dropdown>
                        </div>
                    </div>
                    <div ibmRow class="margin-top">
                        <div ibmCol>
                            <ibm-label helperText="">
                                Segment
                                <input ibmText name="segment" formControlName="segment" placeholder="" />
                            </ibm-label>
                        </div>
                        <div ibmCol>
                            <ibm-checkbox
                                name="considerSafetyStock"
                                id="considerSafetyStock"
                                [(checked)]="considerSafetyStockChecked"
                                (checkedChange)="considerSafetyStockCheckedChange.emit($event)"
                                class="checkbox-margin"
                                formControlName="considerSafetyStock"
                            >
                                Consider safety stock
                            </ibm-checkbox>
                        </div>
                    </div>
                    <div ibmRow class="margin-top">
                        <div ibmCol>
                            <ibm-label helperText="">
                                Line Id
                                <input ibmText name="lineId" formControlName="lineId" placeholder="" />
                            </ibm-label>
                        </div>
                        <div ibmCol>
                            <ibm-label helperText="">
                                Item Id
                                <input ibmText name="itemId" formControlName="itemId" placeholder="" />
                            </ibm-label>
                        </div>
                        <div ibmCol>
                            <ibm-label helperText="">
                                Unit of measure
                                <input ibmText name="unitOfMeasure" formControlName="unitOfMeasure" placeholder="" />
                            </ibm-label>
                        </div>
                        <div ibmCol>
                            <ibm-label helperText="">
                                Product class
                                <input ibmText name="productClass" formControlName="productClass"  placeholder="" />
                            </ibm-label>
                        </div>
                    </div>
                    <div ibmRow class="margin-top">
                        <div ibmCol>
                            <ibm-label helperText="">
                                Delivery method
                                <input ibmText name="deliveryMethod" formControlName="deliveryMethod" placeholder="" />
                            </ibm-label>
                        </div>
                        <div ibmCol>
                            <ibm-number
                                [helperText]="quantityHelperText"
                                name="quantity"
                                [value]="quantityValue"
                                (change)="quantityValueChange.emit($event.value)"
                                [label]="quantityLabel"
                                [theme]="quantityTheme"
                                [min]="quantityMin"
                                [max]="quantityMax"
                                [step]="quantityStep"
                                [invalid]="quantityInvalid"
                                [invalidText]="quantityInvalidText"
                                [warn]="quantityWarn"
                                [warnText]="quantityWarnText"
                                [size]="quantitySize"
                                [disabled]="quantityDisabled"
                                formControlName="quantity"
                            >
                            </ibm-number>
                        </div>
                        <div ibmCol>
                            <ibm-label helperText="">
                                Segment
                                <input ibmText name="lineSegment" formControlName="lineSegment" placeholder="" />
                            </ibm-label>
                        </div>
                        <div ibmCol>
                            <ibm-label helperText="">
                                Segment Type
                                <input ibmText name="lineSegmentType" formControlName="lineSegmentType" placeholder="" />
                            </ibm-label>
                        </div>
                    </div>
                    <div ibmRow class="margin-top">
                        <div ibmCol>
                            <ibm-dropdown
                                [label]="shippingNodeLabel"
                                [helperText]="shippingNodeHelperText"
                                [placeholder]="shippingNodePlaceholder"
                                [theme]="shippingNodeTheme"
                                [invalid]="shippingNodeInvalid"
                                [invalidText]="shippingNodeInvalidText"
                                [size]="shippingNodeSize"
                                [warn]="shippingNodeWarn"
                                [warnText]="shippingNodeWarnText"
                                [disabled]="shippingNodeDisabled"
                                [dropUp]="shippingNodeDropUp"
                                [selectionFeedback]="shippingNodeSelectionFeedback"
                                [type]="shippingNodeType"
                                (selected)="onSelectShippingNode($event)"
                                (close)="shippingNodeClose.emit($event)"
                                formControlName="shippingNode"
                            >
                                <ibm-dropdown-list [items]="shippingNodeItems"></ibm-dropdown-list>
                            </ibm-dropdown>
                        </div>
                        <div ibmCol>
                            <ibm-dropdown
                                [label]="dgLabel"
                                [helperText]="dgHelperText"
                                [placeholder]="dgPlaceholder"
                                [theme]="dgTheme"
                                [invalid]="dgInvalid"
                                [invalidText]="dgInvalidText"
                                [size]="dgSize"
                                [warn]="dgWarn"
                                [warnText]="dgWarnText"
                                [disabled]="dgDisabled"
                                [dropUp]="dgDropUp"
                                [selectionFeedback]="dgSelectionFeedback"
                                [type]="dgType"
                                (selected)="onSelectDistributionGroup($event)"
                                (close)="dgClose.emit($event)"
                                formControlName="dg"
                            >
                                <ibm-dropdown-list [items]="dgItems"></ibm-dropdown-list>
                            </ibm-dropdown>
                        </div>
                    </div>
                    <div ibmRow class="margin-top">
                        <div ibmCol>
                            <button
                                ibmButton="secondary"
                                (click)="button3886839157349837322918347909375902Clicked.emit()"
                            >
                                Cancel
                            </button>
                            <button
                                ibmButton="primary"
                                (click)="onSave()"
                                class="create-btn-margin"
                            >
                                Create
                            </button>
                        </div>
                    </div>
                </div>
            </ibm-accordion-item>
        </ibm-accordion>
        
        
    </form>
    Los valores de acordeón y los valores de botón serán diferentes del diseño que se ha desarrollado. Al copiar el código anterior:
    1. Añada las propiedades de acordeón [align] y [title] según las observaciones del código al exportar el fragmento.
    2. Asegúrese de que la propiedad del botón Crear y Suprimir (pulsar) sea la misma que el diseño del fragmento.
  8. Copie el contenido de src/app/components/create-reservation-form/create-reservation-form.module.ts del código de IBM Carbon UI Builder en el archivo create-reservation-form.module.ts recién creado.
    Botón Copiar

    Aparte del módulo anterior, también son necesarios algunos módulos angulares: FormsModule y ReactiveFormsModule.

    El archivo debe contener el código siguiente:
    import { NgModule } from '@angular/core';
    import { FormsModule, ReactiveFormsModule } from '@angular/forms';
    
    import {
        AccordionModule,
        GridModule,
        InputModule,
        DropdownModule,
        CheckboxModule,
        NumberModule,
        ComboBoxModule,
        ButtonModule
    } from 'carbon-components-angular';
    import { CreateReservationForm } from './create-reservation-form.component';
    @NgModule({
        imports: [
            AccordionModule, GridModule, InputModule, DropdownModule, CheckboxModule, NumberModule, ComboBoxModule, ButtonModule, FormsModule, ReactiveFormsModule
        ],
        declarations: [CreateReservationForm],
        exports: [CreateReservationForm]
    })
    export class CreateReservationFormModule { }
  9. Copie el contenido de src/app/components/create-reservation-form/create-reservation-form.component.scss del código de IBM Carbon UI Builder en el archivo create-reservation-form.component.scss recién creado.
    Botón Copiar
  10. Abra el archivo create-reservation-form.component.ts recién creado para editarlo.
    1. Cambie el nombre del selector por 'buc-create-reservation-form'.
      @Component({
      	selector: "buc-create-reservation-form",
      	templateUrl: "./create-reservation-form.component.html",
      	styleUrls: ["./create-reservation-form.component.scss"]
      })
    2. Implemente la interfaz OnInit en este componente. Añada implements OnInit después del nombre de clase.
      @Component({
      	selector: "buc-create-reservation-form",
      	templateUrl: "./create-reservation-form.component.html",
      	styleUrls: ["./create-reservation-form.component.scss"]
      })
      export class CreateReservationForm implements OnInit{

      A continuación, algunos de los campos deberán actualizarse para que se puedan utilizar:

    3. Cambie @Input() quantityValue = 50; por @Input() quantityValue = 1;
    4. Añada nuevas variables y métodos añadiendo nuevas variables después de todas las declaraciones de variables:
      // new variables
      public validDemandTypes;
      orgCode: string;
      dgMap: any = {};
      public tenantId;
      public isCancelled: boolean;
      createReservationForm: FormGroup;
      private nlsMap: any = {
      	'custom.LABEL_CREATE_RESERVATION': '',
      	'custom.LABEL_RESERVATION_EXPIRY': '',
      	'custom.ERROR_INVALID_EXPIRY': '',
      	'custom.ERROR_RESERVATION': '',
      	'custom.SUCCESS_RESERVATION': ''
      };
      constructor(
      	private locCommonSvc: LocalCommonService,
      	public demandService: InventoryDemandService,
      	private inventoryShipNodesService: InventoryShipNodesService,
      	private dgSvc: InventoryDistributionService,
      	private reservationService: CreateReservationService,
      	private bucNotificationService: BucNotificationService,
      	private router: Router,
      	private translateSvc: TranslateService
      ) {}
      ngOnInit(): void {
      	this.createReservationForm = new FormGroup({
      		reference: new FormControl(),
      		timeToExpire: new FormControl(),
      		demandType: new FormControl([]),
      		segment: new FormControl(),
      		segmentType: new FormControl(),
      		considerSafetyStock: new FormControl(),
      		lineId: new FormControl(),
      		itemId: new FormControl(),
      		unitOfMeasure: new FormControl(),
      		productClass: new FormControl(),
      		deliveryMethod: new FormControl(),
      		quantity: new FormControl(),
      		lineSegment: new FormControl(),
      		lineSegmentType: new FormControl(),
      		shippingNode: new FormControl(),
      		dg: new FormControl()
      	});
      	this.initialize();
      	this.tenantId =
      		BucSvcAngularStaticAppInfoFacadeUtil.getInventoryTenantId();
      	this._initTranslations();
      }
      /** Fetch translations for the page */
      private async _initTranslations() {
      	const keys = Object.keys(this.nlsMap);
      	const json = await this.translateSvc.get(keys).toPromise();
      	keys.forEach(k => this.nlsMap[k] = json[k]);
      }
      async initialize(clearForm = false) {
      	await this.loadDemandTypes();
      	await this.getShipNodes();
      	await this.loadDG();
      }
      // loading demand types
      async loadDemandTypes() {
      	try {
      		this.validDemandTypes = await getValidDemandTypes(this.demandService);
      		const data = this.validDemandTypes.map(sup => ({
      			content: sup,
      			selected: false,
      			id: sup
      		}));
      		this.mapDemandTypes();
      	} catch (e) {
      		this.locCommonSvc.showErrorNotification('error', e.message);
      	}
      }
      mapDemandTypes() {
      	this.demandTypeItems = this.validDemandTypes.map(item => {
      		return {
      			content: item
      		};
      	});
      }
      // loading ship nodes
      private async getShipNodes() {
      	if (!this.shippingNodeItems || this.shippingNodeItems.length === 0) {
      		const response = await
      		this.inventoryShipNodesService.getIVShipNodesByTenantID().toPromise();
      		let shippingNodes = [];
      		if (response && response.length) {
      			shippingNodes = response.map(item => item.shipNode);
      			this.shippingNodeItems = shippingNodes.map(item => {
      				return {
      					content: item
      				};
      			});
      		}
      	}
      }
      // loading DG
      async loadDG() {
      	try {
      		const resp = await
      		this.dgSvc.getDistributionRuleListByPage(this.orgCode, 1, 999, '').toPromise();
      		const list = resp.distributionGroups
      			.filter(dg => (!dg.dgType || dg.dgType === 'PROD') &&
      				(!dg.dgPurpose || dg.dgPurpose === 'SOURCING'))
      			.map(dg => {
      				const id = dg.dgId || dg.dgKey;
      				this.dgMap[id] = dg;
      				return {
      					id,
      					content: dg.dgName,
      					selected: false,
      					value: id
      				};
      			})
      			.sort((a, b) =>
      				a.content.toLocaleLowerCase().localeCompare(b.content.toLocaleLowerCase()));
      		this.dgItems = list;
      	} catch (e) {
      		this.locCommonSvc.showErrorNotification('error', e.message);
      	}
      }
      async onSave() {
      	let shipNodeValue = '';
      	if (this.createReservationForm.value.shippingNode &&
      		this.createReservationForm.value.shippingNode.length) {
      		shipNodeValue = this.createReservationForm.value.shippingNode.find(st =>
      			st.selected).content;
      	}
      	let dgValue = '';
      	if (this.createReservationForm.value.dg &&
      		this.createReservationForm.value.dg.length) {
      		dgValue = this.createReservationForm.value.dg.find(st =>
      			st.selected).content;
      	}
      	let demandTypeValue = '';
      	if (this.createReservationForm.value.dg &&
      		this.createReservationForm.value.demandType.length) {
      		demandTypeValue = this.createReservationForm.value.demandType.content;
      	}
      	const request = {
      		reference: this.createReservationForm.value.reference,
      		timeToExpire: this.createReservationForm.value.timeToExpire,
      		segment: this.createReservationForm.value.segment,
      		segmentType: this.createReservationForm.value.segmentType,
      		demandType: this.createReservationForm.value.demandType.content,
      		considerSafetyStock: this.createReservationForm.value.considerSafetyStock ?
      			this.createReservationForm.value.considerSafetyStock : false,
      		lines: [{
      			lineId: this.createReservationForm.value.lineId,
      			itemId: this.createReservationForm.value.itemId,
      			unitOfMeasure: this.createReservationForm.value.unitOfMeasure,
      			productClass: this.createReservationForm.value.productClass,
      			deliveryMethod: this.createReservationForm.value.deliveryMethod,
      			shipNode: shipNodeValue,
      			distributionGroup: dgValue,
      			segment: this.createReservationForm.value.lineSegment,
      			segmentType: this.createReservationForm.value.lineSegmentType,
      			quantity: this.createReservationForm.value.quantity
      		}]
      	};
      	// Call reservation API here
      	try {
      		await this.reservationService.createReservation(this.tenantId,
      			request).toPromise();
      		this.showNotification('success',
      			this.nlsMap['custom.SUCCESS_RESERVATION']);
      	} catch (error) {
      		this.showNotification('error', this.nlsMap['custom.ERROR_RESERVATION'] +
      			' ' + error.error_message);
      	}
      }
      // notification
      showNotification(statusType, message) {
      	const notification = new BucNotificationModel({
      		statusType,
      		statusContent: message
      	});
      	this.bucNotificationService.send([notification]);
      }
      onCancel() {
      	this.isCancelled = true;
      	this.router.navigate([Constants.RESULTS_ROUTE]);
      }
    5. Actualice la sección de importación con las líneas siguientes:
      import { Component, Input, Output, EventEmitter, OnInit } from "@angular/core";
      import { FormControl, FormGroup } from "@angular/forms";
      import { ActivatedRoute, Router } from "@angular/router";
      import { BucNotificationModel, BucNotificationService } from "@buc/common-components";
      import { InventoryDemandService, InventoryDistributionService,
          CommonService as LocalCommonService, 
          getValidDemandTypes,
          Constants , InventoryShipNodesService} from "@buc/inventory-shared";
      import { TranslateService } from "@ngx-translate/core";
      import { BucSvcAngularStaticAppInfoFacadeUtil } from '@buc/svc-angular';
      import { CreateReservationService } from "../services/create-reservation.service";
    6. Como resultado, el archivo create-reservation-form.component.ts debe parecerse al archivo siguiente:
      import { Component, Input, Output, EventEmitter, OnInit } from "@angular/core";
      import { FormControl, FormGroup } from "@angular/forms";
      import { ActivatedRoute, Router } from "@angular/router";
      import { BucNotificationModel, BucNotificationService } from "@buc/common-components";
      import { InventoryDemandService, InventoryDistributionService,
          CommonService as LocalCommonService, 
          getValidDemandTypes,
          Constants , InventoryShipNodesService} from "@buc/inventory-shared";
      import { TranslateService } from "@ngx-translate/core";
      import { BucSvcAngularStaticAppInfoFacadeUtil } from '@buc/svc-angular';
      import { CreateReservationService } from "../services/create-reservation.service";
      
      @Component({
      	selector: "buc-create-reservation-form",
      	templateUrl: "./create-reservation-form.component.html",
      	styleUrls: ["./create-reservation-form.component.scss"]
      })
      export class CreateReservationForm implements OnInit{
      	@Input() accordion165433494446278754849833236715917Align = "end";
      	@Input() accordionItem36327672493936585592059716298563Title =
      		"Create reservation";
      
      	@Input() demandTypeLabel = "Demand type";
      	@Input() demandTypeHelperText = "";
      	@Input() demandTypePlaceholder = "";
      	@Input() demandTypeTheme = "dark";
      	@Input() demandTypeInvalid = false;
      	@Input() demandTypeInvalidText = "";
      	@Input() demandTypeSize = "md";
      	@Input() demandTypeWarn = false;
      	@Input() demandTypeWarnText = "";
      	@Input() demandTypeDisabled = false;
      	@Input() demandTypeDropUp = false;
      	@Input() demandTypeSelectionFeedback = "top-after-reopen";
      	@Input() demandTypeType: "single" | "multi" = "single";
      	@Input() demandTypeItems = [];
      
      	@Input() considerSafetyStockChecked = false;
      
      	@Input() quantityHelperText = "";
      	@Input() quantityValue = 1;
      	@Input() quantityLabel = "Quantity";
      	@Input() quantityTheme = "";
      	@Input() quantityMin = 0;
      	@Input() quantityMax = 100;
      	@Input() quantityStep = 1;
      	@Input() quantityInvalid = false;
      	@Input() quantityInvalidText = undefined;
      	@Input() quantityWarn = undefined;
      	@Input() quantityWarnText = undefined;
      	@Input() quantitySize = "md";
      	@Input() quantityDisabled = undefined;
      
      	@Input() shippingNodeLabel = "Shipping node";
      	@Input() shippingNodeHelperText = "";
      	@Input() shippingNodePlaceholder = "";
      	@Input() shippingNodeTheme = "dark";
      	@Input() shippingNodeInvalid = false;
      	@Input() shippingNodeInvalidText = "";
      	@Input() shippingNodeSize = "md";
      	@Input() shippingNodeWarn = false;
      	@Input() shippingNodeWarnText = "";
      	@Input() shippingNodeDisabled = false;
      	@Input() shippingNodeDropUp = false;
      	@Input() shippingNodeSelectionFeedback = "top-after-reopen";
      	@Input() shippingNodeType: "single" | "multi" = "single";
      	@Input() shippingNodeItems = [];
      
      	@Input() dgLabel = "Distribution group";
      	@Input() dgHelperText = "";
      	@Input() dgPlaceholder = "";
      	@Input() dgTheme = "dark";
      	@Input() dgInvalid = false;
      	@Input() dgInvalidText = "";
      	@Input() dgSize = "md";
      	@Input() dgWarn = false;
      	@Input() dgWarnText = "";
      	@Input() dgDisabled = false;
      	@Input() dgDropUp = false;
      	@Input() dgSelectionFeedback = "top-after-reopen";
      	@Input() dgType: "single" | "multi" = "single";
      	@Input() dgItems = [];
      
      	@Output() accordionItem36327672493936585592059716298563Selected =
      		new EventEmitter();
      
      	@Output() demandTypeSelected = new EventEmitter<any>();
      	@Output() demandTypeClose = new EventEmitter<any>();
      
      	@Output() considerSafetyStockCheckedChange = new EventEmitter<boolean>();
      
      	@Output() quantityValueChange = new EventEmitter<number>();
      	@Output() quantityChange = new EventEmitter<any>();
      
      	@Output() shippingNodeSelected = new EventEmitter<any>();
      	@Output() shippingNodeClose = new EventEmitter<any>();
      
      	@Output() dgSelected = new EventEmitter<any>();
      	@Output() dgClose = new EventEmitter<any>();
      
      	@Output() button3886839157349837322918347909375902Clicked =
      		new EventEmitter();
      
      	@Output() creatClicked = new EventEmitter();
      
       // new variables
      public validDemandTypes;
      orgCode: string;
      dgMap: any = {};
      public tenantId;
      public isCancelled: boolean;
      createReservationForm: FormGroup;
      private nlsMap: any = {
      	'custom.LABEL_CREATE_RESERVATION': '',
      	'custom.LABEL_RESERVATION_EXPIRY': '',
      	'custom.ERROR_INVALID_EXPIRY': '',
      	'custom.ERROR_RESERVATION': '',
      	'custom.SUCCESS_RESERVATION': ''
      };
      constructor(
      	private locCommonSvc: LocalCommonService,
      	public demandService: InventoryDemandService,
      	private inventoryShipNodesService: InventoryShipNodesService,
      	private dgSvc: InventoryDistributionService,
      	private reservationService: CreateReservationService,
      	private bucNotificationService: BucNotificationService,
      	private router: Router,
      	private translateSvc: TranslateService,
      	private route: ActivatedRoute
      ) {}
      ngOnInit(): void {
      	this.createReservationForm = new FormGroup({
      		reference: new FormControl(),
      		timeToExpire: new FormControl(),
      		demandType: new FormControl([]),
      		segment: new FormControl(),
      		segmentType: new FormControl(),
      		considerSafetyStock: new FormControl(),
      		lineId: new FormControl(),
      		itemId: new FormControl(),
      		unitOfMeasure: new FormControl(),
      		productClass: new FormControl(),
      		deliveryMethod: new FormControl(),
      		quantity: new FormControl(),
      		lineSegment: new FormControl(),
      		lineSegmentType: new FormControl(),
      		shippingNode: new FormControl(),
      		dg: new FormControl()
      	});
      	this.initialize();
      	this.tenantId =
      		BucSvcAngularStaticAppInfoFacadeUtil.getInventoryTenantId();
      	this._initTranslations();
      }
      /** Fetch translations for the page */
      private async _initTranslations() {
      	const keys = Object.keys(this.nlsMap);
      	const json = await this.translateSvc.get(keys).toPromise();
      	keys.forEach(k => this.nlsMap[k] = json[k]);
      }
      async initialize(clearForm = false) {
      	await this.loadDemandTypes();
      	await this.getShipNodes();
      	await this.loadDG();
      	// set default values in the form
      	this.createReservationForm.controls['itemId'].setValue(this.reservationService.itemData?.itemId);
      	this.createReservationForm.controls['productClass'].setValue(this.reservationService.itemData?.productClass);
      	this.createReservationForm.controls['unitOfMeasure'].setValue(this.reservationService.itemData?.unitOfMeasure);
      }
      
      // loading demand types
      async loadDemandTypes() {
      	try {
      		this.validDemandTypes = await getValidDemandTypes(this.demandService);
      		const data = this.validDemandTypes.map(sup => ({
      			content: sup,
      			selected: false,
      			id: sup
      		}));
      		this.mapDemandTypes();
      	} catch (e) {
      		this.locCommonSvc.showErrorNotification('error', e.message);
      	}
      }
      mapDemandTypes() {
      	this.demandTypeItems = this.validDemandTypes.map(item => {
      		return {
      			content: item
      		};
      	});
      }
      
      // loading ship nodes
      private async getShipNodes() {
      	if (!this.shippingNodeItems || this.shippingNodeItems.length === 0) {
      		const response = await
      		this.inventoryShipNodesService.getIVShipNodesByTenantID().toPromise();
      		let shippingNodes = [];
      		if (response && response.length) {
      			shippingNodes = response.map(item => item.shipNode);
      			this.shippingNodeItems = shippingNodes.map(item => {
      				return {
      					content: item
      				};
      			});
      		}
      	}
      }
      // loading DG
      async loadDG() {
      	try {
      		const resp = await
      		this.dgSvc.getDistributionRuleListByPage(this.orgCode, 1, 999, '').toPromise();
      		const list = resp.distributionGroups
      			.filter(dg => (!dg.dgType || dg.dgType === 'PROD') &&
      				(!dg.dgPurpose || dg.dgPurpose === 'SOURCING'))
      			.map(dg => {
      				const id = dg.dgId || dg.dgKey;
      				this.dgMap[id] = dg;
      				return {
      					id,
      					content: dg.dgName,
      					selected: false,
      					value: id
      				};
      			})
      			.sort((a, b) =>
      				a.content.toLocaleLowerCase().localeCompare(b.content.toLocaleLowerCase()));
      		this.dgItems = list;
      	} catch (e) {
      		this.locCommonSvc.showErrorNotification('error', e.message);
      	}
      }
      async onSave() {
      	const request = {
      		reference: this.createReservationForm.value.reference,
      		timeToExpire: this.createReservationForm.value.timeToExpire,
      		segment: this.createReservationForm.value.segment,
      		segmentType: this.createReservationForm.value.segmentType,
      		demandType: this.createReservationForm.value.demandType.content,
      		considerSafetyStock: this.createReservationForm.value.considerSafetyStock ?
      			this.createReservationForm.value.considerSafetyStock : false,
      		lines: [{
      			lineId: this.createReservationForm.value.lineId,
      			itemId: this.createReservationForm.value.itemId,
      			unitOfMeasure: this.createReservationForm.value.unitOfMeasure,
      			productClass: this.createReservationForm.value.productClass,
      			deliveryMethod: this.createReservationForm.value.deliveryMethod,
      			shipNode: this.createReservationForm.value.shippingNode?this.createReservationForm.value.shippingNode.content:'',
      			distributionGroup: this.createReservationForm.value.dg?this.createReservationForm.value.dg.content:'',
      			segment: this.createReservationForm.value.lineSegment,
      			segmentType: this.createReservationForm.value.lineSegmentType,
      			quantity: this.createReservationForm.value.quantity
      		}]
      	};
      	// Call reservation API here
      	try {
      		await this.reservationService.createReservation(this.tenantId,
      			request).toPromise();
      		this.showNotification('success',
      			this.nlsMap['custom.SUCCESS_RESERVATION']);
      		// enabling dg and shipping node
      		this.dgDisabled = false;
      		this.shippingNodeDisabled = false;
      		// After successful reservation storing reference id to populate data in table
      		this.reservationService.reservationRef = this.createReservationForm.value.reference;
      
      	} catch (error) {
      		console.log("error", error)
      		this.showNotification('error', this.nlsMap['custom.ERROR_RESERVATION'] +
      			' ' + error.error.error_message);
      	}
      }
      // notification
      showNotification(statusType, message) {
      	const notification = new BucNotificationModel({
      		statusType,
      		statusContent: message
      	});
      	this.bucNotificationService.send([notification]);
      }
      onCancel() {
      	this.isCancelled = true;
      	this.router.navigate([Constants.RESULTS_ROUTE]);
      }
      
      onSelectShippingNode(event) {
      	// Disabling dg once shipping node is selected
      	this.dgDisabled = true;
        }
      
        onSelectDistributionGroup(event){
      	// Disabling shipping node once dg is selected
      	this.shippingNodeDisabled = true;
        }
      }
      
  11. Abra el archivo src-custom/app/app-customization.impl.ts para editarlo.
    1. Añada CreateResevationFormModule a la matriz de importaciones.
    2. Actualice la importación correspondiente.
      import { CreateReservationFormModule } from './features/create-reservation/components/create-reservation-form.module';
    3. Como resultado, el archivo src-custom/app/app-customization.impl.ts debe parecerse al siguiente archivo:
      import { RouterModule, Routes } from '@angular/router';
      import { InventoryModuleUrlGuardServiceFn } from '@buc/inventory-shared';
      import { BucCommonClassesConnectorResourcePermissionsGuard } from '@buc/svc-angular';
      import { CreateReservationComponent } from './features/create-reservation/create-reservation.component';
      import { BucActionsModule, BucCommonComponentsModule, BucFeatureComponentsModule, BucIconsModule } from '@buc/common-components';
      import { SharedModule } from '@buc/inventory-shared';
      import { CreateReservationFormModule } from './features/create-reservation/components/create-reservation-form.module';
      import { CustomConstants } from './features/create-reservation/custom-constants';
      import { ReservationActionService } from './features/create-reservation/services/reservation-action.service';
      export const customRoutes: Routes = [
         {
          canActivate: [InventoryModuleUrlGuardServiceFn, BucCommonClassesConnectorResourcePermissionsGuard],
          path: 'create-reservation',
          component: CreateReservationComponent,
          data: {
            id: 'CUSINV0001' // New resourceId to control permissions
          }
        }
      ];
      export class AppCustomizationImpl {
          static readonly components = [CreateReservationComponent];
          static readonly providers = [];
          static readonly imports = [
              RouterModule.forChild(customRoutes),
                 BucCommonComponentsModule,
                 BucFeatureComponentsModule,
                 BucIconsModule,
                 SharedModule,
                 CreateReservationFormModule,
                 BucActionsModule.forChild(
                  [ 
                    {
                    name: CustomConstants.ACTION_IDS_CREATE_RESERVATION,
                    action: ReservationActionService
                  }
                  ]
                )
        ];
          static readonly exports = [RouterModule];
      }
  12. Añada el código siguiente al archivo src-custom/app/features/create-reservation/create-reservation.component.html después del comentario <!–Reservation form --> :
    <buc-create-reservation-form></buc-create-reservation-form>
  13. Vuelva a Order Hub y vuelva a cargar el bastidor. El formulario debe estar visible en la interfaz de usuario:
    Formulario