Added Service to Fetch the Availability Date

This commit is contained in:
Lorenz Hilpert
2019-02-07 14:27:23 +01:00
parent cc65eb62d3
commit 2921c26d5f
19 changed files with 338 additions and 4 deletions

View File

@@ -0,0 +1,60 @@
import { TestBed, getTestBed } from '@angular/core/testing';
import { CatAvailabilityService } from './cat-availability.service';
import { HttpTestingController, HttpClientTestingModule } from '@angular/common/http/testing';
import { CAT_SERVICE_ENDPOINT } from './tokens';
import { AvailabilityRequestDTO } from './dtos';
import { CatServiceValidationError } from './errors';
describe('CatAvailabilityService', () => {
const endpoint = 'https://fake-endpoint.de';
let injector: TestBed;
let service: CatAvailabilityService;
let httpMock: HttpTestingController;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [
CatAvailabilityService,
{ provide: CAT_SERVICE_ENDPOINT, useValue: endpoint }
]
});
injector = getTestBed();
service = injector.get(CatAvailabilityService);
httpMock = injector.get(HttpTestingController);
});
describe('#get', () => {
it('should issue a POST request to /ola/availability', () => {
service.get([]).subscribe();
const req = httpMock.expectOne({ method: 'POST', url: `${endpoint}/ola/availability` });
});
it('should have the argument in the request body', () => {
const av: AvailabilityRequestDTO[] = [{ ean: '123456789' }];
service.get(av).subscribe();
const req = httpMock.expectOne({ method: 'POST', url: `${endpoint}/ola/availability` });
expect(req.request.body).toBe(av);
});
it('should throw an CatServiceValidationError if the validation fails', () => {
const av: AvailabilityRequestDTO[] = [null];
service.get(av).subscribe(
() => { console.log('fsag'); },
(error) => {
expect(error instanceof CatServiceValidationError).toBeTruthy();
}
);
httpMock.expectNone({ method: 'POST', url: `${endpoint}/ola/availability` });
});
});
});

View File

@@ -0,0 +1,39 @@
import { Injectable, Inject } from '@angular/core';
import { AvailabilityRequestDTO, ArticleAvailabilityDTO } from './dtos';
import { HttpClient } from '@angular/common/http';
import { CAT_AV_SERVICE_ENDPOINT } from './tokens';
import { Observable, isObservable, throwError, } from 'rxjs';
import { ApiResponse } from './response';
import { availabilityRequestValidator } from './validators';
import { CatServiceValidationError } from './errors';
@Injectable({ providedIn: 'root' })
export class CatAvailabilityService {
endpoint = '';
constructor(
private http: HttpClient,
@Inject(CAT_AV_SERVICE_ENDPOINT) endpoint: string | Observable<string>
) {
if (isObservable(endpoint)) {
endpoint.subscribe(e => this.endpoint = e);
} else {
this.endpoint = endpoint;
}
}
get(req: AvailabilityRequestDTO[]): Observable<ApiResponse<ArticleAvailabilityDTO[]>> {
for (const result of req.map(item => availabilityRequestValidator(item))) {
if (!result.valid) {
return throwError(new CatServiceValidationError(result));
}
}
return this.http.post<ApiResponse<ArticleAvailabilityDTO[]>>(
`${this.endpoint}/ola/availability`,
req
);
}
}

View File

@@ -0,0 +1,84 @@
import { PriceDTO } from './price.dto';
import { AvailabilityType } from '../../enums';
export interface ArticleAvailabilityDTO {
/**
* Produkt / Artikel PK
*/
itemId?: number;
/**
* Eindeutige Referenz zur Zuordnung
*/
requestReference: string;
/**
* EAN
*/
ean: string;
/**
* Shop Id
*/
shop?: number;
/**
* Price
*/
price: PriceDTO;
/**
* Lieferant
*/
supplier: string;
/**
* Stock Status Code / Meldeschlüssel
*/
ssc: string;
/**
* Verfügbare Menge
*/
qty?: number;
/**
* Vorgemerkt
*/
isPrebooked?: boolean;
/**
* Voraussichtliches Lieferdatum
*/
at?: Date;
/**
* Alternatives Voraussichtliches Lieferdatum
*/
altAt?: Date;
/**
* Verfügbarkeitsstatus
*/
availabilityType: AvailabilityType;
/**
* Rang
*/
preferred?: number;
/**
* Zeitstemple der Anfrage
*/
requested?: Date;
/**
* StatusCode der Verfügbarkeitsanfrage
*/
requestStatusCode: string;
/**
* Beschreibung des StatusCode
*/
requestMessage: string;
}

View File

@@ -1,10 +1,12 @@
// start:ng42.barrel
export * from './article-availability.dto';
export * from './availability.dto';
export * from './item.dto';
export * from './price-value.dto';
export * from './price.dto';
export * from './product.dto';
export * from './shelf-info.dto';
export * from './shop.dto';
export * from './size.dto';
export * from './spec.dto';
export * from './stock-info.dto';

View File

@@ -0,0 +1,11 @@
export interface ShopDTO {
/**
* PK
*/
id?: number;
/**
* Name / Bezeichner
*/
name: string;
}

View File

@@ -0,0 +1,58 @@
import { PriceDTO } from '../data';
export interface AvailabilityRequestDTO {
/**
* Artikel / Produkt PK
*/
itemId?: string;
/**
* EAN
*/
ean?: string;
/**
* Menge / Stück
*/
qty?: number;
/**
* Bestellzeichen
*/
orderCode?: string;
/**
* Lieferant
*/
supplier?: string;
/**
* Bestellung vormerken
*/
preBook?: boolean;
/**
* Preis
*/
prive?: PriceDTO;
/**
* Stock Status Code
*/
ssc?: string;
/**
* Vsl. Lieferdatum
*/
estimatedShipping?: Date;
/**
* Shop PK
*/
shopId?: number;
/**
* Zuordnungs-ID
*/
availabilityReference?: string;
}

View File

@@ -1,5 +1,6 @@
// start:ng42.barrel
export * from './autocomplete-token.dto';
export * from './availability-request.dto';
export * from './query-token.dto';
// end:ng42.barrel

View File

@@ -0,0 +1,8 @@
import { CatServiceError } from './cat-service.error';
import { ValidationResult } from '../models';
export class CatServiceValidationError extends CatServiceError {
constructor(public result: ValidationResult) {
super(result.message);
}
}

View File

@@ -0,0 +1,7 @@
export class CatServiceError extends Error {
constructor(message: string) {
super(`[cat-service] ${message}`);
}
}

View File

@@ -0,0 +1,5 @@
// start:ng42.barrel
export * from './cat-service-validation.error';
export * from './cat-service.error';
// end:ng42.barrel

View File

@@ -1,5 +1,6 @@
// start:ng42.barrel
export * from './cat-image.service';
export * from './cat-availability.service';
export * from './cat-search-mock.data';
export * from './cat-search-mock.service';
export * from './cat-search.service';

View File

@@ -1,4 +1,5 @@
// start:ng42.barrel
export * from './dictionary.model';
export * from './valiation-result.model';
// end:ng42.barrel

View File

@@ -0,0 +1,27 @@
import { StringDictionary } from './dictionary.model';
export class ValidationResult {
private _valid = true;
get valid() { return this._valid; }
private _message?: string;
get message() { return this._message; }
private _invalidProperties?: StringDictionary<string>;
get invalidProperties() { return this._invalidProperties; }
setMessage(message: string) {
this._message = message;
this._valid = false;
}
addPropertyError(proeprty: string, reason: string) {
const ip = this.invalidProperties || {};
ip[proeprty] = reason;
this._invalidProperties = ip;
if (this.message == null) {
this.setMessage('Invalid property.');
}
}
}

View File

