diff --git a/Dockerfile b/Dockerfile index 207594f..14729f2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,6 +23,7 @@ WORKDIR $APP_HOME COPY --chown=node:node ./cfg $APP_HOME/cfg COPY --chown=node:node ./queries $APP_HOME/queries +COPY --chown=node:node ./wsdl $APP_HOME/wsdl COPY --chown=node:node --from=build $APP_HOME/lib $APP_HOME/lib EXPOSE 50051 diff --git a/cfg/config.json b/cfg/config.json index 8a11dfa..b914cc3 100644 --- a/cfg/config.json +++ b/cfg/config.json @@ -70,6 +70,9 @@ "tax": { "address": "localhost:50063" }, + "credential": { + "address": "localhost:50063" + }, "product": { "address": "localhost:50068" } diff --git a/cfg/config_test.json b/cfg/config_test.json index cbfc682..c412384 100644 --- a/cfg/config_test.json +++ b/cfg/config_test.json @@ -163,6 +163,19 @@ ] } } + }, + "credential": { + "address": "localhost:50173", + "mock": { + "protoPath": "io/restorecommerce/credential.proto", + "packageName": "io.restorecommerce.credential", + "serviceName": "CredentialService", + "protoLoadOptions": { + "includeDirs": [ + "node_modules/@restorecommerce/protos/" + ] + } + } } } } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index b6ce6fc..cc8827e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,14 +8,14 @@ "name": "@restorecommerce/fulfillments-srv", "version": "0.0.20", "dependencies": { - "@restorecommerce/acs-client": "^1.6.6", + "@restorecommerce/acs-client": "^1.6.7", "@restorecommerce/cart": "^1.0.5", "@restorecommerce/chassis-srv": "^1.6.0", "@restorecommerce/cluster-service": "^1.0.3", "@restorecommerce/grpc-client": "^2.2.1", - "@restorecommerce/kafka-client": "^1.2.1", + "@restorecommerce/kafka-client": "^1.2.6", "@restorecommerce/logger": "^1.2.10", - "@restorecommerce/rc-grpc-clients": "^5.1.27", + "@restorecommerce/rc-grpc-clients": "^5.1.28", "@restorecommerce/resource-base-interface": "^1.6.0", "@restorecommerce/service-config": "^1.0.12", "@types/soap": "^0.21.0", @@ -2198,14 +2198,14 @@ } }, "node_modules/@restorecommerce/acs-client": { - "version": "1.6.6", - "resolved": "https://registry.npmjs.org/@restorecommerce/acs-client/-/acs-client-1.6.6.tgz", - "integrity": "sha512-6UfcleChboHqAMoX3GnXymhDAch3zP0qNrDLju31HV1LPtX8vbHfYlpctHmr/+a30GWHgK0a2keHZrHrUZF52g==", + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/@restorecommerce/acs-client/-/acs-client-1.6.7.tgz", + "integrity": "sha512-MnZpTK2rdCW51HrPQlqgYdXIqTbzR1GRiycoZkUqfX5+B5IGtGEWbTgs6qIAQMT7p1WIGpogX55kKh3khb0KQQ==", "dependencies": { "@restorecommerce/grpc-client": "^2.2.1", - "@restorecommerce/kafka-client": "^1.2.5", + "@restorecommerce/kafka-client": "^1.2.6", "@restorecommerce/logger": "^1.2.10", - "@restorecommerce/rc-grpc-clients": "^5.1.27", + "@restorecommerce/rc-grpc-clients": "^5.1.28", "@restorecommerce/service-config": "^1.0.12", "deepdash": "^5.3.9", "lodash": "^4.17.21", @@ -2547,12 +2547,12 @@ } }, "node_modules/@restorecommerce/kafka-client": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@restorecommerce/kafka-client/-/kafka-client-1.2.5.tgz", - "integrity": "sha512-tvEhiWsTewnoA9kEFLqE1op+62ItGOKjoV6pF85zisznxin7BYXXcn7zCd3d4JQpao0HHBPuzgILCYRyaIdn9w==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@restorecommerce/kafka-client/-/kafka-client-1.2.6.tgz", + "integrity": "sha512-5XV/vLK0lMqLpakCZj+haEKAL2EoTBcW3/oed6q3H3C9vdjiQlJmUvT/3kkiOEx4f0ELWLqlrWU36K6Vfc6ATg==", "dependencies": { "@restorecommerce/logger": "^1.2.10", - "@restorecommerce/rc-grpc-clients": "^5.1.27", + "@restorecommerce/rc-grpc-clients": "^5.1.28", "async": "^3.2.5", "cls-rtracer": "^2.6.3", "events": "^3.3.0", @@ -2588,9 +2588,9 @@ "integrity": "sha512-IbFpZFsYBTzYdrntDQ+lThelgsgS9HJkhMgj23IH5U8ewtaHj5jRsC8t3y/sNspQUyGPuvwGjephOsflmzuw7g==" }, "node_modules/@restorecommerce/rc-grpc-clients": { - "version": "5.1.27", - "resolved": "https://registry.npmjs.org/@restorecommerce/rc-grpc-clients/-/rc-grpc-clients-5.1.27.tgz", - "integrity": "sha512-zjPI8/CSjV93yDWVei2NiidblleFjQwD7NfgjchKkFc1rgzFJTd7ZHyOqoP6EV5VdbMgc3B3DRodxn0vlt1EtQ==", + "version": "5.1.28", + "resolved": "https://registry.npmjs.org/@restorecommerce/rc-grpc-clients/-/rc-grpc-clients-5.1.28.tgz", + "integrity": "sha512-GWeyuaUoBaSjBe4usMOO5yJgXkoWMAmOH9mZ+qckclIEkKVlvJhjePHwnR5Qenjsb+mjm3uBmz+QcX53zLYQ7g==", "dependencies": { "@grpc/grpc-js": "^1.9.11", "@restorecommerce/grpc-client": "^2.2.1", diff --git a/package.json b/package.json index b294e6f..fed8aba 100644 --- a/package.json +++ b/package.json @@ -10,14 +10,14 @@ }, "type": "module", "dependencies": { - "@restorecommerce/acs-client": "^1.6.6", + "@restorecommerce/acs-client": "^1.6.7", "@restorecommerce/cart": "^1.0.5", "@restorecommerce/chassis-srv": "^1.6.0", "@restorecommerce/cluster-service": "^1.0.3", "@restorecommerce/grpc-client": "^2.2.1", - "@restorecommerce/kafka-client": "^1.2.1", + "@restorecommerce/kafka-client": "^1.2.6", "@restorecommerce/logger": "^1.2.10", - "@restorecommerce/rc-grpc-clients": "^5.1.27", + "@restorecommerce/rc-grpc-clients": "^5.1.28", "@restorecommerce/resource-base-interface": "^1.6.0", "@restorecommerce/service-config": "^1.0.12", "@types/soap": "^0.21.0", diff --git a/src/services/fulfillment.ts b/src/services/fulfillment.ts index 143e7ef..cbe2740 100644 --- a/src/services/fulfillment.ts +++ b/src/services/fulfillment.ts @@ -61,6 +61,10 @@ import { Customer, CustomerServiceDefinition } from '@restorecommerce/rc-grpc-clients/dist/generated-server/io/restorecommerce/customer.js'; +import { + Credential, + CredentialServiceDefinition +} from '@restorecommerce/rc-grpc-clients/dist/generated-server/io/restorecommerce/credential.js'; import { Shop, ShopServiceDefinition @@ -173,6 +177,7 @@ export class FulfillmentService protected readonly address_service: Client; protected readonly country_service: Client; protected readonly tax_service: Client; + protected readonly credential_service: Client; constructor( readonly fulfillmentCourierSrv: FulfillmentCourierService, @@ -272,6 +277,15 @@ export class FulfillmentService TaxServiceDefinition, createChannel(cfg.get('client:tax:address')) ); + + this.credential_service = createClient( + { + ...cfg.get('client:credential'), + logger + } as GrpcClientConfig, + CredentialServiceDefinition, + createChannel(cfg.get('client:credential:address')) + ); } protected handleStatusError(id: string, e: any, payload?: any): T { @@ -405,11 +419,10 @@ export class FulfillmentService context?: any, ): Promise> { ids = [...new Set(ids)]; - const entity = ({} as new() => T).name; if (ids.length > 1000) { throwOperationStatusCode( - entity, + service.constructor?.name, this.operation_status_codes.LIMIT_EXHAUSTED, ); } @@ -450,22 +463,22 @@ export class FulfillmentService ); } - async getById(map: { [id: string]: T }, id: string): Promise { - if (id in map) { + async getById(map: { [id: string]: T }, id: string, name: string): Promise { + if (map && id in map) { return map[id]; } else { throwStatusCode( - ({} as new() => T).name, + name, id, this.status_codes.NOT_FOUND ); } } - async getByIds(map: { [id: string]: T }, ids: string[]): Promise { + async getByIds(map: { [id: string]: T }, ids: string[], name: string): Promise { return Promise.all(ids.map( - id => this.getById(map, id) + id => this.getById(map, id, name) )); } @@ -579,6 +592,15 @@ export class FulfillmentService context, ); + const credential_map = await this.get( + Object.values(courier_map).map( + c => c.payload?.credential_id + ), + this.credential_service, + subject, + context, + ) + const tax_map = await this.get( Object.values(product_map).flatMap( p => p.payload?.tax_ids @@ -593,11 +615,13 @@ export class FulfillmentService const sender_country = await this.getById( country_map, item.packaging.sender?.address?.country_id, + 'Country' ); const recipient_country = await this.getById( country_map, item.packaging.recipient?.address?.country_id, + 'Country' ); const products = await this.getByIds( @@ -605,14 +629,16 @@ export class FulfillmentService item.packaging.parcels.map( parcel => parcel?.product_id ), + 'Product' ); const couriers = await this.getByIds( courier_map, products.map( product => product.payload?.courier_id - ) - ) + ), + 'Courier' + ); couriers.every( courier => courier.payload?.shop_ids?.includes( @@ -624,6 +650,16 @@ export class FulfillmentService this.status_codes.SHOP_ID_NOT_IDENTICAL, ); + const credentials = await this.getByIds( + credential_map, + couriers.map( + c => c.payload?.credential_id + ).filter( + id => id + ), + 'Credential' + ); + const status: Status[] = [ sender_country?.status, recipient_country?.status, @@ -633,16 +669,19 @@ export class FulfillmentService const shop_country = await this.getById( shop_map, - item.shop_id + item.shop_id, + 'Shop' ).then( shop => this.getById( orga_map, - shop.payload?.organization_id + shop.payload!.organization_id, + 'Organization' ) ).then( orga => this.getByIds( contact_point_map, - orga.payload?.contact_point_ids + orga.payload!.contact_point_ids, + 'ContactPoint' ) ).then( cpts => cpts.find( @@ -657,18 +696,21 @@ export class FulfillmentService ).then( contact_point => this.getById( address_map, - contact_point.payload?.physical_address_id, + contact_point.payload!.physical_address_id, + 'ContactPoint' ) ).then( address => this.getById( country_map, - address.payload?.country_id + address.payload!.country_id, + 'Country' ) ); const customer = await this.getById( customer_map, - item.customer_id + item.customer_id, + 'Customer' ); const customer_country = await this.getByIds( @@ -677,7 +719,8 @@ export class FulfillmentService customer.payload.private?.contact_point_ids, orga_map[customer.payload.commercial?.organization_id]?.payload.contact_point_ids, orga_map[customer.payload.public_sector?.organization_id]?.payload.contact_point_ids, - ].flatMap(id => id).filter(id => id) + ].flatMap(id => id).filter(id => id), + 'Country' ).then( cps => cps.find( cp => cp.payload?.contact_point_type_ids.indexOf( @@ -692,11 +735,13 @@ export class FulfillmentService cp => this.getById( address_map, cp.payload.physical_address_id, + 'Address' ) ).then( address => this.getById( country_map, - address.payload.country_id + address.payload.country_id, + 'Country' ) ); @@ -740,6 +785,7 @@ export class FulfillmentService payload: item, products, couriers, + credentials, sender_country, recipient_country, options: null, @@ -921,7 +967,7 @@ export class FulfillmentService }, context); upsert_results.items.forEach(item => { - if (item.payload.fulfillment_state in this.emitters) { + if (this.emitters && item.payload.fulfillment_state in this.emitters) { switch (item.payload.fulfillment_state) { case FulfillmentState.INVALID: case FulfillmentState.FAILED: @@ -1069,7 +1115,7 @@ export class FulfillmentService updates => updates.items.forEach( item => { response_map[item.payload?.id ?? item.status?.id] = item as FulfillmentResponse; - if (item.payload.fulfillment_state in this.emitters) { + if (this.emitters && item.payload.fulfillment_state in this.emitters) { switch (item.payload.fulfillment_state) { case FulfillmentState.INVALID: case FulfillmentState.FAILED: @@ -1208,7 +1254,7 @@ export class FulfillmentService }, context); update_results.items.forEach(item => { - if (item.payload.fulfillment_state in this.emitters) { + if (this.emitters && item.payload.fulfillment_state in this.emitters) { switch (item.payload.fulfillment_state) { case FulfillmentState.INVALID: case FulfillmentState.FAILED: diff --git a/src/stubs/dhl_soap.ts b/src/stubs/dhl_soap.ts index 24c2f3f..982a5dc 100644 --- a/src/stubs/dhl_soap.ts +++ b/src/stubs/dhl_soap.ts @@ -11,6 +11,9 @@ import { import { FulfillmentCourier as Courier } from '@restorecommerce/rc-grpc-clients/dist/generated-server/io/restorecommerce/fulfillment_courier.js'; +import { + Credential +} from '@restorecommerce/rc-grpc-clients/dist/generated-server/io/restorecommerce/credential.js'; import { OperationStatus, Status } from '@restorecommerce/rc-grpc-clients/dist/generated-server/io/restorecommerce/status.js'; import { FlatAggregatedFulfillment, @@ -21,6 +24,13 @@ import { Stub } from '../stub.js'; dayjs.extend(customParseFormat); type ClientMap = { [id: string]: soap.Client }; +type RequestMap = { + [id: string]: { + courier: Courier, + credential: Credential, + fulfillments: FlatAggregatedFulfillment[], + } +} interface Origin { @@ -125,6 +135,31 @@ interface ShipmentCancelRequest shipmentNumber: string[]; } +interface Config +{ + ordering?: { + wsdl?: string, + version?: number[], + endpoint?: string, + username?: string, + password?: string, + wsdl_header?: { + Authentification?: { + user?: string, + signature?: string, + }, + }, + }, + tracking?: { + version?: number[], + appname?: string, + endpoint?: string, + username?: string, + password?: string, + secret?: string, + }, +} + const parseService = (attributes: any[]) => attributes.filter((att: any) => att.id.startsWith('urn:restorecommerce:fufs:names:service:attr:dhl') ).map((att: any) => ({ @@ -539,85 +574,133 @@ class DHLSoap extends Stub { }; } - async registerSoapClient(courier?: Courier): Promise { + async getSoapClient(courier: Courier, credential: Credential): Promise { this.courier = courier = courier ?? this.courier; if (this.clients[courier.id]) { return this.clients[courier.id]; } try{ - const configs = JSON.parse(courier?.configuration?.value?.toString() ?? null)?.ordering ?? this.stub_defaults?.ordering; - const wsdl = configs?.wsdl ?? this.stub_defaults?.ordering?.wsdl; - const username = configs?.username ?? this.stub_defaults?.ordering?.username; - const password = configs?.password ?? this.stub_defaults?.ordering?.password; - const endpoint = configs?.endpoint ?? this.stub_defaults?.ordering?.endpoint; - const wsdlHeader = configs?.wsdl_header ?? this.stub_defaults?.ordering?.wsdl_header; - this.clients[courier.id] = await soap.createClientAsync(wsdl).then(client => { - client.setEndpoint(endpoint); - client.addSoapHeader(typeof(wsdlHeader) === 'string' ? JSON.parse(wsdlHeader) : wsdlHeader); - client.setSecurity(new soap.BasicAuthSecurity(username, password)); - return client; - }); + const config: Config = { + ordering: { + ...this.stub_defaults?.ordering, + ...JSON.parse(courier?.configuration?.value?.toString() ?? null)?.ordering, + ...credential + ? { + username: credential?.user, + password: credential?.pass, + } + : {}, + ...JSON.parse(credential?.credentials?.value?.toString() ?? null)?.ordering, + } + }; + + this.clients[courier.id] = await soap.createClientAsync(config.ordering.wsdl).then( + client => { + client.setEndpoint(config.ordering.endpoint); + client.addSoapHeader( + typeof(config.ordering.wsdl_header) === 'string' + ? JSON.parse(config.ordering.wsdl_header) + : config.ordering.wsdl_header + ); + client.setSecurity(new soap.BasicAuthSecurity(config.ordering.username, config.ordering.password)); + return client; + } + ); } catch (err) { - this.logger?.error(`${this.constructor.name}:\n Failed to create Client!`); - this.logger?.error(`${this.constructor.name}: ${JSON.stringify(err, null, 2)}`); + this.logger?.error(`${this.type}:\n Failed to create Client!`); + this.logger?.error(`${this.type}: ${JSON.stringify(err, null, 2)}`); throw err; } return this.clients[courier.id]; }; - protected override async evaluateImpl (fulfillments: FlatAggregatedFulfillment[]): Promise { + protected async soapCall( + funcName: string, + fulfillments: FlatAggregatedFulfillment[] + ): Promise { if (fulfillments.length === 0) return []; - const dhl_order_request = this.AggregatedFulfillmentRequests2DHLShipmentOrderRequest(fulfillments); - const client = await this.registerSoapClient(); - return new Promise((resolve): void => { - client.GVAPI_2_0_de.GKVAPISOAP11port0.evaluateShipmentOrder( - dhl_order_request, - (error: any, result: any): any => { - resolve(this.DHLShipmentLabels2FulfillmentResponses(fulfillments, result, error)); + const request_map = fulfillments.reduce( + (a, b) => { + const c = a[b.courier?.id]; + if (c) { + c.fulfillments.push(b); } - ); - }); + else if (b.courier?.id) { + a[b.courier.id] = { + courier: b.courier, + credential: b.credential, + fulfillments: [b], + }; + } + return a; + }, + {} as RequestMap + ); + return await Promise.all( + Object.values(request_map).map( + ({courier, credential, fulfillments}) => this.getSoapClient(courier, credential).then( + client => new Promise( + (resolve, reject): void => { + const timer = setTimeout(reject, 30000, this.operation_status_codes.TIMEOUT); + client.GVAPI_2_0_de.GKVAPISOAP11port0[funcName]( + this.AggregatedFulfillmentRequests2DHLShipmentOrderRequest(fulfillments), + (error: any, result: any): any => { + try { + clearTimeout(timer); + resolve(this.DHLShipmentLabels2FulfillmentResponses(fulfillments, result, error)); + } + catch (e: any) { + reject(e); + } + } + ) + } + ) + ) + ) + ).then( + p => p.flatMap(p => p) + ); + } + + protected override async evaluateImpl (fulfillments: FlatAggregatedFulfillment[]): Promise { + return await this.soapCall('evaluateShipmentOrder', fulfillments); } protected override async submitImpl (fulfillments: FlatAggregatedFulfillment[]): Promise { - if (fulfillments.length === 0) return []; - const dhl_order_request = this.AggregatedFulfillmentRequests2DHLShipmentOrderRequest(fulfillments); - const client = await this.registerSoapClient(); - return await new Promise((resolve, reject): void => { - const timer = setTimeout(reject, 30000, this.operation_status_codes.TIMEOUT); - client.GVAPI_2_0_de.GKVAPISOAP11port0.createShipmentOrder( - dhl_order_request, - (error: any, result: any): any => { - clearTimeout(timer); - try { - resolve(this.DHLShipmentLabels2FulfillmentResponses(fulfillments, result, error)); - } - catch (e: any) { - reject(e); - } - } - ); - }); + return await this.soapCall('createShipmentOrder', fulfillments); } + protected override async cancelImpl (fulfillments: FlatAggregatedFulfillment[]): Promise { + return await this.soapCall('deleteShipmentOrder', fulfillments); + }; + protected override async trackImpl (fulfillments: FlatAggregatedFulfillment[]): Promise { const promises = fulfillments.map(async item => { try { + const courier = item.courier; + const credential = item.credential; const options = JSON.parse(item?.options?.value?.toString() ?? null); - const config = JSON.parse(this.courier?.configuration?.value?.toString() ?? null)?.tracking ?? this.stub_defaults?.tracking; - const client = { - appname: config?.appname ?? this.stub_defaults?.tracking?.appname, - username: config?.username ?? this.stub_defaults?.tracking?.username, - password: config?.password ?? this.stub_defaults?.tracking?.password, - endpoint: config?.endpoint ?? this.stub_defaults?.tracking?.endpoint, - secret: config?.secret ?? this.stub_defaults?.tracking?.secret, + const config: Config = { + tracking: { + ...this.stub_defaults?.tracking, + ...JSON.parse(courier?.configuration?.value?.toString() ?? null)?.tracking, + ...credential + ? { + username: credential?.user, + password: credential?.pass, + } + : {}, + ...JSON.parse(credential?.credentials?.value?.toString() ?? null)?.tracking, + } }; - const auth = 'Basic ' + Buffer.from(`${client.username}:${client.password}`).toString('base64'); + + const auth = 'Basic ' + Buffer.from(`${config.tracking.username}:${config.tracking.password}`).toString('base64'); const attributes = { - appname: client.appname, - password: client.secret, + appname: config.tracking.appname, + password: config.tracking.secret, 'piece-code': item.label.shipment_number, 'language-code': options?.['language-code'] ?? 'de', request: options?.request ?? 'd-get-piece-detail' @@ -637,15 +720,15 @@ class DHLSoap extends Stub { // body: params, }; - return await fetch(`${client.endpoint}?${params}`, payload).then( + return await fetch(`${config.tracking.endpoint}?${params}`, payload).then( response => DHLTracking2FulfillmentTracking(item, response), err => { - this.logger?.error(`${this.constructor.name}: ${err}`); + this.logger?.error(`${this.type}: ${err}`); return DHLTracking2FulfillmentTracking(item, null, err); } ); } catch (err) { - this.logger?.error(`${this.constructor.name}: ${err}`); + this.logger?.error(`${this.type}: ${err}`); return { ...item, status: { @@ -660,39 +743,6 @@ class DHLSoap extends Stub { return await Promise.all(promises); }; - protected override async cancelImpl (fulfillments: FlatAggregatedFulfillment[]): Promise { - if (fulfillments.length === 0) return []; - const fulfillment_map: { [k: string]: FlatAggregatedFulfillment } = {}; - fulfillments.forEach(a => fulfillment_map[a.label.shipment_number] = a); - const dhl_cancel_request = this.AggregatedFulfillment2DHLShipmentCancelRequest(fulfillments); - const client = await this.registerSoapClient(); - return await new Promise((resolve, reject: (v: FlatAggregatedFulfillment[]) => void): void => { - const timer = setTimeout(reject, 30000, this.operation_status_codes.TIMEOUT); - client.GVAPI_2_0_de.GKVAPISOAP11port0.deleteShipmentOrder(dhl_cancel_request, - (err: any, result: any): any => { - clearTimeout(timer); - try { - if (err) { - if (result?.html) { - this.logger?.error(`${this.constructor.name}: ${result.html.head.title}`); - reject(DHLShipmentCancelResponse2AggregatedFulfillment(fulfillment_map, null, result.html.head.title)); - } - else { - this.logger?.error(`${this.constructor.name}: ${err}`); - reject(DHLShipmentCancelResponse2AggregatedFulfillment(fulfillment_map, null, err)); - } - } - else { - resolve(DHLShipmentCancelResponse2AggregatedFulfillment(fulfillment_map, result)); - } - } - catch (e: any) { - reject(e); - } - }); - }); - }; - async getTariffCode(fulfillment: FlatAggregatedFulfillment): Promise { return fulfillment.recipient_country.country_code; } diff --git a/src/utils.ts b/src/utils.ts index 6171abf..f2b37eb 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -17,6 +17,10 @@ import { FulfillmentProductResponse, FulfillmentProductServiceImplementation, } from '@restorecommerce/rc-grpc-clients/dist/generated-server/io/restorecommerce/fulfillment_product.js'; +import { + Credential, + CredentialResponse, +} from '@restorecommerce/rc-grpc-clients/dist/generated-server/io/restorecommerce/credential.js'; import { UserServiceDefinition } from '@restorecommerce/rc-grpc-clients/dist/generated-server/io/restorecommerce/user.js'; @@ -104,6 +108,7 @@ export interface AggregatedFulfillment extends FulfillmentResponse { products: FulfillmentProductResponse[]; couriers: CourierResponse[]; + credentials: CredentialResponse[]; sender_country: CountryResponse; recipient_country: CountryResponse; options: any; @@ -114,6 +119,7 @@ export interface FlatAggregatedFulfillment extends FulfillmentResponse uuid: string; product: FulfillmentProduct; courier: Courier; + credential: Credential; sender_country: Country; recipient_country: Country; parcel: Parcel; @@ -192,8 +198,9 @@ export const flatMapAggregatedFulfillments = (fulfillments: AggregatedFulfillmen return fulfillments.flatMap((fulfillment) => { const uuid = randomUUID(); return fulfillment.payload?.packaging?.parcels.map((parcel, i): FlatAggregatedFulfillment => { - const product = fulfillment.products?.[i].payload; - const courier = fulfillment.couriers?.[i].payload; + const product = fulfillment.products?.[i]?.payload; + const courier = fulfillment.couriers?.[i]?.payload; + const credential = fulfillment.credentials?.[i]?.payload; const label = fulfillment.payload?.labels?.[i]; const tracking = fulfillment.payload?.trackings?.[i]; return { @@ -206,6 +213,7 @@ export const flatMapAggregatedFulfillments = (fulfillments: AggregatedFulfillmen recipient_country: fulfillment.recipient_country?.payload, product, courier, + credential, parcel, label, tracking, diff --git a/test/mocks.ts b/test/mocks.ts index 0ca434a..904821e 100644 --- a/test/mocks.ts +++ b/test/mocks.ts @@ -57,8 +57,8 @@ import { PaymentState } from '@restorecommerce/rc-grpc-clients/dist/generated/io/restorecommerce/invoice'; import { - DeepPartial -} from '@restorecommerce/rc-grpc-clients/dist/generated/io/restorecommerce/resource_base'; + CredentialListResponse +} from '@restorecommerce/rc-grpc-clients/dist/generated/io/restorecommerce/credential'; import { FulfillmentProductList, PackingSolutionQueryList @@ -1263,4 +1263,14 @@ export const rules = { operationStatus, }) }, + credential: { + read: ( + call: any, + callback: (error: any, response: CredentialListResponse) => void, + )=> callback(null, { + items: [], + totalCount: 0, + operationStatus + }), + }, }; \ No newline at end of file