@pisell/pisellos 2.2.291 → 2.2.293

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.
Files changed (174) hide show
  1. package/dist/core/index.d.ts +7 -0
  2. package/dist/core/index.js +108 -65
  3. package/dist/model/strategy/adapter/itemRule/adapter.d.ts +4 -1
  4. package/dist/model/strategy/adapter/itemRule/adapter.js +135 -35
  5. package/dist/model/strategy/adapter/itemRule/evaluator.d.ts +8 -1
  6. package/dist/model/strategy/adapter/itemRule/evaluator.js +25 -1
  7. package/dist/model/strategy/adapter/itemRule/type.d.ts +44 -0
  8. package/dist/model/strategy/adapter/itemRule/type.js +19 -1
  9. package/dist/model/strategy/adapter/promotion/index.js +0 -9
  10. package/dist/modules/BookingContext/index.d.ts +3 -0
  11. package/dist/modules/BookingContext/index.js +42 -13
  12. package/dist/modules/BookingContext/types.d.ts +4 -4
  13. package/dist/modules/BookingContext/types.js +3 -3
  14. package/dist/modules/OpenData/types.d.ts +1 -0
  15. package/dist/modules/Order/index.d.ts +18 -3
  16. package/dist/modules/Order/index.js +885 -485
  17. package/dist/modules/Order/salesNotes.d.ts +31 -0
  18. package/dist/modules/Order/salesNotes.js +492 -0
  19. package/dist/modules/Order/types.d.ts +93 -5
  20. package/dist/modules/Order/types.js +5 -0
  21. package/dist/modules/Order/utils.d.ts +12 -0
  22. package/dist/modules/Order/utils.js +96 -31
  23. package/dist/modules/Product/types.d.ts +2 -0
  24. package/dist/modules/ProductList/clientDataVariants.d.ts +50 -0
  25. package/dist/modules/ProductList/clientDataVariants.js +216 -0
  26. package/dist/modules/ProductList/index.d.ts +18 -3
  27. package/dist/modules/ProductList/index.js +220 -38
  28. package/dist/modules/ProductList/types.d.ts +10 -0
  29. package/dist/modules/Quotation/index.d.ts +22 -0
  30. package/dist/modules/Quotation/index.js +293 -28
  31. package/dist/modules/ResourcePlanner/index.d.ts +0 -22
  32. package/dist/modules/ResourcePlanner/index.js +1 -180
  33. package/dist/modules/ResourcePlanner/localClock.d.ts +33 -0
  34. package/dist/modules/ResourcePlanner/localClock.js +183 -0
  35. package/dist/modules/ResourcePlanner/planner.d.ts +5 -14
  36. package/dist/modules/ResourcePlanner/planner.js +2111 -958
  37. package/dist/modules/ResourcePlanner/types.d.ts +359 -187
  38. package/dist/modules/ResourcePlanner/types.js +33 -1
  39. package/dist/plugins/request.d.ts +1 -0
  40. package/dist/server/index.d.ts +17 -2
  41. package/dist/server/index.js +1134 -932
  42. package/dist/server/modules/floor-plan/index.d.ts +4 -0
  43. package/dist/server/modules/floor-plan/index.js +240 -98
  44. package/dist/server/modules/menu/index.js +48 -23
  45. package/dist/server/modules/order/index.d.ts +17 -7
  46. package/dist/server/modules/order/index.js +419 -207
  47. package/dist/server/modules/products/index.d.ts +10 -4
  48. package/dist/server/modules/products/index.js +177 -84
  49. package/dist/server/modules/resource/index.js +21 -13
  50. package/dist/server/utils/product.d.ts +1 -1
  51. package/dist/server/utils/product.js +186 -22
  52. package/dist/server/utils/small-ticket.d.ts +9 -1
  53. package/dist/server/utils/small-ticket.js +131 -84
  54. package/dist/solution/BaseSales/index.d.ts +26 -3
  55. package/dist/solution/BaseSales/index.js +1384 -905
  56. package/dist/solution/BaseSales/types.d.ts +2 -0
  57. package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +3 -0
  58. package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +10 -3
  59. package/dist/solution/BaseSales/utils.js +6 -3
  60. package/dist/solution/BookingByStep/index.d.ts +4 -4
  61. package/dist/solution/BookingTicket/index.d.ts +1 -1
  62. package/dist/solution/BookingTicket/index.js +4 -2
  63. package/dist/solution/BookingTicket/utils/addProductDecision.d.ts +2 -1
  64. package/dist/solution/BookingTicket/utils/addProductDecision.js +6 -3
  65. package/dist/solution/BookingTicket/utils/orderCustomer.js +3 -2
  66. package/dist/solution/RegisterAndLogin/config.d.ts +9 -3
  67. package/dist/solution/RegisterAndLogin/config.js +95 -40
  68. package/dist/solution/RegisterAndLogin/index.js +4 -1
  69. package/dist/solution/ScanOrder/index.d.ts +1 -0
  70. package/dist/solution/ScanOrder/index.js +31 -27
  71. package/dist/solution/ScanOrder/types.d.ts +2 -0
  72. package/dist/solution/ScanOrder/utils.d.ts +1 -0
  73. package/dist/solution/ScanOrder/utils.js +8 -3
  74. package/dist/solution/UnifiedBookingSales/index.d.ts +128 -74
  75. package/dist/solution/UnifiedBookingSales/index.js +3877 -963
  76. package/dist/solution/UnifiedBookingSales/remoteOccupancyCache.d.ts +49 -0
  77. package/dist/solution/UnifiedBookingSales/remoteOccupancyCache.js +430 -0
  78. package/dist/solution/UnifiedBookingSales/types.d.ts +161 -77
  79. package/dist/solution/UnifiedBookingSales/types.js +4 -9
  80. package/dist/solution/VenueBooking/index.d.ts +3 -0
  81. package/dist/solution/VenueBooking/index.js +549 -497
  82. package/dist/solution/VenueBooking/utils/dateSummary.d.ts +1 -0
  83. package/dist/solution/VenueBooking/utils/dateSummary.js +3 -1
  84. package/dist/solution/VenueBooking/utils/slotMerge.d.ts +2 -0
  85. package/dist/solution/VenueBooking/utils/slotMerge.js +3 -1
  86. package/dist/utils/platform.d.ts +8 -0
  87. package/dist/utils/platform.js +15 -0
  88. package/lib/core/index.d.ts +7 -0
  89. package/lib/core/index.js +20 -2
  90. package/lib/model/strategy/adapter/itemRule/adapter.d.ts +4 -1
  91. package/lib/model/strategy/adapter/itemRule/adapter.js +73 -4
  92. package/lib/model/strategy/adapter/itemRule/evaluator.d.ts +8 -1
  93. package/lib/model/strategy/adapter/itemRule/evaluator.js +23 -1
  94. package/lib/model/strategy/adapter/itemRule/type.d.ts +44 -0
  95. package/lib/model/strategy/adapter/itemRule/type.js +19 -1
  96. package/lib/modules/BookingContext/index.d.ts +3 -0
  97. package/lib/modules/BookingContext/index.js +35 -8
  98. package/lib/modules/BookingContext/types.d.ts +4 -4
  99. package/lib/modules/BookingContext/types.js +3 -3
  100. package/lib/modules/OpenData/types.d.ts +1 -0
  101. package/lib/modules/Order/index.d.ts +18 -3
  102. package/lib/modules/Order/index.js +325 -28
  103. package/lib/modules/Order/salesNotes.d.ts +31 -0
  104. package/lib/modules/Order/salesNotes.js +382 -0
  105. package/lib/modules/Order/types.d.ts +93 -5
  106. package/lib/modules/Order/types.js +4 -0
  107. package/lib/modules/Order/utils.d.ts +12 -0
  108. package/lib/modules/Order/utils.js +85 -16
  109. package/lib/modules/Product/types.d.ts +2 -0
  110. package/lib/modules/ProductList/clientDataVariants.d.ts +50 -0
  111. package/lib/modules/ProductList/clientDataVariants.js +204 -0
  112. package/lib/modules/ProductList/index.d.ts +18 -3
  113. package/lib/modules/ProductList/index.js +137 -8
  114. package/lib/modules/ProductList/types.d.ts +10 -0
  115. package/lib/modules/Quotation/index.d.ts +22 -0
  116. package/lib/modules/Quotation/index.js +158 -11
  117. package/lib/modules/ResourcePlanner/index.d.ts +0 -22
  118. package/lib/modules/ResourcePlanner/index.js +9 -129
  119. package/lib/modules/ResourcePlanner/localClock.d.ts +33 -0
  120. package/lib/modules/ResourcePlanner/localClock.js +205 -0
  121. package/lib/modules/ResourcePlanner/planner.d.ts +5 -14
  122. package/lib/modules/ResourcePlanner/planner.js +1807 -783
  123. package/lib/modules/ResourcePlanner/types.d.ts +359 -187
  124. package/lib/modules/ResourcePlanner/types.js +13 -1
  125. package/lib/plugins/request.d.ts +1 -0
  126. package/lib/server/index.d.ts +17 -2
  127. package/lib/server/index.js +149 -21
  128. package/lib/server/modules/floor-plan/index.d.ts +4 -0
  129. package/lib/server/modules/floor-plan/index.js +60 -7
  130. package/lib/server/modules/menu/index.js +26 -4
  131. package/lib/server/modules/order/index.d.ts +17 -7
  132. package/lib/server/modules/order/index.js +194 -57
  133. package/lib/server/modules/products/index.d.ts +10 -4
  134. package/lib/server/modules/products/index.js +93 -23
  135. package/lib/server/modules/resource/index.js +12 -2
  136. package/lib/server/utils/product.d.ts +1 -1
  137. package/lib/server/utils/product.js +163 -3
  138. package/lib/server/utils/small-ticket.d.ts +9 -1
  139. package/lib/server/utils/small-ticket.js +123 -79
  140. package/lib/solution/BaseSales/index.d.ts +26 -3
  141. package/lib/solution/BaseSales/index.js +396 -70
  142. package/lib/solution/BaseSales/types.d.ts +2 -0
  143. package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +3 -0
  144. package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +9 -2
  145. package/lib/solution/BaseSales/utils.js +3 -0
  146. package/lib/solution/BookingByStep/index.d.ts +4 -4
  147. package/lib/solution/BookingTicket/index.d.ts +1 -1
  148. package/lib/solution/BookingTicket/index.js +2 -1
  149. package/lib/solution/BookingTicket/utils/addProductDecision.d.ts +2 -1
  150. package/lib/solution/BookingTicket/utils/addProductDecision.js +5 -2
  151. package/lib/solution/BookingTicket/utils/orderCustomer.js +2 -1
  152. package/lib/solution/RegisterAndLogin/config.d.ts +9 -3
  153. package/lib/solution/RegisterAndLogin/config.js +49 -8
  154. package/lib/solution/RegisterAndLogin/index.js +4 -1
  155. package/lib/solution/ScanOrder/index.d.ts +1 -0
  156. package/lib/solution/ScanOrder/index.js +5 -1
  157. package/lib/solution/ScanOrder/types.d.ts +2 -0
  158. package/lib/solution/ScanOrder/utils.d.ts +1 -0
  159. package/lib/solution/ScanOrder/utils.js +4 -0
  160. package/lib/solution/UnifiedBookingSales/index.d.ts +128 -74
  161. package/lib/solution/UnifiedBookingSales/index.js +2592 -424
  162. package/lib/solution/UnifiedBookingSales/remoteOccupancyCache.d.ts +49 -0
  163. package/lib/solution/UnifiedBookingSales/remoteOccupancyCache.js +316 -0
  164. package/lib/solution/UnifiedBookingSales/types.d.ts +161 -77
  165. package/lib/solution/UnifiedBookingSales/types.js +4 -6
  166. package/lib/solution/VenueBooking/index.d.ts +3 -0
  167. package/lib/solution/VenueBooking/index.js +33 -9
  168. package/lib/solution/VenueBooking/utils/dateSummary.d.ts +1 -0
  169. package/lib/solution/VenueBooking/utils/dateSummary.js +3 -1
  170. package/lib/solution/VenueBooking/utils/slotMerge.d.ts +2 -0
  171. package/lib/solution/VenueBooking/utils/slotMerge.js +3 -1
  172. package/lib/utils/platform.d.ts +8 -0
  173. package/lib/utils/platform.js +22 -0
  174. package/package.json +1 -1
