Creación de los servicios de reserva y actualización de Order Hub para utilizar los nuevos archivos
Procedimiento
Cree un servicio para llamar a la API Crear reserva desde Sterling™ Intelligent PromisingInventory Visibility para crear una reserva.
- Ve a src-custom/app/features/create-reservation y crea una carpeta llamada services.
- Cree un servicio en src-custom/app/features/create-reservation/services.
- Ejecute el mandato siguiente:
ng g s create-reservationEsto creará un nuevo servicio en la carpeta de servicios. Este servicio se puede utilizar para añadir llamadas API.
- Copie el siguiente contenido en el create-reservation.service.ts archivo:
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 acción de reserva.
- Cree otro servicio en la misma carpeta de servicios.
- Ejecute el mandato siguiente:
ng g s reservation-actionEsto creará un nuevo servicio en la carpeta de servicios. Este servicio se puede utilizar para añadir todas las acciones del menú desplegable.
- Copie el siguiente contenido en el reservation-action.service.ts archivo:
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ñade el servicio de acción de reserva al código del centro de pedidos:
- Abre el archivo src-custom/app/app-customization.impl.ts para editarlo.
- Actualiza la matriz de importaciones para incluir módulos que añadan el servicio reservation-action :
BucActionsModule.forChild( [ { name: CustomConstants.ACTION_IDS_CREATE_RESERVATION, action: ReservationActionService } ] ) - Como resultado, la matriz de importaciones debería tener el siguiente código:
static readonly imports = [ RouterModule.forChild(customRoutes), BucCommonComponentsModule, BucFeatureComponentsModule, BucIconsModule, SharedModule, BucActionsModule.forChild( [ { name: CustomConstants.ACTION_IDS_CREATE_RESERVATION, action: ReservationActionService } ] ) ]; - Actualiza la importación con el siguiente código:
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 nueva acción para crear una reserva:
- Abre el archivo src-custom/app/features/search/inventory-table/inventory-table.component.ts para editarlo.
- Añada la importación siguiente:
import { CustomConstants } from '../../create-reservation/custom-constants'; - Añade el siguiente método 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, } ); } - En el
onOverflowMenuClickmétodo, añada la siguiente constante en la matriz de elementos:CustomConstants.ACTION_CREATE_RESERVATION - Como resultado, el
onOverflowMenuClickmétodo debería parecerse al siguiente código: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); } } - En el
onOverflowMenuActionSelectedmétodo, añade un nuevo caso:case CustomConstants.ACTION_CREATE_RESERVATION: this._setCreateReservation({ item: this.itemData }); break; - Como resultado, el
onOverflowMenuActionSelectedmétodo debería parecerse al siguiente código: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; } } - En el
_setOverflowMenumétodo, añade un nuevo ID de acción en laactionIdsmatriz:CustomConstants.ACTION_CREATE_RESERVATION - Como resultado, el
_setOverflowMenumétodo debería parecerse al siguiente código: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(); }
- Ve a src-custom/app/features/create-reservation y crea una carpeta llamada components.
- Cree los siguientes archivos dentro de la carpeta de componentes :
- create-reservation-form.component.ts
- create-reservation-form.component.html
- create-reservation-form.component.scss
- create-reservation-form.module.ts
- Abre tu formulario en el generador de interfaces de usuario Carbon ( IBM ) y haz clic en Exportar. Asegúrate de que la pestaña Angular esté seleccionada.
- Copie el contenido de src/app/components/create-reservation-form/create-reservation-form.component.ts del código Carbon UI Builder de IBM en el archivo recién create-reservation-form.component.ts creado.

- Abre el archivo recién create-reservation-form.component.html creado para editarlo.
- Añada el siguiente código:
<form [formGroup]="createReservationForm"> </form> - 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 IBM Carbon UI Builder en el archivo.

Dado que se utiliza el módulo de formularios reactivos, se requiere
formGroupun para el envío del formulario yformControlNamese requiere un para cada campo.Por tanto:- Añade lo siguiente
formControlNamepara cada campo:formControlName = referencepara los camposreferencede entrada.Después de añadirlo,formControlNamedebería parecerse al siguiente fragmento:<input ibmText name="reference" formControlName="reference" placeholder="" /> - Del mismo modo, se requiere
formControlNameun para cada uno de los campos del formulario.Reemplaza todos los
(event)parámetros del archivo por($event).Al hacerlo, se resuelven los siguientes errores:
Property 'value' does not exist on type EventTarget in TypeScript. - Cambia el
(selected)evento del nodo de envío y el grupo de distribución de la siguiente manera en cada uno de susibm-dropdownfragmentos:En el menú desplegable del nodo de envío, indicado por elibm-dropdownfragmento conformControlName="shippingNode", cambia el(selected)evento a:(selected)="onSelectShippingNode($event)"En el menú desplegable del grupo de distribución, indicado por elibm-dropdownfragmento conformControlName="dg", cambie el(selected)evento a:(selected)="onSelectDistributionGroup($event)"Estos métodos son necesarios para capturar eventos cuando se selecciona cualquiera de los menús desplegables «Nodo de envío» o «Grupo de distribución».
Por ejemplo:
Después de añadir todos los valores de control, el archivo create-reservation-form.component.html tiene el siguiente aspecto:<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 del acordeón y los valores de los botones serán diferentes al diseño que se desarrolle. Al copiar el código anterior:- Añade las propiedades [align] y [title] según las indicaciones del código al exportar el fragmento.
- Asegúrese de que la propiedad del botón Crear y Eliminar (clic) sea la misma que la del diseño del fragmento.
- Añade lo siguiente
- Copie el contenido de src/app/components/create-reservation-form/create-reservation-form.module.ts del código Carbon UI Builder de IBM en el archivo recién create-reservation-form.module.ts creado.

Además del módulo anterior, también se necesitan algunos módulos angulares:
FormsModuleyReactiveFormsModule.El archivo debe contener el siguiente código: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 { } - Copie el contenido de src/app/components/create-reservation-form/create-reservation-form.component.scss del código Carbon UI Builder de IBM en el archivo recién create-reservation-form.component.scss creado.

- Abre el archivo recién create-reservation-form.component.ts creado para editarlo.
- Cambia el nombre del selector a
'buc-create-reservation-form'.@Component({ selector: "buc-create-reservation-form", templateUrl: "./create-reservation-form.component.html", styleUrls: ["./create-reservation-form.component.scss"] }) - Implementar la
OnInitinterfaz en este componente. Añadirimplements OnInitdespués del nombre de la 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, será necesario actualizar algunos de los campos para que puedan utilizarse:
- Cambiar
@Input() quantityValue = 50;a@Input() quantityValue = 1; - Añade 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]); } - Actualiza la sección de importación con las siguientes líneas:
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"; - Como resultado, el create-reservation-form.component.ts archivo debería parecerse al siguiente archivo:
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; } }
- Cambia el nombre del selector a
- Abre el archivo src-custom/app/app-customization.impl.ts para editarlo.
- Añadir
CreateResevationFormModulea la matriz de importaciones. - Actualiza la importación correspondiente.
import { CreateReservationFormModule } from './features/create-reservation/components/create-reservation-form.module'; - Como resultado, el archivo src-custom/app/app-customization.impl.ts debería tener un aspecto similar al siguiente:
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]; }
- Añadir
- Añade el siguiente código al archivo src-custom/app/features/create-reservation/create-reservation.component.html después del
<!–Reservation form -->comentario:<buc-create-reservation-form></buc-create-reservation-form> - Vuelve al Order Hub de última generación y vuelve a cargar el marco. El formulario debe estar visible en la interfaz de usuario:
