All files / projects/requisition-management/src/app/services/requisitions requisitions.service.ts

82.69% Statements 43/52
63.63% Branches 14/22
73.33% Functions 11/15
87.75% Lines 43/49

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 1943x 3x 3x 3x   3x   3x 3x     3x                               3x   5x 5x 5x     5x                         5x                         1x 1x 1x   1x 1x     1x     1x                   2x       2x   2x             2x 2x                                     1x     1x       1x 1x             1x         1x                   3x   3x 3x   3x                   3x                   2x       2x         2x 1x   1x 1x                      
import { HttpHeaders, HttpParams } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable, of, throwError } from 'rxjs';
import { concatMap, map } from 'rxjs/operators';
 
import { AttributeHelper } from 'ish-core/models/attribute/attribute.helper';
import { OrderData } from 'ish-core/models/order/order.interface';
import { ApiService } from 'ish-core/services/api/api.service';
import { UserService } from 'ish-core/services/user/user.service';
 
import { RequisitionData } from '../../models/requisition/requisition.interface';
import { RequisitionMapper } from '../../models/requisition/requisition.mapper';
import { Requisition, RequisitionStatus, RequisitionViewer } from '../../models/requisition/requisition.model';
 
type RequisitionIncludeType =
  | 'invoiceToAddress'
  | 'commonShipToAddress'
  | 'commonShippingMethod'
  | 'discounts'
  | 'lineItems'
  | 'lineItems_discounts'
  | 'lineItems_warranty'
  | 'payments'
  | 'payments_paymentMethod'
  | 'payments_paymentInstrument';
 
@Injectable({ providedIn: 'root' })
export class RequisitionsService {
  constructor(
    private apiService: ApiService,
    private userService: UserService,
    private requisitionMapper: RequisitionMapper
  ) {}
 
  private allIncludes: RequisitionIncludeType[] = [
    'invoiceToAddress',
    'commonShipToAddress',
    'commonShippingMethod',
    'discounts',
    'lineItems',
    'lineItems_discounts',
    'lineItems_warranty',
    'payments',
    'payments_paymentMethod',
    'payments_paymentInstrument',
  ];
 
  private orderHeaders = new HttpHeaders({
    'content-type': 'application/json',
    Accept: 'application/vnd.intershop.order.v1+json',
  });
 
  /**
   * Get all customer requisitions of a certain status and view. The current user is expected to have the approver permission.
   *
   * @param  view    Defines whether the 'buyer' or 'approver' view is returned. Default: 'buyer'
   * @param  status  Approval status filter. Default: All requisitions are returned
   * @returns        Requisitions of the customer with their main attributes. To get all properties the getRequisition call is needed.
   */
  getRequisitions(view?: RequisitionViewer, status?: RequisitionStatus): Observable<Requisition[]> {
    let params = new HttpParams();
    if (view) {
      params = params.set('view', view);
    }
    if (status) {
      params = params.set('status', status);
    }
 
    return this.apiService
      .b2bUserEndpoint()
      .get<RequisitionData>(`requisitions`, { params })
      .pipe(map(data => this.requisitionMapper.fromListData(data)));
  }
 
  /**
   * Get a customer requisition of a certain id. The current user is expected to have the approver permission.
   *
   * @param  id      Requisition id.
   * @returns        Requisition with all attributes. If the requisition is approved and the order is placed, also order data are returned as part of the requisition.
   */
  getRequisition(requisitionId: string): Observable<Requisition> {
    Iif (!requisitionId) {
      return throwError(() => new Error('getRequisition() called without required id'));
    }
 
    const params = new HttpParams().set('include', this.allIncludes.join());
 
    return this.apiService
      .b2bUserEndpoint()
      .get<RequisitionData>(`requisitions/${this.apiService.encodeResourceId(requisitionId)}`, {
        params,
      })
      .pipe(
        concatMap(payload =>
          this.processRequisitionData(payload).pipe(
            concatMap(requisition => this.getRequisitionCostCenter(requisition))
          )
        )
      );
  }
 
  /**
   * Updates the requisition status. The current user is expected to have the approver permission.
   *
   * @param id          Requisition id.
   * @param statusCode  The requisition approval status
   * @param comment     The approval comment
   * @returns           The updated requisition with all attributes. If the requisition is approved and the order is placed, also order data are returned as part of the requisition.
   */
  updateRequisitionStatus(
    requisitionId: string,
    statusCode: RequisitionStatus,
    approvalComment?: string
  ): Observable<Requisition> {
    Iif (!requisitionId) {
      return throwError(() => new Error('updateRequisitionStatus() called without required id'));
    }
    Iif (!statusCode) {
      return throwError(() => new Error('updateRequisitionStatus() called without required requisition status'));
    }
 
    const params = new HttpParams().set('include', this.allIncludes.join());
    const body = {
      name: 'string',
      type: 'ApprovalStatusChange',
      statusCode,
      approvalComment,
    };
 
    return this.apiService
      .b2bUserEndpoint()
      .patch<RequisitionData>(`requisitions/${this.apiService.encodeResourceId(requisitionId)}`, body, {
        params,
      })
      .pipe(concatMap(payload => this.processRequisitionData(payload)));
  }
 
  /**
   *  Gets the order data, if needed and maps the requisition/order data.
   *
   * @param payload  The requisition row data returned by the REST interface.
   * @returns        The requisition.
   */
  private processRequisitionData(payload: RequisitionData): Observable<Requisition> {
    const params = new HttpParams().set('include', this.allIncludes.join());
 
    if (!Array.isArray(payload.data)) {
      const requisitionData = payload.data;
 
      Iif (requisitionData.order?.itemId) {
        return this.apiService
          .get<OrderData>(`orders/${this.apiService.encodeResourceId(requisitionData.order.itemId)}`, {
            headers: this.orderHeaders,
            params,
          })
          .pipe(map(data => this.requisitionMapper.fromData(payload, data)));
      }
    }
 
    return of(this.requisitionMapper.fromData(payload));
  }
 
  /**
   *  Gets the cost center data, if cost center approval is needed (the current user needs cost center admin permission) and appends it at the requisition cost center approval data.
   *
   * @param requisition   The requisition (without cost center).
   * @returns             The requisition with cost center if appropriate().
   */
  private getRequisitionCostCenter(requisition: Requisition): Observable<Requisition> {
    Iif (!requisition) {
      return of(undefined);
    }
 
    const costCenterUuid = AttributeHelper.getAttributeValueByAttributeName(
      requisition.attributes,
      'BusinessObjectAttributes#Order_CostCenter'
    ) as string;
 
    if (!costCenterUuid) {
      return of(requisition);
    } else {
      return this.userService.getCostCenter(costCenterUuid).pipe(
        map(costCenter => ({
          ...requisition,
          approval: {
            ...requisition.approval,
            costCenterApproval: { ...requisition.approval.costCenterApproval, costCenter },
          },
        }))
      );
    }
  }
}