@@ -0,0 +1,49 @@
1
+ import type { AvailabilityDateRange } from '../../modules/ResourcePlanner';
2
+ type AvailabilityId = number | string;
3
+ export declare class AvailabilityRemoteOccupancyCache {
4
+ private readonly maxCells;
5
+ private readonly cells;
6
+ private readonly resourceMeta;
7
+ private readonly resourceCellCounts;
8
+ constructor(maxCells?: number);
9
+ clear(): void;
10
+ read(params: {
11
+ scopeKey: string;
12
+ resourceIds: AvailabilityId[];
13
+ dateRange: AvailabilityDateRange;
14
+ }): Record<string, any>[] | null;
15
+ hasCompleteCoverage(params: {
16
+ scopeKey: string;
17
+ resourceIds: AvailabilityId[];
18
+ dateRange: AvailabilityDateRange;
19
+ }): boolean;
20
+ publish(params: {
21
+ scopeKey: string;
22
+ timezoneName: string;
23
+ resourceIds: AvailabilityId[];
24
+ dateRange: AvailabilityDateRange;
25
+ rawResources: Record<string, any>[];
26
+ version: number;
27
+ }): void;
28
+ private buildResourceKey;
29
+ private buildCellKey;
30
+ private touchCell;
31
+ /**
32
+ * A response is one coherent resource snapshot for its requested range. If any overlapping day
33
+ * already contains a newer response, publishing only the older response's remaining days would
34
+ * let a cross-midnight event leak back into that newer day when ranges are recomposed.
35
+ */
36
+ private canPublishResourceRange;
37
+ /**
38
+ * A day cell stores the original event range so it can be reconstructed without losing server
39
+ * identity. When a newer adjacent-day response replaces that event, evict older neighbour cells
40
+ * whose event overlaps the refreshed range. The next wider read becomes a cache miss instead of
41
+ * reintroducing stale occupancy from the neighbour.
42
+ */
43
+ private invalidateAdjacentOverlappingCells;
44
+ private deleteCell;
45
+ private deleteResourceCells;
46
+ private writeResourceMeta;
47
+ private writeCell;
48
+ }
49
+ export {};
@@ -0,0 +1,316 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.AvailabilityRemoteOccupancyCache = void 0;
7
+ var _lodashEs = require("lodash-es");
8
+ var _localClock = require("../../modules/ResourcePlanner/localClock");
9
+ function uniqueIds(values) {
10
+ const result = new Map();
11
+ values.forEach(value => {
12
+ if (value === undefined || value === null || value === '') return;
13
+ result.set(String(value), value);
14
+ });
15
+ return Array.from(result.values());
16
+ }
17
+ function buildDateList(dateRange) {
18
+ if (!dateRange?.startDate || !dateRange?.endDate) return [];
19
+ try {
20
+ const startOrdinal = (0, _localClock.dateOrdinalFromLocalDate)(dateRange.startDate);
21
+ const endOrdinal = (0, _localClock.dateOrdinalFromLocalDate)(dateRange.endDate);
22
+ if (endOrdinal < startOrdinal) return [];
23
+ const dates = [];
24
+ let cursor = (0, _localClock.localDateToScalarStart)(dateRange.startDate);
25
+ for (let ordinal = startOrdinal; ordinal <= endOrdinal; ordinal += 1) {
26
+ dates.push((0, _localClock.formatLocalDate)(cursor));
27
+ cursor = (0, _localClock.addLocalCalendarDays)(cursor, 1);
28
+ }
29
+ return dates;
30
+ } catch {
31
+ return [];
32
+ }
33
+ }
34
+ function resolveResourceId(raw) {
35
+ const id = raw.resourceId ?? raw.resource_id ?? raw.id;
36
+ if (id === undefined || id === null || id === '') return null;
37
+ return id;
38
+ }
39
+ function getRawEventStartAt(rawEvent) {
40
+ const startAt = rawEvent.start_at ?? rawEvent.startAt ?? rawEvent.start_time ?? rawEvent.startTime;
41
+ return startAt ? String(startAt) : null;
42
+ }
43
+ function getRawEventEndAt(rawEvent) {
44
+ const endAt = rawEvent.end_at ?? rawEvent.endAt ?? rawEvent.end_time ?? rawEvent.endTime;
45
+ return endAt ? String(endAt) : null;
46
+ }
47
+ function parseEventScalar(value) {
48
+ return (0, _localClock.localDateTimeToScalar)((0, _localClock.parseLocalDateTime)(value));
49
+ }
50
+ function buildEventIdentity(resourceId, rawEvent) {
51
+ const scheduleEventId = rawEvent.schedule_event_id ?? rawEvent.scheduleEventId;
52
+ if (scheduleEventId !== undefined && scheduleEventId !== null && scheduleEventId !== '') {
53
+ return `scheduleEvent:${String(resourceId)}:${String(scheduleEventId)}`;
54
+ }
55
+ const bookingUid = rawEvent.booking_uid ?? rawEvent.bookingUid ?? rawEvent.metadata?.unique_identification_number;
56
+ if (bookingUid !== undefined && bookingUid !== null && bookingUid !== '') {
57
+ return `bookingUid:${String(resourceId)}:${String(bookingUid)}`;
58
+ }
59
+ const productUid = rawEvent.product_uid ?? rawEvent.productUid ?? rawEvent.metadata?.product_uid;
60
+ if (productUid !== undefined && productUid !== null && productUid !== '') {
61
+ return `productUid:${String(resourceId)}:${String(productUid)}`;
62
+ }
63
+ return ['range', String(resourceId), getRawEventStartAt(rawEvent) || '', getRawEventEndAt(rawEvent) || ''].join(':');
64
+ }
65
+ function bucketEventDates(params) {
66
+ const startAt = getRawEventStartAt(params.rawEvent);
67
+ const endAt = getRawEventEndAt(params.rawEvent);
68
+ if (!startAt || !endAt) return [];
69
+ try {
70
+ const startScalar = parseEventScalar(startAt);
71
+ const endScalar = parseEventScalar(endAt);
72
+ if (endScalar <= startScalar) return [];
73
+ const endInclusiveScalar = endScalar - 1000;
74
+ const startDate = (0, _localClock.formatLocalDate)(startScalar);
75
+ const endDate = (0, _localClock.formatLocalDate)(endInclusiveScalar);
76
+ const startOrdinal = (0, _localClock.dateOrdinalFromLocalDate)(startDate);
77
+ const endOrdinal = (0, _localClock.dateOrdinalFromLocalDate)(endDate);
78
+ if (endOrdinal < startOrdinal) return [];
79
+ const dates = [];
80
+ let cursorDate = startDate;
81
+ for (let ordinal = startOrdinal; ordinal <= endOrdinal; ordinal += 1) {
82
+ if (params.requestedDates.has(cursorDate)) {
83
+ dates.push(cursorDate);
84
+ }
85
+ cursorDate = (0, _localClock.nextDate)(cursorDate);
86
+ }
87
+ return dates;
88
+ } catch {
89
+ return [];
90
+ }
91
+ }
92
+ function sortEventList(events) {
93
+ return [...events].sort((left, right) => {
94
+ const leftStart = getRawEventStartAt(left) || '';
95
+ const rightStart = getRawEventStartAt(right) || '';
96
+ if (leftStart !== rightStart) return leftStart.localeCompare(rightStart);
97
+ const leftEnd = getRawEventEndAt(left) || '';
98
+ const rightEnd = getRawEventEndAt(right) || '';
99
+ if (leftEnd !== rightEnd) return leftEnd.localeCompare(rightEnd);
100
+ return buildEventIdentity(left.resource_id ?? left.resourceId ?? '', left).localeCompare(buildEventIdentity(right.resource_id ?? right.resourceId ?? '', right));
101
+ });
102
+ }
103
+ class AvailabilityRemoteOccupancyCache {
104
+ maxCells;
105
+ cells = new Map();
106
+ resourceMeta = new Map();
107
+ resourceCellCounts = new Map();
108
+ constructor(maxCells = 4096) {
109
+ this.maxCells = maxCells;
110
+ }
111
+ clear() {
112
+ this.cells.clear();
113
+ this.resourceMeta.clear();
114
+ this.resourceCellCounts.clear();
115
+ }
116
+ read(params) {
117
+ const requestedResourceIds = uniqueIds(params.resourceIds);
118
+ const requestedDates = buildDateList(params.dateRange);
119
+ if (requestedResourceIds.length === 0 || requestedDates.length === 0) return [];
120
+ const resources = [];
121
+ for (const resourceId of requestedResourceIds) {
122
+ const resourceKey = this.buildResourceKey(params.scopeKey, resourceId);
123
+ const eventList = new Map();
124
+ for (const date of requestedDates) {
125
+ const cellKey = this.buildCellKey(resourceKey, date);
126
+ const cell = this.touchCell(cellKey);
127
+ if (!cell) return null;
128
+ cell.eventList.forEach(rawEvent => {
129
+ eventList.set(buildEventIdentity(resourceId, rawEvent), (0, _lodashEs.cloneDeep)(rawEvent));
130
+ });
131
+ }
132
+ const metadataEntry = this.resourceMeta.get(resourceKey);
133
+ if (!metadataEntry) return null;
134
+ if (metadataEntry.status === 'absent') continue;
135
+ if (!metadataEntry.metadata) return null;
136
+ resources.push({
137
+ ...(0, _lodashEs.cloneDeep)(metadataEntry.metadata),
138
+ event_list: sortEventList(Array.from(eventList.values()))
139
+ });
140
+ }
141
+ return resources;
142
+ }
143
+ hasCompleteCoverage(params) {
144
+ const requestedResourceIds = uniqueIds(params.resourceIds);
145
+ const requestedDates = buildDateList(params.dateRange);
146
+ if (requestedResourceIds.length === 0 || requestedDates.length === 0) return true;
147
+ for (const resourceId of requestedResourceIds) {
148
+ const resourceKey = this.buildResourceKey(params.scopeKey, resourceId);
149
+ for (const date of requestedDates) {
150
+ const cell = this.cells.get(this.buildCellKey(resourceKey, date));
151
+ if (!cell) return false;
152
+ }
153
+ }
154
+ return true;
155
+ }
156
+ publish(params) {
157
+ const requestedResourceIds = uniqueIds(params.resourceIds);
158
+ const requestedDates = buildDateList(params.dateRange);
159
+ if (requestedResourceIds.length === 0 || requestedDates.length === 0) return;
160
+ const requestedDateSet = new Set(requestedDates);
161
+ const publishedAt = Date.now();
162
+ const requestedResourceKeyById = new Map(requestedResourceIds.map(resourceId => [String(resourceId), this.buildResourceKey(params.scopeKey, resourceId)]));
163
+ const rawResourceById = new Map();
164
+ (params.rawResources || []).forEach(rawResource => {
165
+ const resourceId = resolveResourceId(rawResource);
166
+ if (resourceId !== null && requestedResourceKeyById.has(String(resourceId))) {
167
+ rawResourceById.set(String(resourceId), rawResource);
168
+ }
169
+ });
170
+ requestedResourceIds.forEach(resourceId => {
171
+ const resourceKey = requestedResourceKeyById.get(String(resourceId));
172
+ if (!resourceKey) return;
173
+ if (!this.canPublishResourceRange(resourceKey, requestedDates, params.version)) return;
174
+ const rawResource = rawResourceById.get(String(resourceId));
175
+ const nextStatus = rawResource ? 'present' : 'absent';
176
+ const currentMetadata = this.resourceMeta.get(resourceKey);
177
+ if (currentMetadata && currentMetadata.version <= params.version && currentMetadata.status !== nextStatus) {
178
+ this.deleteResourceCells(resourceKey);
179
+ }
180
+ this.invalidateAdjacentOverlappingCells({
181
+ resourceKey,
182
+ requestedDates: requestedDateSet,
183
+ timezoneName: params.timezoneName
184
+ });
185
+ const metadata = rawResource ? (({
186
+ event_list: _eventList,
187
+ ...rest
188
+ }) => rest)(rawResource) : undefined;
189
+ this.writeResourceMeta(resourceKey, nextStatus, metadata, params.version);
190
+ const eventsByDate = new Map();
191
+ requestedDates.forEach(date => {
192
+ eventsByDate.set(date, new Map());
193
+ });
194
+ const eventList = Array.isArray(rawResource?.event_list) ? rawResource.event_list : [];
195
+ eventList.forEach(event => {
196
+ const rawEvent = (0, _lodashEs.cloneDeep)(event);
197
+ const identity = buildEventIdentity(resourceId, rawEvent);
198
+ bucketEventDates({
199
+ rawEvent,
200
+ timezoneName: params.timezoneName,
201
+ requestedDates: requestedDateSet
202
+ }).forEach(date => {
203
+ eventsByDate.get(date)?.set(identity, rawEvent);
204
+ });
205
+ });
206
+ requestedDates.forEach(date => {
207
+ this.writeCell({
208
+ key: this.buildCellKey(resourceKey, date),
209
+ resourceKey,
210
+ version: params.version,
211
+ eventList: sortEventList(Array.from(eventsByDate.get(date)?.values() || [])),
212
+ fetchedAt: publishedAt,
213
+ lastAccessedAt: publishedAt
214
+ });
215
+ });
216
+ });
217
+ }
218
+ buildResourceKey(scopeKey, resourceId) {
219
+ return `${scopeKey}:${String(resourceId)}`;
220
+ }
221
+ buildCellKey(resourceKey, date) {
222
+ return `${resourceKey}:${date}`;
223
+ }
224
+ touchCell(cellKey) {
225
+ const entry = this.cells.get(cellKey);
226
+ if (!entry) return null;
227
+ entry.lastAccessedAt = Date.now();
228
+ this.cells.delete(cellKey);
229
+ this.cells.set(cellKey, entry);
230
+ return entry;
231
+ }
232
+
233
+ /**
234
+ * A response is one coherent resource snapshot for its requested range. If any overlapping day
235
+ * already contains a newer response, publishing only the older response's remaining days would
236
+ * let a cross-midnight event leak back into that newer day when ranges are recomposed.
237
+ */
238
+ canPublishResourceRange(resourceKey, requestedDates, version) {
239
+ const metadata = this.resourceMeta.get(resourceKey);
240
+ if (metadata && metadata.version > version) return false;
241
+ return requestedDates.every(date => {
242
+ const current = this.cells.get(this.buildCellKey(resourceKey, date));
243
+ return !current || current.version <= version;
244
+ });
245
+ }
246
+
247
+ /**
248
+ * A day cell stores the original event range so it can be reconstructed without losing server
249
+ * identity. When a newer adjacent-day response replaces that event, evict older neighbour cells
250
+ * whose event overlaps the refreshed range. The next wider read becomes a cache miss instead of
251
+ * reintroducing stale occupancy from the neighbour.
252
+ */
253
+ invalidateAdjacentOverlappingCells(params) {
254
+ const keysToDelete = [];
255
+ this.cells.forEach((cell, cellKey) => {
256
+ if (cell.resourceKey !== params.resourceKey) return;
257
+ const cellDate = cellKey.slice(cell.resourceKey.length + 1);
258
+ if (params.requestedDates.has(cellDate)) return;
259
+ const overlapsRequestedDate = cell.eventList.some(rawEvent => bucketEventDates({
260
+ rawEvent,
261
+ timezoneName: params.timezoneName,
262
+ requestedDates: params.requestedDates
263
+ }).length > 0);
264
+ if (overlapsRequestedDate) keysToDelete.push(cellKey);
265
+ });
266
+ keysToDelete.forEach(cellKey => this.deleteCell(cellKey));
267
+ }
268
+ deleteCell(cellKey) {
269
+ const entry = this.cells.get(cellKey);
270
+ if (!entry) return;
271
+ this.cells.delete(cellKey);
272
+ const nextCount = (this.resourceCellCounts.get(entry.resourceKey) || 1) - 1;
273
+ if (nextCount <= 0) {
274
+ this.resourceCellCounts.delete(entry.resourceKey);
275
+ this.resourceMeta.delete(entry.resourceKey);
276
+ return;
277
+ }
278
+ this.resourceCellCounts.set(entry.resourceKey, nextCount);
279
+ }
280
+ deleteResourceCells(resourceKey) {
281
+ const keysToDelete = [];
282
+ this.cells.forEach((cell, cellKey) => {
283
+ if (cell.resourceKey === resourceKey) keysToDelete.push(cellKey);
284
+ });
285
+ keysToDelete.forEach(cellKey => this.deleteCell(cellKey));
286
+ }
287
+ writeResourceMeta(resourceKey, status, metadata, version) {
288
+ const current = this.resourceMeta.get(resourceKey);
289
+ if (current && current.version > version) return;
290
+ this.resourceMeta.set(resourceKey, {
291
+ version,
292
+ status,
293
+ metadata: metadata ? (0, _lodashEs.cloneDeep)(metadata) : undefined
294
+ });
295
+ }
296
+ writeCell(entry) {
297
+ const current = this.cells.get(entry.key);
298
+ if (current && current.version > entry.version) return;
299
+ if (!current) {
300
+ this.resourceCellCounts.set(entry.resourceKey, (this.resourceCellCounts.get(entry.resourceKey) || 0) + 1);
301
+ } else {
302
+ this.cells.delete(entry.key);
303
+ }
304
+ this.cells.set(entry.key, {
305
+ ...entry,
306
+ eventList: (0, _lodashEs.cloneDeep)(entry.eventList)
307
+ });
308
+ while (this.cells.size > this.maxCells) {
309
+ const oldest = this.cells.entries().next().value;
310
+ if (!oldest) break;
311
+ const [oldestKey] = oldest;
312
+ this.deleteCell(oldestKey);
313
+ }
314
+ }
315
+ }
316
+ exports.AvailabilityRemoteOccupancyCache = AvailabilityRemoteOccupancyCache;
@@ -1,91 +1,189 @@
1
- import type { ResourcePlannerModule } from '../../modules';
2
1
  import type { OpenDataConfig } from '../../modules/OpenData';
3
- import type { ResourcePlannerAssignment, ResourcePlannerAssignableSlotResult, ResourcePlannerContextInput, ResourcePlannerProjection, ResourcePlannerQuery, ResourcePlannerSelectionPatch, ResourcePlannerSnapshot, ResourcePlannerValidationResult } from '../../modules/ResourcePlanner';
4
- import type { ProductListLoadProductsParams } from '../../modules/ProductList';
2
+ import type { ProductListLoadProductsParams, ProductListStoreQueryParams } from '../../modules/ProductList';
3
+ import type { ProductData } from '../../modules/Product/types';
5
4
  import type { LoadScheduleAvailableDateParams } from '../../modules/Schedule/types';
5
+ import type { AvailabilityDateRange, AvailabilityErrorCode, AvailabilityId, AvailabilityOccupancy, AvailabilityProduct, AvailabilityProjection, AvailabilityQuery, AvailabilityRequirementSelection, AvailabilityResource, AvailabilitySelectionValidationResult, DateAvailabilityQueryResult, GetProductTimeRangesRequest, ProductAvailabilityQueryResult, ProductTimeRange, ProductTimeRangeGroup, ResourceAvailabilityGroup, ResourceAvailabilityRangeGroup, TimeAvailabilityGroup, TimeAvailabilityItem } from '../../modules/ResourcePlanner';
6
6
  import type { BookingTicketState } from '../BookingTicket/types';
