Creating the reservation services and updating Order Hub to use the new files

Learn how to create the create-reservation and reservation-action services and update Order Hub to use the new files. In this lesson, you make several changes to your files, including by copying file changes exported from the IBM Carbon UI Builder.

Procedure

Create the service and update the Order Hub files to use the new files.

Create a service to call the Create reservation API from Sterling Inventory Visibility to create reservation.

  1. Go to src-custom/app/features/create-reservation and create a folder called services.
  2. Create a service at src-custom/app/features/create-reservation/services.
  3. Run the following command:
    ng g s create-reservation

    This will create a new service under the services folder. This service can be used to add API calls.

  4. Copy following content into the create-reservation.service.ts file:
    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$;
      }
    
    }
    

Create a reservation action service.

  1. Create another service in the same services folder.
  2. Run the following command:
    ng g s reservation-action

    This will create a new service under the services folder. This service can be used to add all the overflow menu actions.

  3. Copy the following content into the reservation-action.service.ts file:
    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;
      }
    }
    

Add the reservation action service to the Order Hub code:

  1. Open the src-custom/app/app-customization.impl.ts file for editing.
  2. Update the imports array to include modules to add the reservation-action service:
               BucActionsModule.forChild(
                [ 
                  {
                  name: CustomConstants.ACTION_IDS_CREATE_RESERVATION,
                  action: ReservationActionService
                }
                ]
              )
  3. As a result, the imports array should have the following code:
        static readonly imports = [
            RouterModule.forChild(customRoutes),
               BucCommonComponentsModule,
               BucFeatureComponentsModule,
               BucIconsModule,
               SharedModule,
               BucActionsModule.forChild(
                [ 
                  {
                  name: CustomConstants.ACTION_IDS_CREATE_RESERVATION,
                  action: ReservationActionService
                }
                ]
              )
      ];
  4. Update the import with the following code:
    import { CustomConstants } from './features/create-reservation/custom-constants';
    import { ReservationActionService } from './features/create-reservation/services/reservation-action.service';
    import { BucActionsModule } from '@buc/common-components';

Add a new action for the create reservation:

  1. Open the src-custom/app/features/search/inventory-table/inventory-table.component.ts file for editing.
  2. Add the following import:
    import { CustomConstants } from '../../create-reservation/custom-constants';
  3. Add the following method at the end:
        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. In the onOverflowMenuClick method, add the following constant in the items array:
    CustomConstants.ACTION_CREATE_RESERVATION
  5. As a result, the onOverflowMenuClick method should resemble the following code:
      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. In the onOverflowMenuActionSelected method, add a new case:
        case CustomConstants.ACTION_CREATE_RESERVATION:
          this._setCreateReservation({ item: this.itemData });
          break;
  7. As a result, the onOverflowMenuActionSelected method should resemble the following code:
      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. In the _setOverflowMenu method, add new action ID in the actionIds array:
    CustomConstants.ACTION_CREATE_RESERVATION
  9. As a result, the _setOverflowMenu method should resemble the following code:
      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();
      }
