@sabstravtech/obtservices 0.2.2606301620 → 0.2.2607131200
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/angular/lib/vendor/services/chatbot-taxi-search.service.d.ts +5 -1
- package/base/lib/vendor/classes/cabhire-enterprise-search.d.ts +9 -0
- package/base/lib/vendor/interfaces/Icabhire-enterprise-search.d.ts +4 -0
- package/base/lib/vendor/interfaces/chatbot.types.d.ts +16 -0
- package/fesm2022/sabstravtech-obtservices-angular.mjs +99 -25
- package/fesm2022/sabstravtech-obtservices-angular.mjs.map +1 -1
- package/fesm2022/sabstravtech-obtservices-base.mjs +7 -0
- package/fesm2022/sabstravtech-obtservices-base.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -2,18 +2,22 @@ import { ChatSearchParameters, ChatbotTravelHandler } from '@sabstravtech/obtser
|
|
|
2
2
|
import { ChatbotService } from './chatbot.service';
|
|
3
3
|
import { EnterpriseSearchService } from './search.service';
|
|
4
4
|
import { ResultAwareService } from './result-aware.service';
|
|
5
|
+
import { UserService } from './user.service';
|
|
5
6
|
import * as i0 from "@angular/core";
|
|
6
7
|
export declare class ChatbotTaxiSearchService implements ChatbotTravelHandler {
|
|
7
8
|
private chatbotService;
|
|
8
9
|
private searchService;
|
|
9
10
|
private resultAwareService;
|
|
11
|
+
private userService;
|
|
10
12
|
readonly travelType: "taxi";
|
|
11
|
-
constructor(chatbotService: ChatbotService, searchService: EnterpriseSearchService, resultAwareService: ResultAwareService);
|
|
13
|
+
constructor(chatbotService: ChatbotService, searchService: EnterpriseSearchService, resultAwareService: ResultAwareService, userService: UserService);
|
|
12
14
|
handle(parameters: ChatSearchParameters, autoSearch: boolean): Promise<void>;
|
|
13
15
|
private runSearch;
|
|
14
16
|
private buildTaxiCards;
|
|
15
17
|
private injectNoResultsMessage;
|
|
16
18
|
private populateTaxiParams;
|
|
19
|
+
private searchAndResolveGeoLocation;
|
|
20
|
+
private locationDataToResolved;
|
|
17
21
|
private resolveGeoLocation;
|
|
18
22
|
private matchTerminal;
|
|
19
23
|
static ɵfac: i0.ɵɵFactoryDeclaration<ChatbotTaxiSearchService, never>;
|
|
@@ -91,6 +91,15 @@ export declare class CabHireEnterpriseSearch<CH_Q extends CabhireQuoteFetcherTyp
|
|
|
91
91
|
key: string;
|
|
92
92
|
value: string;
|
|
93
93
|
}[]);
|
|
94
|
+
private _viaTerminals;
|
|
95
|
+
get viaTerminals(): {
|
|
96
|
+
key: string;
|
|
97
|
+
value: string;
|
|
98
|
+
}[];
|
|
99
|
+
set viaTerminals(value: {
|
|
100
|
+
key: string;
|
|
101
|
+
value: string;
|
|
102
|
+
}[]);
|
|
94
103
|
private _time;
|
|
95
104
|
get time(): string;
|
|
96
105
|
set time(value: string);
|
|
@@ -109,6 +109,10 @@ export interface CabHireEnterpriseSearchInterface extends BaseEnterpriseSearch<C
|
|
|
109
109
|
key: string;
|
|
110
110
|
value: string;
|
|
111
111
|
}[];
|
|
112
|
+
viaTerminals: {
|
|
113
|
+
key: string;
|
|
114
|
+
value: string;
|
|
115
|
+
}[];
|
|
112
116
|
time: string;
|
|
113
117
|
departs: moment.Moment;
|
|
114
118
|
adults: number;
|
|
@@ -153,11 +153,24 @@ export interface ChatSearchParameters {
|
|
|
153
153
|
timeFlexibility?: number;
|
|
154
154
|
refundableOnly?: boolean;
|
|
155
155
|
via?: string;
|
|
156
|
+
viaLocationData?: string;
|
|
157
|
+
viaFlightNumber?: string;
|
|
158
|
+
viaFlightTime?: string;
|
|
159
|
+
viaCarrier?: string;
|
|
156
160
|
vehicleType?: string;
|
|
157
161
|
pickupTerminal?: string;
|
|
158
162
|
pickupFlightNumber?: string;
|
|
163
|
+
pickupFlightTime?: string;
|
|
164
|
+
pickupCarrier?: string;
|
|
165
|
+
pickupLocationData?: string;
|
|
159
166
|
dropoffTerminal?: string;
|
|
160
167
|
dropoffFlightNumber?: string;
|
|
168
|
+
dropoffFlightTime?: string;
|
|
169
|
+
dropoffCarrier?: string;
|
|
170
|
+
dropoffLocationData?: string;
|
|
171
|
+
limoType?: string;
|
|
172
|
+
transportType?: string;
|
|
173
|
+
limoAsDirectedDuration?: number;
|
|
161
174
|
locationCode?: string;
|
|
162
175
|
flight?: string;
|
|
163
176
|
terminal?: string;
|
|
@@ -265,6 +278,9 @@ export interface ChatFlightFareTicket {
|
|
|
265
278
|
/** True when this fare belongs to a separately-priced inbound (dual-single)
|
|
266
279
|
* leg, so the Fare Rules lookup reads the inbound raw journeys array. */
|
|
267
280
|
isReturnLeg?: boolean;
|
|
281
|
+
/** True when this fare belongs to a multi-city itinerary, so the Fare Rules
|
|
282
|
+
* modal shows every leg's segment cards (matching the results page). */
|
|
283
|
+
isMultiCity?: boolean;
|
|
268
284
|
}
|
|
269
285
|
/** Flight fare breakdown for the expandable panel on a chat flight card. */
|
|
270
286
|
export interface ChatFlightFareBreakdown {
|
|
@@ -17680,8 +17680,9 @@ class ResultAwareService {
|
|
|
17680
17680
|
const searchParams = this.searchService.searches[ServiceType.Flight];
|
|
17681
17681
|
if (typeof searchParams?.openFlightFareRules !== 'function')
|
|
17682
17682
|
return;
|
|
17683
|
-
const
|
|
17684
|
-
const
|
|
17683
|
+
const isMultiCity = !!ticket.isMultiCity;
|
|
17684
|
+
const { rules, flights } = makeFareRules(journey, FlightDirectionEnum.Outbound, isMultiCity);
|
|
17685
|
+
const isReturn = !isMultiCity && (journey.inboundFlights?.length ?? 0) > 0;
|
|
17685
17686
|
let inboundRules = null;
|
|
17686
17687
|
let inboundFlights = null;
|
|
17687
17688
|
if (isReturn) {
|
|
@@ -17689,7 +17690,9 @@ class ResultAwareService {
|
|
|
17689
17690
|
inboundRules = inbound.rules;
|
|
17690
17691
|
inboundFlights = inbound.flights;
|
|
17691
17692
|
}
|
|
17692
|
-
|
|
17693
|
+
// Pass the whole itinerary as flightDetail so the modal renders every leg's
|
|
17694
|
+
// segment cards — matching the results page for both returns and multi-city.
|
|
17695
|
+
const flightDetail = isMultiCity || isReturn ? journey : null;
|
|
17693
17696
|
searchParams.openFlightFareRules(rules, flights, journey.sourceId, { centered: true, size: 'xl' }, null, flightDetail, inboundRules, inboundFlights);
|
|
17694
17697
|
}
|
|
17695
17698
|
collectFareTickets(journey, sections, journeyIndex, isReturnLeg) {
|
|
@@ -19477,7 +19480,7 @@ class ChatbotFlightSearchService {
|
|
|
19477
19480
|
* For combined-return journeys the key includes both outbound + inbound
|
|
19478
19481
|
* flight numbers; for dual-single legs it's just that leg's numbers.
|
|
19479
19482
|
*/
|
|
19480
|
-
indexFaresByFlights(raw, includeInbound, isReturnLeg = false) {
|
|
19483
|
+
indexFaresByFlights(raw, includeInbound, isReturnLeg = false, isMultiCity = false) {
|
|
19481
19484
|
const map = new Map();
|
|
19482
19485
|
if (!raw?.length)
|
|
19483
19486
|
return map;
|
|
@@ -19485,7 +19488,7 @@ class ChatbotFlightSearchService {
|
|
|
19485
19488
|
const key = this.flightSignature(it, includeInbound);
|
|
19486
19489
|
if (!key)
|
|
19487
19490
|
return;
|
|
19488
|
-
const fare = this.toFareTicket(it, idx, isReturnLeg);
|
|
19491
|
+
const fare = this.toFareTicket(it, idx, isReturnLeg, isMultiCity);
|
|
19489
19492
|
if (!fare)
|
|
19490
19493
|
return;
|
|
19491
19494
|
const arr = map.get(key) ?? [];
|
|
@@ -19518,7 +19521,7 @@ class ChatbotFlightSearchService {
|
|
|
19518
19521
|
.join('/');
|
|
19519
19522
|
return `${out}|${inn}`;
|
|
19520
19523
|
}
|
|
19521
|
-
toFareTicket(it, idx, isReturnLeg = false) {
|
|
19524
|
+
toFareTicket(it, idx, isReturnLeg = false, isMultiCity = false) {
|
|
19522
19525
|
const price = it?.total?.price;
|
|
19523
19526
|
if (!(price > 0))
|
|
19524
19527
|
return null;
|
|
@@ -19541,7 +19544,8 @@ class ChatbotFlightSearchService {
|
|
|
19541
19544
|
price,
|
|
19542
19545
|
currency: it?.total?.currency || 'GBP',
|
|
19543
19546
|
journeyIndex: idx,
|
|
19544
|
-
isReturnLeg: isReturnLeg || undefined
|
|
19547
|
+
isReturnLeg: isReturnLeg || undefined,
|
|
19548
|
+
isMultiCity: isMultiCity || undefined
|
|
19545
19549
|
};
|
|
19546
19550
|
}
|
|
19547
19551
|
/**
|
|
@@ -19583,7 +19587,7 @@ class ChatbotFlightSearchService {
|
|
|
19583
19587
|
}
|
|
19584
19588
|
}
|
|
19585
19589
|
const sorted = [...bySig.values()];
|
|
19586
|
-
const fareIndex = this.indexFaresByFlights(journeys, false, false);
|
|
19590
|
+
const fareIndex = this.indexFaresByFlights(journeys, false, false, true);
|
|
19587
19591
|
const cards = [];
|
|
19588
19592
|
for (let i = 0; i < Math.min(MAX_FLIGHT_CARDS, sorted.length); i++) {
|
|
19589
19593
|
const journey = sorted[i];
|
|
@@ -21505,11 +21509,13 @@ class ChatbotTaxiSearchService {
|
|
|
21505
21509
|
chatbotService;
|
|
21506
21510
|
searchService;
|
|
21507
21511
|
resultAwareService;
|
|
21512
|
+
userService;
|
|
21508
21513
|
travelType = 'taxi';
|
|
21509
|
-
constructor(chatbotService, searchService, resultAwareService) {
|
|
21514
|
+
constructor(chatbotService, searchService, resultAwareService, userService) {
|
|
21510
21515
|
this.chatbotService = chatbotService;
|
|
21511
21516
|
this.searchService = searchService;
|
|
21512
21517
|
this.resultAwareService = resultAwareService;
|
|
21518
|
+
this.userService = userService;
|
|
21513
21519
|
}
|
|
21514
21520
|
async handle(parameters, autoSearch) {
|
|
21515
21521
|
this.searchService.resetSearchChosenObjects();
|
|
@@ -21520,6 +21526,12 @@ class ChatbotTaxiSearchService {
|
|
|
21520
21526
|
if (autoSearch) {
|
|
21521
21527
|
this.chatbotService.setSearching(true, 'taxi');
|
|
21522
21528
|
}
|
|
21529
|
+
if (this.searchService.travellerInformation.value.length === 0) {
|
|
21530
|
+
const selfTraveller = this.userService.createSelfTraveller();
|
|
21531
|
+
if (selfTraveller) {
|
|
21532
|
+
this.searchService.addTraveller(selfTraveller);
|
|
21533
|
+
}
|
|
21534
|
+
}
|
|
21523
21535
|
await this.populateTaxiParams(parameters);
|
|
21524
21536
|
if (!autoSearch) {
|
|
21525
21537
|
return;
|
|
@@ -21618,11 +21630,34 @@ class ChatbotTaxiSearchService {
|
|
|
21618
21630
|
if (parameters.vehicleType) {
|
|
21619
21631
|
taxiSearch.vehicleType = parameters.vehicleType;
|
|
21620
21632
|
}
|
|
21633
|
+
else {
|
|
21634
|
+
taxiSearch.vehicleType = CabHireVehicleType.Any;
|
|
21635
|
+
}
|
|
21636
|
+
if (parameters.limoType) {
|
|
21637
|
+
taxiSearch.limoType = parameters.limoType;
|
|
21638
|
+
}
|
|
21639
|
+
if (parameters.transportType) {
|
|
21640
|
+
taxiSearch.transportType = parameters.transportType;
|
|
21641
|
+
}
|
|
21642
|
+
if (parameters.limoAsDirectedDuration) {
|
|
21643
|
+
taxiSearch.limoAsDirectedDuration = parameters.limoAsDirectedDuration;
|
|
21644
|
+
}
|
|
21621
21645
|
const [fromResolved, toResolved, viaResolved] = await Promise.all([
|
|
21622
|
-
|
|
21623
|
-
|
|
21624
|
-
|
|
21646
|
+
parameters.pickupLocationData
|
|
21647
|
+
? this.locationDataToResolved(parameters.pickupLocationData, taxiSearch)
|
|
21648
|
+
: this.searchAndResolveGeoLocation(parameters.departure, taxiSearch),
|
|
21649
|
+
parameters.dropoffLocationData
|
|
21650
|
+
? this.locationDataToResolved(parameters.dropoffLocationData, taxiSearch)
|
|
21651
|
+
: this.searchAndResolveGeoLocation(parameters.arrival, taxiSearch),
|
|
21652
|
+
parameters.viaLocationData
|
|
21653
|
+
? this.locationDataToResolved(parameters.viaLocationData, taxiSearch)
|
|
21654
|
+
: parameters.via ? this.searchAndResolveGeoLocation(parameters.via, taxiSearch) : Promise.resolve(null),
|
|
21625
21655
|
]);
|
|
21656
|
+
// Clear via if this search has no stop
|
|
21657
|
+
if (!parameters.via && !parameters.viaLocationData) {
|
|
21658
|
+
taxiSearch.viasTo = null;
|
|
21659
|
+
taxiSearch.viaTerminals = [];
|
|
21660
|
+
}
|
|
21626
21661
|
if (fromResolved) {
|
|
21627
21662
|
const { result, address } = fromResolved;
|
|
21628
21663
|
if (result.terminals?.length) {
|
|
@@ -21634,6 +21669,12 @@ class ChatbotTaxiSearchService {
|
|
|
21634
21669
|
if (parameters.pickupFlightNumber) {
|
|
21635
21670
|
address.FlightNumber = parameters.pickupFlightNumber;
|
|
21636
21671
|
}
|
|
21672
|
+
if (parameters.pickupCarrier) {
|
|
21673
|
+
address.Carrier = parameters.pickupCarrier;
|
|
21674
|
+
}
|
|
21675
|
+
if (parameters.pickupFlightTime) {
|
|
21676
|
+
address.FlightTrainDateTime = parameters.pickupFlightTime;
|
|
21677
|
+
}
|
|
21637
21678
|
taxiSearch.fromAddress = address;
|
|
21638
21679
|
}
|
|
21639
21680
|
if (toResolved) {
|
|
@@ -21647,37 +21688,70 @@ class ChatbotTaxiSearchService {
|
|
|
21647
21688
|
if (parameters.dropoffFlightNumber) {
|
|
21648
21689
|
address.FlightNumber = parameters.dropoffFlightNumber;
|
|
21649
21690
|
}
|
|
21691
|
+
if (parameters.dropoffCarrier) {
|
|
21692
|
+
address.Carrier = parameters.dropoffCarrier;
|
|
21693
|
+
}
|
|
21694
|
+
if (parameters.dropoffFlightTime) {
|
|
21695
|
+
address.FlightTrainDateTime = parameters.dropoffFlightTime;
|
|
21696
|
+
}
|
|
21650
21697
|
taxiSearch.toAddress = address;
|
|
21651
21698
|
}
|
|
21652
21699
|
if (viaResolved) {
|
|
21653
|
-
|
|
21700
|
+
const { result, address } = viaResolved;
|
|
21701
|
+
if (result.terminals?.length) {
|
|
21702
|
+
taxiSearch.viaTerminals = result.terminals;
|
|
21703
|
+
}
|
|
21704
|
+
if (parameters.viaFlightNumber)
|
|
21705
|
+
address.FlightNumber = parameters.viaFlightNumber;
|
|
21706
|
+
if (parameters.viaCarrier)
|
|
21707
|
+
address.Carrier = parameters.viaCarrier;
|
|
21708
|
+
if (parameters.viaFlightTime)
|
|
21709
|
+
address.FlightTrainDateTime = parameters.viaFlightTime;
|
|
21710
|
+
taxiSearch.viasTo = address;
|
|
21654
21711
|
}
|
|
21655
21712
|
}
|
|
21656
|
-
async
|
|
21713
|
+
async searchAndResolveGeoLocation(searchTerm, taxiSearch) {
|
|
21657
21714
|
if (!searchTerm)
|
|
21658
21715
|
return null;
|
|
21659
21716
|
try {
|
|
21660
21717
|
const results = await firstValueFrom(this.searchService.getGeoLocations(searchTerm));
|
|
21661
21718
|
if (results?.length) {
|
|
21662
|
-
const term = searchTerm.toLowerCase();
|
|
21719
|
+
const term = searchTerm.toLowerCase().trim();
|
|
21720
|
+
const isIataCode = /^[a-z]{3}$/.test(term);
|
|
21663
21721
|
let location = results[0];
|
|
21664
|
-
if (term.includes('airport')) {
|
|
21665
|
-
location = results.find((r) => r.type ===
|
|
21722
|
+
if (term.includes('airport') || isIataCode) {
|
|
21723
|
+
location = results.find((r) => r.type === LocationTypes.Airport) ?? results[0];
|
|
21666
21724
|
}
|
|
21667
21725
|
else if (term.includes('station') || term.includes('rail')) {
|
|
21668
|
-
location = results.find((r) => r.type ===
|
|
21669
|
-
}
|
|
21670
|
-
const address = taxiSearch.getAddress(location);
|
|
21671
|
-
if (location.type === 'Airport' && !address?.Town) {
|
|
21672
|
-
address.Town = location.name;
|
|
21726
|
+
location = results.find((r) => r.type === LocationTypes.TrainStation) ?? results[0];
|
|
21673
21727
|
}
|
|
21674
|
-
return
|
|
21728
|
+
return this.resolveGeoLocation(location, taxiSearch);
|
|
21675
21729
|
}
|
|
21676
21730
|
}
|
|
21677
21731
|
catch {
|
|
21678
21732
|
}
|
|
21679
21733
|
return null;
|
|
21680
21734
|
}
|
|
21735
|
+
locationDataToResolved(locationDataJson, taxiSearch) {
|
|
21736
|
+
try {
|
|
21737
|
+
const location = JSON.parse(locationDataJson);
|
|
21738
|
+
// terminals from GetGeoLocationResult are raw string[] — process same as _getGeoLocations does
|
|
21739
|
+
if (Array.isArray(location.terminals)) {
|
|
21740
|
+
location.terminals = this.searchService.processTerminals(location.terminals);
|
|
21741
|
+
}
|
|
21742
|
+
return Promise.resolve(this.resolveGeoLocation(location, taxiSearch));
|
|
21743
|
+
}
|
|
21744
|
+
catch {
|
|
21745
|
+
return Promise.resolve(null);
|
|
21746
|
+
}
|
|
21747
|
+
}
|
|
21748
|
+
resolveGeoLocation(location, taxiSearch) {
|
|
21749
|
+
const address = taxiSearch.getAddress(location);
|
|
21750
|
+
if (location.type === LocationTypes.Airport && !address?.Town) {
|
|
21751
|
+
address.Town = location.name;
|
|
21752
|
+
}
|
|
21753
|
+
return { result: location, address };
|
|
21754
|
+
}
|
|
21681
21755
|
matchTerminal(aiTerminal, terminals) {
|
|
21682
21756
|
const t = aiTerminal.toLowerCase().trim();
|
|
21683
21757
|
if (!t || t.includes('any') || t.includes('main'))
|
|
@@ -21688,13 +21762,13 @@ class ChatbotTaxiSearchService {
|
|
|
21688
21762
|
const byKey = terminals.find((x) => x.key.toLowerCase().includes(t) || t.includes(x.value.toLowerCase()));
|
|
21689
21763
|
return byKey ? byKey.key : null;
|
|
21690
21764
|
}
|
|
21691
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: ChatbotTaxiSearchService, deps: [{ token: ChatbotService }, { token: EnterpriseSearchService }, { token: ResultAwareService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
21765
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: ChatbotTaxiSearchService, deps: [{ token: ChatbotService }, { token: EnterpriseSearchService }, { token: ResultAwareService }, { token: UserService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
21692
21766
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: ChatbotTaxiSearchService, providedIn: 'root' });
|
|
21693
21767
|
}
|
|
21694
21768
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: ChatbotTaxiSearchService, decorators: [{
|
|
21695
21769
|
type: Injectable,
|
|
21696
21770
|
args: [{ providedIn: 'root' }]
|
|
21697
|
-
}], ctorParameters: () => [{ type: ChatbotService }, { type: EnterpriseSearchService }, { type: ResultAwareService }] });
|
|
21771
|
+
}], ctorParameters: () => [{ type: ChatbotService }, { type: EnterpriseSearchService }, { type: ResultAwareService }, { type: UserService }] });
|
|
21698
21772
|
|
|
21699
21773
|
/** Safety timeout (ms) waiting for eurostar results. */
|
|
21700
21774
|
const EUROSTAR_RESULTS_WAIT_MS = 60_000;
|