7
- export declare enum UnifiedBookingSalesHooks {
8
- onPlannerContextLoaded = "unifiedBookingSales:onPlannerContextLoaded",
9
- onPlannerCommitted = "unifiedBookingSales:onPlannerCommitted"
10
- }
7
+ import type { AllergyRequirement } from '../../model/strategy/adapter/itemRule';
8
+ import type { SalesNoteDraftInput } from '../../modules/Order/types';
9
+ export type { ProductListStoreQueryParams } from '../../modules/ProductList';
10
+ export type { AvailabilityAbsoluteRange, AvailabilityAssignment, AvailabilityCell, AvailabilityDateRange, AvailabilityDisplayRange, AvailabilityErrorCode, AvailabilityId, AvailabilityMode, AvailabilityOccupancy, AvailabilityProduct, AvailabilityProductKind, AvailabilityProjection, AvailabilityProjectionInput, AvailabilityProjectionMeta, AvailabilityQuery, AvailabilityQueryResult, AvailabilityRequirementGroup, AvailabilityRequirementGroupResult, AvailabilityRequirementSelection, AvailabilityResource, AvailabilityResourceOption, AvailabilityResourceType, AvailabilityResourceWindow, AvailabilityScheduleMode, AvailabilityScheduleRef, AvailabilityScheduleRule, AvailabilitySelectionValidationParams, AvailabilitySelectionValidationResult, AvailabilitySessionRange, AvailabilityStatus, DateAvailabilityGroup, DateAvailabilityItem, DateAvailabilityQuery, DateAvailabilityQueryResult, GetProductTimeRangesRequest, ProductAvailabilityGroup, ProductAvailabilityItem, ProductAvailabilityQuery, ProductAvailabilityQueryResult, ProductTimeRange, ProductTimeRangeGroup, QueryAvailabilityBaseRequest, ResourceAvailabilityGroup, ResourceAvailabilityQuery, ResourceAvailabilityQueryResult, ResourceAvailabilityRangeGroup, TimeAvailabilityGroup, TimeAvailabilityItem, TimeAvailabilityQuery, TimeAvailabilityQueryResult, } from '../../modules/ResourcePlanner';
11
11
  export interface UnifiedBookingSalesState extends BookingTicketState {
12
- resourcePlanner: ResourcePlannerModule;
12
+ }
13
+ export interface UnifiedBookingSalesPolicy {
14
+ id?: AvailabilityId;
15
+ title?: unknown;
16
+ content?: string;
17
+ [key: string]: unknown;
18
+ }
19
+ export interface UnifiedBookingSalesPolicyResponse {
20
+ data?: UnifiedBookingSalesPolicy;
21
+ [key: string]: unknown;
22
+ }
23
+ export declare enum UnifiedBookingSalesHooks {
24
+ onAvailabilityProjectionPrepared = "unifiedBookingSales:onAvailabilityProjectionPrepared",
25
+ onAvailabilitySelectionCommitted = "unifiedBookingSales:onAvailabilitySelectionCommitted",
26
+ onAvailabilityProjectionDiagnostic = "unifiedBookingSales:onAvailabilityProjectionDiagnostic"
13
27
  }