@@ -2,3 +2,4 @@ import { InjectionToken } from '@angular/core';
import { Observable } from 'rxjs';
export const CAT_SERVICE_ENDPOINT = new InjectionToken<string | Observable<string>>('cat:service:endpoint');
export const CAT_AV_SERVICE_ENDPOINT = new InjectionToken<string | Observable<string>>('cat:av:service:endpoint');

View File

@@ -0,0 +1,15 @@
import { AvailabilityRequestDTO } from '../dtos';
import { ValidationResult, StringDictionary } from '../models';
export function availabilityRequestValidator(av: AvailabilityRequestDTO): ValidationResult {
const result = new ValidationResult();
if (av == null) {
result.setMessage('AvailabilityRequestDTO is null or undefined.');
} else {
}
return result;
}

View File

@@ -0,0 +1,4 @@
// start:ng42.barrel
export * from './availability-request.validator';
// end:ng42.barrel

View File

@@ -2,6 +2,7 @@
* Public API Surface of cat-service
*/
export * from './lib/cat-image.service';
export * from './lib/cat-availability.service';
export * from './lib/cat-search-mock.data';
export * from './lib/cat-search-mock.service';
export * from './lib/cat-search.service';

View File

@@ -7,7 +7,7 @@ import { ComponentsModule } from './modules/components.module';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { BasicAuthorizationInterceptor, BasicAuthorizationOptions } from './core/interceptors';
import { SearchResultsComponent } from './components/search-results/search-results.component';
import { CatServiceModule, CAT_SERVICE_ENDPOINT, CatSearchService } from 'cat-service';
import { CatServiceModule, CAT_SERVICE_ENDPOINT, CatSearchService, CAT_AV_SERVICE_ENDPOINT } from 'cat-service';
import { ProductCardComponent } from './components/product-card/product-card.component';
import { ConfigService } from './core/services/config.service';
import { ProductDetailsComponent } from './components/product-details/product-details.component';
@@ -45,7 +45,11 @@ export function _basicAuthorizationInterceptorFactory(conf: ConfigService) {
}
export function _catServiceEndpointProviderFactory(conf: ConfigService) {
return conf.select<string>('catService', 'endpoint');
return conf.select<string>('catService', 'endpoint', 'catService');
}
export function _catAvServiceEndpointProviderFactory(conf: ConfigService) {
return conf.select<string>('catService', 'endpoint', 'avService');
}
export function _feedServiceEndpointProviderFactory(conf: ConfigService) {
@@ -79,6 +83,7 @@ export function _feedServiceEndpointProviderFactory(conf: ConfigService) {
{ provide: APP_INITIALIZER, useFactory: _configInitializer, multi: true, deps: [ ConfigService ] },
{ provide: HTTP_INTERCEPTORS, useFactory: _basicAuthorizationInterceptorFactory, deps: [ConfigService], multi: true },
{ provide: CAT_SERVICE_ENDPOINT, useFactory: _catServiceEndpointProviderFactory, deps: [ConfigService] },
{ provide: CAT_AV_SERVICE_ENDPOINT, useFactory: _catAvServiceEndpointProviderFactory, deps: [ConfigService] },
{ provide: FEED_SERVICE_ENDPOINT, useFactory: _feedServiceEndpointProviderFactory, deps: [ConfigService] },
// { provide: CatSearchService, useClass: CatSearchMockService }, // Uncomment if u want to use the CatSearchMockService
{ provide: FeedService, useClass: FeedMockService } // Uncomment if u want to use the FeedMockService

View File

@@ -3,11 +3,15 @@
"client": "eu6YYrF3NB4CtxMTwrgC",
"password": "rf5f9JUzKW7cjwd6vb6YHv2L2knEZ6m4mNsbpLMF",
"endpoints": [
"https://catsearch.paragon-data.de"
"https://catsearch.paragon-data.de",
"https://ava.paragon-data.de"
]
},
"catService": {
"endpoint": "https://catsearch.paragon-data.de"
"endpoint": {
"catService": "https://catsearch.paragon-data.de",
"avService": "https://ava.paragon-data.de"
}
},
"feedService": {
"endpoint": "https://isa.paragon-data.de"