Copy files from the IBM Carbon UI Builder:
Note: There might be minor differences between the sample HTML provided in this tutorial and the HTML that you export from the IBM Carbon UI Builder. This is expected as the IBM Carbon UI Builder is an online tool that is updated on a regular basis.
  1. Go to src-custom/app/features/create-reservation and create a folder called components.
  2. Create the following files inside the components folder:
    • create-reservation-form.component.ts
    • create-reservation-form.component.html
    • create-reservation-form.component.scss
    • create-reservation-form.module.ts
  3. Open your form in the IBM Carbon UI Builder and click Export. Ensure that the Angular tab is selected.
  4. Copy the contents of src/app/components/create-reservation-form/create-reservation-form.component.ts from the IBM Carbon UI Builder code into the newly created create-reservation-form.component.ts file.
    Copy button
  5. Open the newly created create-reservation-form.component.html file for editing.
  6. Add the following code:
    <form [formGroup]="createReservationForm">
    </form>
  7. After the first line of the newly added code, copy the contents of src/app/components/create-reservation-form/create-reservation-form.component.html from the IBM Carbon UI Builder code into the file.
    Copy button

    Since the reactive forms module is used, a formGroup is required for form submission and formControlName is required for each field.

    Therefore:
    1. Add the following formControlName for each field: formControlName = reference for reference input fields.
      After adding the formControlName it should resemble the following snippet:
      <input ibmText name="reference" formControlName="reference" placeholder=""
      />
    2. Similarly, a formControlName is required for each and every field in the form.

      Replace all the (event) parameters in the file with ($event).

      Doing so resolves the following errors: Property 'value' does not exist on type EventTarget in TypeScript.

    3. Change the (selected) event of the shipping node and distribution group as follows in each of their ibm-dropdown snippets:
      In the shipping node drop down, denoted by the ibm-dropdown snippet with formControlName="shippingNode", change the (selected) event to:
      (selected)="onSelectShippingNode($event)"
      In the distribution group drop down, denoted by the ibm-dropdown snippet with formControlName="dg", change the (selected) event to:
      (selected)="onSelectDistributionGroup($event)"

      These methods are required to capture events when either of the shipping node or distribution group drop down is selected.

      For example:
      ibm-dropdown updates
    After adding all the control values, the create-reservation-form.component.html file resembles the following code:
    <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>
    Accordion values and button values will be different than the design that is developed. While copying the preceding code:
    1. Add accordion [align] and [title] properties as per the remarks in the code while exporting the fragment.
    2. Ensure that the Create and Delete button (click) property is the same as the fragment design.
  8. Copy the contents of src/app/components/create-reservation-form/create-reservation-form.module.ts from the IBM Carbon UI Builder code into the newly created create-reservation-form.module.ts file.
    Copy button

    Other than the above module, a few angular modules are also needed: FormsModule and ReactiveFormsModule.

    The file should contain the following code:
    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. Copy the contents of src/app/components/create-reservation-form/create-reservation-form.component.scss from the IBM Carbon UI Builder code into the newly created create-reservation-form.component.scss file.
    Copy button
  10. Open the newly created create-reservation-form.component.ts file for editing.
    1. Change the selector name to 'buc-create-reservation-form'.
      @Component({
      	selector: "buc-create-reservation-form",
      	templateUrl: "./create-reservation-form.component.html",
      	styleUrls: ["./create-reservation-form.component.scss"]
      })
    2. Implement the OnInit interface in this component. Add implements OnInit after the class name.
      @Component({
      	selector: "buc-create-reservation-form",
      	templateUrl: "./create-reservation-form.component.html",
      	styleUrls: ["./create-reservation-form.component.scss"]
      })
      export class CreateReservationForm implements OnInit{

      Then, some of the fields will need to be updated so that they can be used:

    3. Change @Input() quantityValue = 50; to @Input() quantityValue = 1;
    4. Add new variables and methods by adding new variables after all the variable declarations:
      // 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. Update the import section with the following lines:
      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. As a result, the create-reservation-form.component.ts file should resemble the following file:
      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. Open the src-custom/app/app-customization.impl.ts file for editing.
    1. Add CreateResevationFormModule into the imports array.
    2. Update the corresponding import.
      import { CreateReservationFormModule } from './features/create-reservation/components/create-reservation-form.module';
    3. As a result, the src-custom/app/app-customization.impl.ts file should resemble the following file:
      import { RouterModule, Routes } from '@angular/router';
      import { Constants, InventoryModuleUrlGuardService } 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: [InventoryModuleUrlGuardService],
          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. Add the following code to the src-custom/app/features/create-reservation/create-reservation.component.html file after the <!–Reservation form --> comment:
    <buc-create-reservation-form></buc-create-reservation-form>
  13. Go back to Order Hub and reload the frame. The form should be visible on the UI:
    Form