14
28
  export interface UnifiedBookingSalesOtherParams extends Record<string, any> {
15
- /**
16
- * Persist the active order workspace in sessionStorage, partitioned by cacheId.
17
- * Disabled by default and ignored when cacheId is missing.
18
- */
19
29
  enableSessionStoragePersist?: boolean;
20
30
  }
21
- /** Explicit OpenData target used by page-level UnifiedBookingSales skins. */
31
+ export type UnifiedBookingSalesAllergyRequirement = AllergyRequirement;
32
+ export interface UnifiedBookingSalesResolveProductAllergyRequirementParams {
33
+ productId: number | string;
34
+ productVariantId?: number | string;
35
+ channel?: string;
36
+ }
22
37
  export interface UnifiedBookingSalesLoadOpenDataParams {
23
38
  businessCode: string;
24
39
  channel: string;
25
- /** Bypasses the target-scoped in-memory cache. */
26
40
  force?: boolean;
27
41
  }
28
- export interface UnifiedBookingSalesLoadPlannerContextParams extends ResourcePlannerQuery {
29
- /** ProductList request options used only when products are not supplied as raw/context data. */
30
- productLoadParams?: ProductListLoadProductsParams;
31
- /** Escape hatch for tests or callers that already own raw ProductList records. */
32
- rawProducts?: Record<string, any>[];
33
- /** Escape hatch for tests or callers that already own raw resource records. */
34
- rawResources?: Record<string, any>[];
35
- /** Fully normalized Planner context; takes precedence over API loading for supplied fields. */
36
- context?: ResourcePlannerContextInput;
37
- /** Enables the v2 resource API + schedule materialization path. */
38
- useResourceDateApi?: boolean;
39
- }
40
- export interface UnifiedBookingSalesCommitPlannerSelectionParams {
41
- /** Optional selection patch applied before validation and order mutation. */
42
- selection?: ResourcePlannerSelectionPatch;
43
- /** Directly supplies selected resource/time facts, usually from resolveAssignableSlots(). */
44
- assignments?: ResourcePlannerAssignment[];
45
- /** Defaults to false. True performs the real BaseSales / OrderModule submit after tempOrder is written. */
46
- submitAfterCommit?: boolean;
47
- }
48
42
  export interface UnifiedBookingSalesLoadProductsByScheduleDateParams extends Omit<ProductListLoadProductsParams, 'schedule_date' | 'product_ids'> {
49
- /** The chosen calendar date, used for both availability lookup and ProductList schedule_date. */
50
43
  date: string;
51
- /** Optional caller-side filter applied after the availability result produces its product pool. */
52
44
  product_ids?: number[];
53
- /** Required by the availability API; this is not the low-code page id. */
54
45
  custom_page_id?: number;
55
- /** Availability API channel, commonly pc. ProductList keeps its own sales application channel. */
56
46
  channel?: string;
57
47
  }
