@foodtolls/common 2.0.1 → 2.2.0
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/dist/enums/notification.enum.d.ts +35 -0
- package/dist/enums/notification.enum.js +43 -0
- package/dist/enums/notification.enum.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/interfaces/inventory.interface.d.ts +3 -74
- package/dist/interfaces/inventory.interface.js +1 -6
- package/dist/interfaces/inventory.interface.js.map +1 -1
- package/dist/interfaces/menu.interface.d.ts +159 -0
- package/dist/interfaces/menu.interface.js +23 -0
- package/dist/interfaces/menu.interface.js.map +1 -0
- package/dist/interfaces/notification.interface.d.ts +17 -0
- package/dist/interfaces/notification.interface.js +3 -0
- package/dist/interfaces/notification.interface.js.map +1 -0
- package/dist/saga/redis-ack-tracker.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utils/menu.util.d.ts +2 -2
- package/dist/utils/menu.util.js +8 -8
- package/dist/utils/menu.util.js.map +1 -1
- package/package.json +1 -1
- package/src/enums/notification.enum.ts +38 -0
- package/src/index.ts +3 -0
- package/src/interfaces/inventory.interface.ts +3 -82
- package/src/interfaces/menu.interface.ts +213 -0
- package/src/interfaces/notification.interface.ts +22 -0
- package/src/saga/redis-ack-tracker.ts +7 -10
- package/src/utils/menu.util.ts +6 -1
- package/tsconfig.json +2 -1
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export enum NotificationType {
|
|
2
|
+
ORDER_PLACED = "ORDER_PLACED",
|
|
3
|
+
ORDER_ACCEPTED = "ORDER_ACCEPTED",
|
|
4
|
+
ORDER_PREPARING = "ORDER_PREPARING",
|
|
5
|
+
ORDER_READY = "ORDER_READY",
|
|
6
|
+
ORDER_COMPLETED = "ORDER_COMPLETED",
|
|
7
|
+
ORDER_CANCELLED = "ORDER_CANCELLED",
|
|
8
|
+
PAYMENT_SUCCESS = "PAYMENT_SUCCESS",
|
|
9
|
+
PAYMENT_FAILED = "PAYMENT_FAILED",
|
|
10
|
+
PAYMENT_REFUNDED = "PAYMENT_REFUNDED",
|
|
11
|
+
VENDOR_APPROVED = "VENDOR_APPROVED",
|
|
12
|
+
VENDOR_REJECTED = "VENDOR_REJECTED",
|
|
13
|
+
OTP_REQUEST = "OTP_REQUEST",
|
|
14
|
+
DELIVERY_ASSIGNED = "DELIVERY_ASSIGNED",
|
|
15
|
+
DELIVERY_PICKED_UP = "DELIVERY_PICKED_UP",
|
|
16
|
+
DELIVERY_COMPLETED = "DELIVERY_COMPLETED",
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export enum NotificationChannel {
|
|
20
|
+
PUSH = "PUSH",
|
|
21
|
+
EMAIL = "EMAIL",
|
|
22
|
+
SMS = "SMS",
|
|
23
|
+
ALL = "ALL",
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export enum NotificationPriority {
|
|
27
|
+
LOW = "LOW",
|
|
28
|
+
NORMAL = "NORMAL",
|
|
29
|
+
HIGH = "HIGH",
|
|
30
|
+
URGENT = "URGENT",
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export enum NotificationStatus {
|
|
34
|
+
PENDING = "PENDING",
|
|
35
|
+
SENT = "SENT",
|
|
36
|
+
FAILED = "FAILED",
|
|
37
|
+
IGNORED = "IGNORED",
|
|
38
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -2,11 +2,14 @@ export * from "./enums/order.enum";
|
|
|
2
2
|
export * from "./enums/vendor.enum";
|
|
3
3
|
export * from "./enums/payment.enum";
|
|
4
4
|
export * from "./enums/auth.enum";
|
|
5
|
+
export * from "./enums/notification.enum";
|
|
5
6
|
export * from "./constants/order.constants";
|
|
6
7
|
export * from "./interfaces/order.interface";
|
|
7
8
|
export * from "./interfaces/orderTrack.interface";
|
|
8
9
|
export * from "./interfaces/inventory.interface";
|
|
9
10
|
export * from "./interfaces/gmap.interface";
|
|
11
|
+
export * from "./interfaces/notification.interface";
|
|
12
|
+
export * from "./interfaces/menu.interface";
|
|
10
13
|
export * from "./utils/menu.util";
|
|
11
14
|
export * from "./utils/reachTimeSelection";
|
|
12
15
|
export * from "./saga";
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { MenuCategory, TimeSlotsRange } from "./menu.interface";
|
|
1
2
|
import { IOrderEntity } from "./order.interface";
|
|
2
3
|
|
|
3
4
|
export interface InventoryRedis {
|
|
4
5
|
restaurantWorkingHours: WorkingHours[];
|
|
5
6
|
menu: [] | MenuCategory[];
|
|
6
|
-
timeSlots: [] |
|
|
7
|
+
timeSlots: [] | TimeSlotsRange[];
|
|
7
8
|
}
|
|
8
9
|
|
|
9
10
|
export interface WorkingHours {
|
|
@@ -29,90 +30,10 @@ export enum RestaurantOpen {
|
|
|
29
30
|
CLOSED = "Closed",
|
|
30
31
|
}
|
|
31
32
|
|
|
32
|
-
export interface Image {
|
|
33
|
-
uid: number;
|
|
34
|
-
name: string;
|
|
35
|
-
status: string;
|
|
36
|
-
url: string;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export enum TimeSlotType {
|
|
40
|
-
DEFAULT = "DEFAULT",
|
|
41
|
-
CUSTOM = "CUSTOM",
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export interface AvailableHours {
|
|
45
|
-
from: string;
|
|
46
|
-
to: string;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export interface AvailableHoursMap {
|
|
50
|
-
Monday: string[];
|
|
51
|
-
Tuesday: string[];
|
|
52
|
-
Wednesday: string[];
|
|
53
|
-
Thursday: string[];
|
|
54
|
-
Friday: string[];
|
|
55
|
-
Saturday: string[];
|
|
56
|
-
Sunday: string[];
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export interface FoodItem {
|
|
60
|
-
key: string;
|
|
61
|
-
subcategory_id: string;
|
|
62
|
-
food_id: string;
|
|
63
|
-
label: string;
|
|
64
|
-
price: number;
|
|
65
|
-
totalPrice: number;
|
|
66
|
-
description: string;
|
|
67
|
-
gstPercentage: number;
|
|
68
|
-
gst: number;
|
|
69
|
-
packaging: boolean;
|
|
70
|
-
packaging_charges: number | null;
|
|
71
|
-
servings: number;
|
|
72
|
-
category: string;
|
|
73
|
-
status: string;
|
|
74
|
-
images: Image[];
|
|
75
|
-
availableDays: string[];
|
|
76
|
-
availableHours: AvailableHoursMap;
|
|
77
|
-
ratings: {
|
|
78
|
-
averageRatings: number;
|
|
79
|
-
ratingCount: number;
|
|
80
|
-
};
|
|
81
|
-
type: string;
|
|
82
|
-
addOns: any[]; // refine later if you have add-on structure
|
|
83
|
-
healthy: boolean;
|
|
84
|
-
vegan: boolean;
|
|
85
|
-
recommend: boolean;
|
|
86
|
-
cuisine: string[];
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
export interface SubCategory {
|
|
90
|
-
key: string;
|
|
91
|
-
category_id: string;
|
|
92
|
-
label: string;
|
|
93
|
-
subcategory_id: string;
|
|
94
|
-
foodItems: FoodItem[];
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
export interface MenuCategory {
|
|
98
|
-
key: string;
|
|
99
|
-
category_id: string;
|
|
100
|
-
label: string;
|
|
101
|
-
hasSubCategory: boolean;
|
|
102
|
-
children: Array<SubCategory | FoodItem>;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
export interface TimeSlot {
|
|
106
|
-
slotName: string;
|
|
107
|
-
availableHours: AvailableHours;
|
|
108
|
-
type: TimeSlotType;
|
|
109
|
-
crossingOver: boolean;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
33
|
export interface SetMenuDetailsDetails {
|
|
113
34
|
restaurantId: string;
|
|
114
35
|
menuCard: MenuCategory[];
|
|
115
|
-
timeSlots:
|
|
36
|
+
timeSlots: TimeSlotsRange[];
|
|
116
37
|
}
|
|
117
38
|
|
|
118
39
|
export interface InventoryFoodAvailability {
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
//Image
|
|
2
|
+
export interface Image {
|
|
3
|
+
uid: string;
|
|
4
|
+
name: string;
|
|
5
|
+
status: string;
|
|
6
|
+
url: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
//Availalility
|
|
10
|
+
export enum TimeSlotType {
|
|
11
|
+
DEFAULT = "DEFAULT",
|
|
12
|
+
CUSTOM = "CUSTOM",
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface AvailableHours {
|
|
16
|
+
from: string;
|
|
17
|
+
to: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface TimeSlotsRange {
|
|
21
|
+
slotName: string;
|
|
22
|
+
availableHours: AvailableHours;
|
|
23
|
+
type: TimeSlotType;
|
|
24
|
+
crossingOver: boolean;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface AvailableHours {
|
|
28
|
+
Monday: string[];
|
|
29
|
+
Tuesday: string[];
|
|
30
|
+
Wednesday: string[];
|
|
31
|
+
Thursday: string[];
|
|
32
|
+
Friday: string[];
|
|
33
|
+
Saturday: string[];
|
|
34
|
+
Sunday: string[];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
//Addons
|
|
38
|
+
export interface AddonItem {
|
|
39
|
+
addon_id: string;
|
|
40
|
+
label: string;
|
|
41
|
+
price: number;
|
|
42
|
+
gstPercentage: number;
|
|
43
|
+
isDefault: boolean;
|
|
44
|
+
sortOrder: number;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface AddonGroup {
|
|
48
|
+
group_id: string;
|
|
49
|
+
label: string;
|
|
50
|
+
selectionType: "SINGLE_SELECT" | "MULTI_SELECT";
|
|
51
|
+
minSelect: number;
|
|
52
|
+
maxSelect: number;
|
|
53
|
+
addons: AddonItem[];
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
//Stock
|
|
57
|
+
export interface Stock {
|
|
58
|
+
initialStockPerDay: number;
|
|
59
|
+
currentStock: number;
|
|
60
|
+
autoRefresh: boolean;
|
|
61
|
+
nextRefreshAt: string;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
//Offers
|
|
65
|
+
export enum OfferScope {
|
|
66
|
+
ITEM = "ITEM",
|
|
67
|
+
CATEGORY = "CATEGORY",
|
|
68
|
+
RESTAURANT = "RESTAURANT",
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export enum OfferType {
|
|
72
|
+
FLAT = "FLAT",
|
|
73
|
+
PERCENT = "PERCENT",
|
|
74
|
+
BOGO = "BOGO",
|
|
75
|
+
BUY_X_GET_Y = "BUY_X_GET_Y",
|
|
76
|
+
COMBO_DISCOUNT = "COMBO_DISCOUNT",
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export interface OfferReward {
|
|
80
|
+
rewardType: "FLAT" | "PERCENT" | "FREE_ITEM" | "DISCOUNTED_ITEM";
|
|
81
|
+
flatAmount?: number;
|
|
82
|
+
percent?: number;
|
|
83
|
+
freeItemId?: string;
|
|
84
|
+
discountedPrice?: number;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export interface Offer {
|
|
88
|
+
offer_id: string;
|
|
89
|
+
scope: OfferScope;
|
|
90
|
+
type: OfferType;
|
|
91
|
+
title: string;
|
|
92
|
+
|
|
93
|
+
startAt: string; // ISO timestamp
|
|
94
|
+
endAt: string;
|
|
95
|
+
|
|
96
|
+
priority: number;
|
|
97
|
+
stackable: boolean;
|
|
98
|
+
|
|
99
|
+
rewards: OfferReward[];
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
//Combos
|
|
103
|
+
export interface ComboFixedItem {
|
|
104
|
+
item_id: string;
|
|
105
|
+
quantity: number;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export interface ComboGroupItem {
|
|
109
|
+
item_id: string;
|
|
110
|
+
defaultQuantity: number;
|
|
111
|
+
extraPrice: number;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export interface ComboGroup {
|
|
115
|
+
group_id: string;
|
|
116
|
+
label: string;
|
|
117
|
+
selectionType: "SINGLE_SELECT" | "MULTI_SELECT";
|
|
118
|
+
minSelect: number;
|
|
119
|
+
maxSelect: number;
|
|
120
|
+
items: ComboGroupItem[];
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export interface Combo {
|
|
124
|
+
combo_id: string;
|
|
125
|
+
label: string;
|
|
126
|
+
description: string;
|
|
127
|
+
basePrice: number;
|
|
128
|
+
discountPrice?: number;
|
|
129
|
+
|
|
130
|
+
fixedItems: ComboFixedItem[];
|
|
131
|
+
groups: ComboGroup[];
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
//FoodItem
|
|
135
|
+
export interface FoodItem {
|
|
136
|
+
key: string;
|
|
137
|
+
food_id: string;
|
|
138
|
+
subcategory_id: string;
|
|
139
|
+
|
|
140
|
+
label: string;
|
|
141
|
+
price: number;
|
|
142
|
+
totalPrice: number;
|
|
143
|
+
description: string;
|
|
144
|
+
|
|
145
|
+
gstPercentage: number;
|
|
146
|
+
gst: number;
|
|
147
|
+
|
|
148
|
+
packaging: boolean;
|
|
149
|
+
packaging_charges: number | null;
|
|
150
|
+
servings: number;
|
|
151
|
+
|
|
152
|
+
category: string; // "fresh" or "packaged"
|
|
153
|
+
status: string; // "Available" or "Unavailable"
|
|
154
|
+
|
|
155
|
+
images: [];
|
|
156
|
+
|
|
157
|
+
availableDays: string[];
|
|
158
|
+
availableHours: AvailableHours;
|
|
159
|
+
|
|
160
|
+
ratings: {
|
|
161
|
+
averageRatings: number;
|
|
162
|
+
ratingCount: number;
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
type: string; // veg/nonveg/egg
|
|
166
|
+
|
|
167
|
+
healthy: boolean;
|
|
168
|
+
vegan: boolean;
|
|
169
|
+
recommend: boolean;
|
|
170
|
+
cuisine: string;
|
|
171
|
+
|
|
172
|
+
/** NEW SECTIONS */
|
|
173
|
+
|
|
174
|
+
addOns: AddonGroup[];
|
|
175
|
+
|
|
176
|
+
stock: Stock;
|
|
177
|
+
|
|
178
|
+
offers: Offer[];
|
|
179
|
+
|
|
180
|
+
combos: Combo[];
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
//SubCategory
|
|
184
|
+
export interface SubCategory {
|
|
185
|
+
key: string;
|
|
186
|
+
category_id: string;
|
|
187
|
+
label: string;
|
|
188
|
+
subcategory_id: string;
|
|
189
|
+
|
|
190
|
+
foodItems: FoodItem[];
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
//Category
|
|
194
|
+
export interface MenuCategory {
|
|
195
|
+
key: string;
|
|
196
|
+
category_id: string;
|
|
197
|
+
label: string;
|
|
198
|
+
hasSubCategory: boolean;
|
|
199
|
+
|
|
200
|
+
children: Array<SubCategory | FoodItem>;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
//Full Menu Structure
|
|
204
|
+
export interface SetMenuDetails {
|
|
205
|
+
restaurantId: string;
|
|
206
|
+
|
|
207
|
+
menuCard: MenuCategory[];
|
|
208
|
+
|
|
209
|
+
timeSlots: TimeSlotsRange[];
|
|
210
|
+
|
|
211
|
+
// Optional global restaurant offers
|
|
212
|
+
restaurantOffers?: Offer[];
|
|
213
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import {
|
|
2
|
+
NotificationType,
|
|
3
|
+
NotificationPriority,
|
|
4
|
+
} from "../enums/notification.enum";
|
|
5
|
+
|
|
6
|
+
export interface INotificationPayload {
|
|
7
|
+
eventType: NotificationType;
|
|
8
|
+
userId: string;
|
|
9
|
+
userType: "USER" | "VENDOR" | "ADMIN";
|
|
10
|
+
recipientEmail?: string;
|
|
11
|
+
recipientPhone?: string;
|
|
12
|
+
data: Record<string, any>;
|
|
13
|
+
priority: NotificationPriority;
|
|
14
|
+
metadata?: any;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface IDeliveryAttempt {
|
|
18
|
+
attemptNumber: number;
|
|
19
|
+
timestamp: Date;
|
|
20
|
+
status: string;
|
|
21
|
+
errorMessage?: string;
|
|
22
|
+
}
|
|
@@ -36,10 +36,10 @@ export class RedisAckTracker {
|
|
|
36
36
|
// Check each pending acknowledgment
|
|
37
37
|
for (const ackKey of Array.from(pendingAcks)) {
|
|
38
38
|
const ackData = await this.getAck(sagaId, ackKey);
|
|
39
|
-
|
|
39
|
+
|
|
40
40
|
if (ackData) {
|
|
41
41
|
pendingAcks.delete(ackKey);
|
|
42
|
-
|
|
42
|
+
|
|
43
43
|
if (!ackData.success) {
|
|
44
44
|
// Service reported failure
|
|
45
45
|
failedAcks.push(ackKey);
|
|
@@ -73,7 +73,9 @@ export class RedisAckTracker {
|
|
|
73
73
|
return {
|
|
74
74
|
success: false,
|
|
75
75
|
sagaId,
|
|
76
|
-
error: `Timeout waiting for acknowledgments: ${Array.from(
|
|
76
|
+
error: `Timeout waiting for acknowledgments: ${Array.from(
|
|
77
|
+
pendingAcks
|
|
78
|
+
).join(", ")}`,
|
|
77
79
|
failedAcks: Array.from(pendingAcks),
|
|
78
80
|
timedOut: true,
|
|
79
81
|
};
|
|
@@ -117,7 +119,7 @@ export class RedisAckTracker {
|
|
|
117
119
|
async getAck(sagaId: string, ackKey: string): Promise<AckData | null> {
|
|
118
120
|
const key = this.getAckKey(sagaId, ackKey);
|
|
119
121
|
const data = await this.redis.get(key);
|
|
120
|
-
|
|
122
|
+
|
|
121
123
|
if (!data) {
|
|
122
124
|
return null;
|
|
123
125
|
}
|
|
@@ -137,12 +139,7 @@ export class RedisAckTracker {
|
|
|
137
139
|
*/
|
|
138
140
|
async setSagaState(sagaId: string, state: SagaState): Promise<void> {
|
|
139
141
|
const key = `saga:${sagaId}:state`;
|
|
140
|
-
await this.redis.set(
|
|
141
|
-
key,
|
|
142
|
-
state,
|
|
143
|
-
"EX",
|
|
144
|
-
this.ACK_TTL_SECONDS
|
|
145
|
-
);
|
|
142
|
+
await this.redis.set(key, state, "EX", this.ACK_TTL_SECONDS);
|
|
146
143
|
}
|
|
147
144
|
|
|
148
145
|
/**
|
package/src/utils/menu.util.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
MenuCategory,
|
|
3
|
+
TimeSlotType,
|
|
4
|
+
SubCategory,
|
|
5
|
+
FoodItem,
|
|
6
|
+
} from "../interfaces/menu.interface";
|
|
2
7
|
|
|
3
8
|
export const findReqCategory = (Menu: MenuCategory[], category: string) => {
|
|
4
9
|
// console.log("findReqCategory", Menu, category);
|