58
- export interface UnifiedBookingSalesStagePlannerProductsParams {
59
- /** Products the customer selected before a time/resource booking exists. */
48
+ export type UnifiedBookingSalesCatalogScope = {
49
+ type: 'schedule';
50
+ customPageId: number;
51
+ channel: string;
52
+ } | {
53
+ type: 'productList';
54
+ params: ProductListLoadProductsParams;
55
+ };
56
+ export interface UnifiedBookingSalesPrepareAvailabilityProjectionParams {
57
+ productIds?: number[];
58
+ resourceIds?: AvailabilityId[];
59
+ dateRange?: Partial<AvailabilityDateRange>;
60
+ catalogScope?: UnifiedBookingSalesCatalogScope;
61
+ rawProducts?: Record<string, any>[];
62
+ rawResources?: Record<string, any>[];
63
+ rawOccupancies?: AvailabilityOccupancy[];
64
+ editingProductLineUids?: string[];
65
+ timezone?: string;
66
+ slotStepMinutes?: number;
67
+ businessHours?: {
68
+ startTime: string;
69
+ endTime: string;
70
+ };
71
+ mode?: 'appointment' | 'scan_order' | 'venue_grid';
72
+ }
73
+ export interface AvailabilityContextRef {
74
+ contextId: string;
75
+ }
76
+ export interface ContextualProductTimeRange extends ProductTimeRange {
77
+ availabilityContextId: string;
78
+ availabilityContextVersion: number;
79
+ }
80
+ export interface ContextualProductTimeRangeGroup extends Omit<ProductTimeRangeGroup, 'ranges'> {
81
+ ranges: ContextualProductTimeRange[];
82
+ }
83
+ export type ContextualAvailabilityQuery = Omit<Extract<AvailabilityQuery, {
84
+ target: 'product';
85
+ }>, never> | Omit<Extract<AvailabilityQuery, {
86
+ target: 'date';
87
+ }>, never> | (Omit<Extract<AvailabilityQuery, {
88
+ target: 'time';
89
+ }>, 'candidates'> & {
90
+ candidates: ContextualProductTimeRange[];
91
+ }) | (Omit<Extract<AvailabilityQuery, {
92
+ target: 'resource';
93
+ }>, 'selectedRanges'> & {
94
+ selectedRanges: ContextualProductTimeRange[];
95
+ });
96
+ export type ContextualTimeAvailabilityItem = Omit<TimeAvailabilityItem, keyof ProductTimeRange> & ContextualProductTimeRange;
97
+ export interface ContextualTimeAvailabilityGroup extends Omit<TimeAvailabilityGroup, 'times'> {
98
+ times: ContextualTimeAvailabilityItem[];
99
+ }
100
+ export interface ContextualResourceAvailabilityRangeGroup extends Omit<ResourceAvailabilityRangeGroup, 'range'> {
101
+ range: ContextualProductTimeRange;
102
+ }
103
+ export interface ContextualResourceAvailabilityGroup extends Omit<ResourceAvailabilityGroup, 'ranges'> {
104
+ ranges: ContextualResourceAvailabilityRangeGroup[];
105
+ }
106
+ type ContextualAvailabilityQueryResultMeta = {
107
+ contextId: string;
108
+ contextVersion: number;
109
+ refreshed: boolean;
110
+ };
111
+ export type ContextualAvailabilityQueryResult = (ProductAvailabilityQueryResult & ContextualAvailabilityQueryResultMeta) | (DateAvailabilityQueryResult & ContextualAvailabilityQueryResultMeta) | ({
112
+ target: 'time';
113
+ evaluatedAt: string;
114
+ snapshotId: string;
115
+ data: ContextualTimeAvailabilityGroup[];
116
+ } & ContextualAvailabilityQueryResultMeta) | ({
117
+ target: 'resource';
118
+ evaluatedAt: string;
119
+ snapshotId: string;
120
+ data: ContextualResourceAvailabilityGroup[];
121
+ } & ContextualAvailabilityQueryResultMeta);
122
+ export type UnifiedBookingSalesAvailabilityCandidate = ContextualProductTimeRange;
123
+ export type UnifiedBookingSalesProductTimeRangeGroup = ContextualProductTimeRangeGroup;
124
+ export type UnifiedBookingSalesAvailabilityQueryResult = ContextualAvailabilityQueryResult;
125
+ export interface UnifiedBookingSalesAvailabilityPreparedPayload {
126
+ context: AvailabilityContextRef;
127
+ contextVersion: number;
128
+ projection: AvailabilityProjection;
129
+ refreshed: boolean;
130
+ reason?: string;
131
+ previousOrderRevision?: AvailabilityId;
132
+ }
133
+ export interface UnifiedBookingSalesAvailabilityDiagnosticPayload {
134
+ contextId: string | null;
135
+ contextVersion: number | null;
136
+ reason: string;
137
+ projection: AvailabilityProjection | null;
138
+ action: 'prepare' | 'refresh' | 'release' | 'destroy' | 'set_other_params_reset' | 'commit_lock_wait' | 'commit_lock_acquired' | 'commit_lock_released';
139
+ snapshotId?: string;
140
+ orderRevision?: AvailabilityId;
141
+ previousOrderRevision?: AvailabilityId;
142
+ registrySize: number;
143
+ projectionPoolSize: number;
144
+ }
145
+ export interface UnifiedBookingSalesStageRetailProductsParams {
60
146
  productIds: Array<number | string>;
61
147
  productLoadParams?: ProductListLoadProductsParams;
62
148
  rawProducts?: Record<string, any>[];
63
149
  }
64
- /** Ordinary retail product staging. No resource, time, or booking facts are required. */
65
- export type UnifiedBookingSalesStageRetailProductsParams = UnifiedBookingSalesStagePlannerProductsParams;
66
- /** Adds one ordinary retail product without replacing other retail lines already in the cart. */
67
150
  export interface UnifiedBookingSalesAddRetailProductParams {
68
- /** Prefer a supplied catalog record when the UI has already loaded it. */
69
151
  product?: Record<string, any>;
70
- /** Used to resolve a product from the current catalog or load it on demand. */
71
152
  productId?: number | string;
72
- /** Defaults to one. */
73
153
  quantity?: number;
74
- /** Only used when the product is not already present in the solution catalog. */
75
154
  productLoadParams?: ProductListLoadProductsParams;
76
155
  }
77
- export interface UnifiedBookingSalesCommitResult {
156
+ export interface ContextualCommitAvailabilitySelectionParams {
157
+ mode: 'add' | 'edit';
158
+ productLineUid?: string;
159
+ orderProduct: Record<string, any>;
160
+ candidate: ContextualProductTimeRange;
161
+ requirementSelections: AvailabilityRequirementSelection[];
162
+ partySize: number;
163
+ bookingCount?: number;
164
+ /** 新增商品行时与商品、预约在同一次 Order mutation 内写入的 Sales Notes。 */
165
+ salesNotes?: SalesNoteDraftInput[];
166
+ /** 编辑预约时,允许本次显式报价覆盖已落库订单行的历史价格。 */
167
+ allowBookingReprice?: boolean;
168
+ /** 编辑预约重报价后,允许订单模块重新应用已选编辑态折扣。 */
169
+ allowBookingDiscountReapply?: boolean;
170
+ }
171
+ export type UnifiedBookingSalesCommitAvailabilitySelectionParams = ContextualCommitAvailabilitySelectionParams;
172
+ export interface UnifiedBookingSalesCommitAvailabilitySelectionResult {
173
+ contextId: string;
174
+ contextVersion: number;
78
175
  tempOrder: Record<string, any> | null;
79
- assignments: ResourcePlannerAssignment[];
80
- validation: ResourcePlannerValidationResult;
81
- submitResult?: unknown;
176
+ validation: AvailabilitySelectionValidationResult;
177
+ candidate: ContextualProductTimeRange;
178
+ productLineUid?: string;
179
+ bookingUid?: string;
180
+ productLineUids?: string[];
181
+ bookingUids?: string[];
82
182
  }
183
+ export type UnifiedBookingSalesAvailabilityErrorCode = AvailabilityErrorCode;
83
184
  export interface UnifiedBookingSalesApplyPlannerDiscountsParams {
84
- /** Customer whose cards/coupons should be loaded. Defaults to tempOrder.customer_id. */
85
185
  customerId?: number | string;
86
- /** Optional explicit card/coupon id. When provided, Rules applies this card instead of auto-picking another card. */
87
186
  preferredDiscountId?: number | string;
88
- /** Defaults to true: after loading eligible cards, let Rules choose the best valid combination. */
89
187
  applyBestDiscount?: boolean;
90
188
  }
91
189
  export interface UnifiedBookingSalesDiscountItem {
@@ -110,7 +208,6 @@ export interface UnifiedBookingSalesDiscountResult {
110
208
  status: 'applied' | 'loaded' | 'no_customer';
111
209
  customerId: number | null;
112
210
  preferredDiscountFound?: boolean;
113
- /** True only when the requested card is both selected and written into a planner product line. */
114
211
  preferredDiscountApplied?: boolean;
115
212
  availableDiscounts: UnifiedBookingSalesDiscountItem[];
116
213
  selectedDiscounts: UnifiedBookingSalesDiscountItem[];
@@ -119,32 +216,19 @@ export interface UnifiedBookingSalesDiscountResult {
119
216
  summaryAfter?: unknown;
120
217
  }
121
218
  export interface UnifiedBookingSalesApi {
122
- /** Loads board OpenData for a concrete business + channel target. */
123
219
  loadOpenData: (params: UnifiedBookingSalesLoadOpenDataParams) => Promise<OpenDataConfig>;
124
- /** Returns the latest OpenData payload cached by this solution instance. */
125
- getOpenData: () => OpenDataConfig | null;
126
- /** Date-first calendar availability backed by ScheduleModule. */
220
+ getOpenData: () => Promise<OpenDataConfig | null>;
127
221
  loadScheduleAvailableDate: (params: LoadScheduleAvailableDateParams) => Promise<unknown>;
128
- /** Date-first product pool derived from schedule date ids and globally sellable products. */
129
222
  loadProductsByScheduleDate: (params: UnifiedBookingSalesLoadProductsByScheduleDateParams) => Promise<unknown[]>;
130
- /** Adds product lines only; booking creation is intentionally deferred. */
131
- stagePlannerProducts: (params: UnifiedBookingSalesStagePlannerProductsParams) => Promise<Record<string, any> | null>;
132
- /** Adds ordinary product lines only. It never creates bookings or invokes ResourcePlanner. */
223
+ queryProducts: (params?: ProductListStoreQueryParams) => Promise<ProductData[]>;
133
224
  stageRetailProducts: (params: UnifiedBookingSalesStageRetailProductsParams) => Promise<Record<string, any> | null>;
134
- /** Adds one ordinary retail line while preserving all existing cart lines. */
135
225
  addRetailProduct: (params: UnifiedBookingSalesAddRetailProductParams) => Promise<Record<string, any>[]>;
136
- /** Loads and normalizes all IO data needed for the pure ResourcePlanner. */
137
- loadPlannerContext: (params?: UnifiedBookingSalesLoadPlannerContextParams) => Promise<ResourcePlannerSnapshot>;
138
- /** Reads continuous availability cells and UI-oriented aggregates. */
139
- queryPlannerAvailability: (query?: ResourcePlannerQuery) => Promise<ResourcePlannerProjection>;
140
- /** Produces selectable slots and the assignments required to commit them. */
141
- resolveAssignableSlots: (query?: ResourcePlannerQuery) => ResourcePlannerAssignableSlotResult;
142
- setPlannerSelection: (patch: ResourcePlannerSelectionPatch) => ResourcePlannerSnapshot;
143
- autoAssignPlanner: (query?: ResourcePlannerQuery) => Promise<ResourcePlannerSnapshot>;
144
- validatePlannerSelection: () => ResourcePlannerValidationResult;
145
- /** Validates, writes to tempOrder, and only optionally makes a real submit request. */
146
- commitPlannerSelection: (params?: UnifiedBookingSalesCommitPlannerSelectionParams) => Promise<UnifiedBookingSalesCommitResult>;
147
- /** Loads the current customer's cards/coupons, optionally applies the best one, and reports line applications. */
226
+ prepareAvailabilityProjection: (params: UnifiedBookingSalesPrepareAvailabilityProjectionParams) => Promise<AvailabilityContextRef>;
227
+ getProductTimeRanges: (contextId: string, request?: GetProductTimeRangesRequest) => Promise<ContextualProductTimeRangeGroup[]>;
228
+ queryBookingAvailability: (contextId: string, request: ContextualAvailabilityQuery) => Promise<ContextualAvailabilityQueryResult>;
229
+ commitAvailabilitySelection: (contextId: string, params: ContextualCommitAvailabilitySelectionParams) => Promise<UnifiedBookingSalesCommitAvailabilitySelectionResult>;
230
+ releaseAvailabilityContext: (contextId: string) => void;
148
231
  applyPlannerDiscounts: (params?: UnifiedBookingSalesApplyPlannerDiscountsParams) => Promise<UnifiedBookingSalesDiscountResult>;
149
- getPlannerSnapshot: () => ResourcePlannerSnapshot;
150
232
  }
233
+ export type UnifiedBookingSalesNormalizedProduct = AvailabilityProduct;
234
+ export type UnifiedBookingSalesNormalizedResource = AvailabilityResource;