@zssz-soft/firebase-functions-shared 1.2.10 → 1.2.11
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/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/lib/modules/booking/booking-email.models.d.ts +90 -0
- package/lib/modules/booking/booking-email.models.d.ts.map +1 -0
- package/lib/modules/booking/booking-email.models.js +18 -0
- package/lib/modules/booking/booking-email.models.js.map +1 -0
- package/lib/modules/booking/booking-email.templates.d.ts +27 -0
- package/lib/modules/booking/booking-email.templates.d.ts.map +1 -0
- package/lib/modules/booking/booking-email.templates.js +431 -0
- package/lib/modules/booking/booking-email.templates.js.map +1 -0
- package/lib/modules/booking/booking-email.triggers.d.ts +23 -0
- package/lib/modules/booking/booking-email.triggers.d.ts.map +1 -0
- package/lib/modules/booking/booking-email.triggers.js +151 -0
- package/lib/modules/booking/booking-email.triggers.js.map +1 -0
- package/lib/modules/booking/index.d.ts +9 -0
- package/lib/modules/booking/index.d.ts.map +1 -0
- package/lib/modules/booking/index.js +25 -0
- package/lib/modules/booking/index.js.map +1 -0
- package/package.json +1 -1
- package/lib/modules/user/user-auth.triggers.d.ts +0 -25
- package/lib/modules/user/user-auth.triggers.d.ts.map +0 -1
- package/lib/modules/user/user-auth.triggers.js +0 -154
- package/lib/modules/user/user-auth.triggers.js.map +0 -1
package/lib/index.d.ts
CHANGED
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,UAAU,CAAC;AACzB,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,UAAU,CAAC;AACzB,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC"}
|
package/lib/index.js
CHANGED
|
@@ -27,4 +27,5 @@ __exportStar(require("./modules/storage"), exports);
|
|
|
27
27
|
__exportStar(require("./modules/user"), exports);
|
|
28
28
|
__exportStar(require("./modules/security"), exports);
|
|
29
29
|
__exportStar(require("./modules/e2e"), exports);
|
|
30
|
+
__exportStar(require("./modules/booking"), exports);
|
|
30
31
|
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;;;;;;;;;;;;;;AAEH,2CAAyB;AACzB,sDAAoC;AACpC,kDAAgC;AAChC,oDAAkC;AAClC,iDAA+B;AAC/B,qDAAmC;AACnC,gDAA8B"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;;;;;;;;;;;;;;AAEH,2CAAyB;AACzB,sDAAoC;AACpC,kDAAgC;AAChC,oDAAkC;AAClC,iDAA+B;AAC/B,qDAAmC;AACnC,gDAA8B;AAC9B,oDAAkC"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Booking Email Notification Data Models
|
|
3
|
+
*
|
|
4
|
+
* Interfaces for booking email trigger configuration and booking data.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Booking data structure for email templates
|
|
8
|
+
* Matches the BookingModel structure saved to Firestore
|
|
9
|
+
*/
|
|
10
|
+
export interface BookingEmailData {
|
|
11
|
+
uid: string;
|
|
12
|
+
accommodation: {
|
|
13
|
+
id: string;
|
|
14
|
+
name: string | {
|
|
15
|
+
en?: string;
|
|
16
|
+
hu?: string;
|
|
17
|
+
};
|
|
18
|
+
contact?: {
|
|
19
|
+
email: string;
|
|
20
|
+
name: string;
|
|
21
|
+
phone: string;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
guest: {
|
|
25
|
+
firstName: string;
|
|
26
|
+
lastName: string;
|
|
27
|
+
email: string;
|
|
28
|
+
phoneNumber?: string;
|
|
29
|
+
language?: 'hu' | 'en';
|
|
30
|
+
};
|
|
31
|
+
stay: {
|
|
32
|
+
checkIn: string;
|
|
33
|
+
checkOut: string;
|
|
34
|
+
nights: number;
|
|
35
|
+
guestCount: number;
|
|
36
|
+
};
|
|
37
|
+
priceDetail: {
|
|
38
|
+
currency: string;
|
|
39
|
+
basePrice: number;
|
|
40
|
+
totalPrice: number;
|
|
41
|
+
};
|
|
42
|
+
payment: {
|
|
43
|
+
method: string;
|
|
44
|
+
status: string;
|
|
45
|
+
};
|
|
46
|
+
source: string;
|
|
47
|
+
workflow?: {
|
|
48
|
+
currentState: string;
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Configuration for booking email triggers
|
|
53
|
+
*/
|
|
54
|
+
export interface BookingEmailConfig {
|
|
55
|
+
/**
|
|
56
|
+
* Firestore collection name for bookings
|
|
57
|
+
* @default 'booking'
|
|
58
|
+
*/
|
|
59
|
+
bookingCollection: string;
|
|
60
|
+
/**
|
|
61
|
+
* Cloud Functions deployment region
|
|
62
|
+
* @default 'europe-west1'
|
|
63
|
+
*/
|
|
64
|
+
region: string;
|
|
65
|
+
/**
|
|
66
|
+
* Maximum number of concurrent function instances
|
|
67
|
+
* @default 10
|
|
68
|
+
*/
|
|
69
|
+
maxInstances?: number;
|
|
70
|
+
/**
|
|
71
|
+
* Optional Firestore database ID
|
|
72
|
+
* Leave undefined for default database
|
|
73
|
+
*/
|
|
74
|
+
databaseId?: string;
|
|
75
|
+
/**
|
|
76
|
+
* Enable sending notification emails to admin/owner
|
|
77
|
+
* @default true
|
|
78
|
+
*/
|
|
79
|
+
adminNotificationEnabled?: boolean;
|
|
80
|
+
/**
|
|
81
|
+
* Fallback admin email when accommodation.contact.email is missing
|
|
82
|
+
* Loaded from environment variable if not provided
|
|
83
|
+
*/
|
|
84
|
+
fallbackAdminEmail?: string;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Default configuration values
|
|
88
|
+
*/
|
|
89
|
+
export declare const DEFAULT_BOOKING_EMAIL_CONFIG: BookingEmailConfig;
|
|
90
|
+
//# sourceMappingURL=booking-email.models.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"booking-email.models.d.ts","sourceRoot":"","sources":["../../../src/modules/booking/booking-email.models.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,aAAa,EAAE;QACb,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,GAAG;YAAE,EAAE,CAAC,EAAE,MAAM,CAAC;YAAC,EAAE,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QAC5C,OAAO,CAAC,EAAE;YACR,KAAK,EAAE,MAAM,CAAC;YACd,IAAI,EAAE,MAAM,CAAC;YACb,KAAK,EAAE,MAAM,CAAC;SACf,CAAC;KACH,CAAC;IACF,KAAK,EAAE;QACL,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;KACxB,CAAC;IACF,IAAI,EAAE;QACJ,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,WAAW,EAAE;QACX,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,OAAO,EAAE;QACP,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE;QACT,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,iBAAiB,EAAE,MAAM,CAAC;IAE1B;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,wBAAwB,CAAC,EAAE,OAAO,CAAC;IAEnC;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;GAEG;AACH,eAAO,MAAM,4BAA4B,EAAE,kBAK1C,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Booking Email Notification Data Models
|
|
4
|
+
*
|
|
5
|
+
* Interfaces for booking email trigger configuration and booking data.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.DEFAULT_BOOKING_EMAIL_CONFIG = void 0;
|
|
9
|
+
/**
|
|
10
|
+
* Default configuration values
|
|
11
|
+
*/
|
|
12
|
+
exports.DEFAULT_BOOKING_EMAIL_CONFIG = {
|
|
13
|
+
bookingCollection: 'booking',
|
|
14
|
+
region: 'europe-west1',
|
|
15
|
+
maxInstances: 10,
|
|
16
|
+
adminNotificationEnabled: true,
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=booking-email.models.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"booking-email.models.js","sourceRoot":"","sources":["../../../src/modules/booking/booking-email.models.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAsFH;;GAEG;AACU,QAAA,4BAA4B,GAAuB;IAC9D,iBAAiB,EAAE,SAAS;IAC5B,MAAM,EAAE,cAAc;IACtB,YAAY,EAAE,EAAE;IAChB,wBAAwB,EAAE,IAAI;CAC/B,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Email Templates for Booking Notifications
|
|
3
|
+
*
|
|
4
|
+
* Bilingual templates (Hungarian and English) matching the existing email style.
|
|
5
|
+
* Generates both HTML and plain text versions of emails.
|
|
6
|
+
*/
|
|
7
|
+
import { BookingEmailData } from './booking-email.models';
|
|
8
|
+
/**
|
|
9
|
+
* Generate guest confirmation email
|
|
10
|
+
* Sent to the guest after successful booking submission
|
|
11
|
+
*/
|
|
12
|
+
export declare function generateGuestConfirmationEmail(booking: BookingEmailData): {
|
|
13
|
+
subject: string;
|
|
14
|
+
html: string;
|
|
15
|
+
text: string;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Generate admin/owner notification email
|
|
19
|
+
* Sent to property owner when a new booking is submitted
|
|
20
|
+
* Admin emails are always in Hungarian
|
|
21
|
+
*/
|
|
22
|
+
export declare function generateAdminNotificationEmail(booking: BookingEmailData): {
|
|
23
|
+
subject: string;
|
|
24
|
+
html: string;
|
|
25
|
+
text: string;
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=booking-email.templates.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"booking-email.templates.d.ts","sourceRoot":"","sources":["../../../src/modules/booking/booking-email.templates.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAuK1D;;;GAGG;AACH,wBAAgB,8BAA8B,CAAC,OAAO,EAAE,gBAAgB,GAAG;IACzE,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd,CAmHA;AAED;;;;GAIG;AACH,wBAAgB,8BAA8B,CAAC,OAAO,EAAE,gBAAgB,GAAG;IACzE,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd,CAkJA"}
|
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Email Templates for Booking Notifications
|
|
4
|
+
*
|
|
5
|
+
* Bilingual templates (Hungarian and English) matching the existing email style.
|
|
6
|
+
* Generates both HTML and plain text versions of emails.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.generateGuestConfirmationEmail = generateGuestConfirmationEmail;
|
|
10
|
+
exports.generateAdminNotificationEmail = generateAdminNotificationEmail;
|
|
11
|
+
const config_1 = require("../../config");
|
|
12
|
+
/**
|
|
13
|
+
* Translation keys for email templates
|
|
14
|
+
*/
|
|
15
|
+
const translations = {
|
|
16
|
+
hu: {
|
|
17
|
+
// Guest confirmation
|
|
18
|
+
bookingConfirmation: 'Foglalási visszaigazolás',
|
|
19
|
+
greeting: (name) => `Kedves ${name}!`,
|
|
20
|
+
thankYou: 'Köszönjük foglalásodat! Az alábbiakban található a foglalási adataid összefoglalása:',
|
|
21
|
+
accommodation: 'Szállás',
|
|
22
|
+
accommodationName: 'Szállás neve',
|
|
23
|
+
stayDetails: 'Tartózkodás részletei',
|
|
24
|
+
checkIn: 'Érkezés',
|
|
25
|
+
checkOut: 'Távozás',
|
|
26
|
+
nights: 'Éjszakák száma',
|
|
27
|
+
nightsUnit: 'éjszaka',
|
|
28
|
+
guests: 'Vendégek száma',
|
|
29
|
+
guestsUnit: 'fő',
|
|
30
|
+
paymentInfo: 'Fizetési információ',
|
|
31
|
+
amount: 'Összeg',
|
|
32
|
+
paymentMethod: 'Fizetési mód',
|
|
33
|
+
pendingApproval: 'A foglalásod jelenleg <strong>jóváhagyásra vár</strong>. Hamarosan értesítünk a foglalásod állapotáról.',
|
|
34
|
+
pendingApprovalText: 'A foglalásod jelenleg jóváhagyásra vár. Hamarosan értesítünk a foglalásod állapotáról.',
|
|
35
|
+
contactUs: 'Ha bármilyen kérdésed van, vedd fel velünk a kapcsolatot!',
|
|
36
|
+
allRightsReserved: 'Minden jog fenntartva.',
|
|
37
|
+
// Admin notification
|
|
38
|
+
newBooking: 'Új foglalás érkezett',
|
|
39
|
+
newBookingAlert: '<strong>Figyelem!</strong> Új foglalás érkezett, amely jóváhagyásra vár.',
|
|
40
|
+
newBookingAlertText: 'Figyelem! Új foglalás érkezett, amely jóváhagyásra vár.',
|
|
41
|
+
guestDetails: 'Vendég adatai',
|
|
42
|
+
name: 'Név',
|
|
43
|
+
email: 'Email',
|
|
44
|
+
phone: 'Telefon',
|
|
45
|
+
source: 'Forrás',
|
|
46
|
+
loginToAdmin: 'Kérlek, jelentkezz be az admin felületre a foglalás jóváhagyásához vagy elutasításához.',
|
|
47
|
+
// Payment methods
|
|
48
|
+
bankTransfer: 'Banki átutalás',
|
|
49
|
+
card: 'Bankkártya',
|
|
50
|
+
cash: 'Készpénz',
|
|
51
|
+
// Sources
|
|
52
|
+
fromWebsite: 'Weboldalról',
|
|
53
|
+
fromPhone: 'Telefonon',
|
|
54
|
+
fromEmail: 'Emailben',
|
|
55
|
+
},
|
|
56
|
+
en: {
|
|
57
|
+
// Guest confirmation
|
|
58
|
+
bookingConfirmation: 'Booking Confirmation',
|
|
59
|
+
greeting: (name) => `Dear ${name},`,
|
|
60
|
+
thankYou: 'Thank you for your booking! Below is a summary of your booking details:',
|
|
61
|
+
accommodation: 'Accommodation',
|
|
62
|
+
accommodationName: 'Accommodation name',
|
|
63
|
+
stayDetails: 'Stay Details',
|
|
64
|
+
checkIn: 'Check-in',
|
|
65
|
+
checkOut: 'Check-out',
|
|
66
|
+
nights: 'Number of nights',
|
|
67
|
+
nightsUnit: 'nights',
|
|
68
|
+
guests: 'Number of guests',
|
|
69
|
+
guestsUnit: 'guests',
|
|
70
|
+
paymentInfo: 'Payment Information',
|
|
71
|
+
amount: 'Amount',
|
|
72
|
+
paymentMethod: 'Payment method',
|
|
73
|
+
pendingApproval: 'Your booking is currently <strong>pending approval</strong>. We will notify you about the status of your booking soon.',
|
|
74
|
+
pendingApprovalText: 'Your booking is currently pending approval. We will notify you about the status of your booking soon.',
|
|
75
|
+
contactUs: 'If you have any questions, please contact us!',
|
|
76
|
+
allRightsReserved: 'All rights reserved.',
|
|
77
|
+
// Admin notification
|
|
78
|
+
newBooking: 'New Booking Received',
|
|
79
|
+
newBookingAlert: '<strong>Attention!</strong> A new booking has been received and is pending approval.',
|
|
80
|
+
newBookingAlertText: 'Attention! A new booking has been received and is pending approval.',
|
|
81
|
+
guestDetails: 'Guest Details',
|
|
82
|
+
name: 'Name',
|
|
83
|
+
email: 'Email',
|
|
84
|
+
phone: 'Phone',
|
|
85
|
+
source: 'Source',
|
|
86
|
+
loginToAdmin: 'Please log in to the admin panel to approve or reject the booking.',
|
|
87
|
+
// Payment methods
|
|
88
|
+
bankTransfer: 'Bank transfer',
|
|
89
|
+
card: 'Credit card',
|
|
90
|
+
cash: 'Cash',
|
|
91
|
+
// Sources
|
|
92
|
+
fromWebsite: 'Website',
|
|
93
|
+
fromPhone: 'Phone',
|
|
94
|
+
fromEmail: 'Email',
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* Get language from booking data, default to Hungarian
|
|
99
|
+
*/
|
|
100
|
+
function getLanguage(booking) {
|
|
101
|
+
return booking.guest.language || 'hu';
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Extract display name from I18n text object or string
|
|
105
|
+
*/
|
|
106
|
+
function getDisplayName(name, lang) {
|
|
107
|
+
if (typeof name === 'string')
|
|
108
|
+
return name;
|
|
109
|
+
return (lang === 'en' ? name.en || name.hu : name.hu || name.en) || 'Accommodation';
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Format ISO date string for display
|
|
113
|
+
*/
|
|
114
|
+
function formatDate(isoDate, lang) {
|
|
115
|
+
const date = new Date(isoDate);
|
|
116
|
+
const locale = lang === 'en' ? 'en-GB' : 'hu-HU';
|
|
117
|
+
return date.toLocaleDateString(locale, {
|
|
118
|
+
year: 'numeric',
|
|
119
|
+
month: 'long',
|
|
120
|
+
day: 'numeric',
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Format currency for display
|
|
125
|
+
*/
|
|
126
|
+
function formatPrice(amount, currency, lang) {
|
|
127
|
+
const locale = lang === 'en' ? 'en-GB' : 'hu-HU';
|
|
128
|
+
return new Intl.NumberFormat(locale, {
|
|
129
|
+
style: 'currency',
|
|
130
|
+
currency: currency,
|
|
131
|
+
}).format(amount);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Get payment method display text
|
|
135
|
+
*/
|
|
136
|
+
function getPaymentMethodText(method, lang) {
|
|
137
|
+
const t = translations[lang];
|
|
138
|
+
switch (method) {
|
|
139
|
+
case 'bank-transfer':
|
|
140
|
+
return t.bankTransfer;
|
|
141
|
+
case 'card':
|
|
142
|
+
return t.card;
|
|
143
|
+
case 'cash':
|
|
144
|
+
return t.cash;
|
|
145
|
+
default:
|
|
146
|
+
return method;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Get booking source display text
|
|
151
|
+
*/
|
|
152
|
+
function getSourceText(source, lang) {
|
|
153
|
+
const t = translations[lang];
|
|
154
|
+
switch (source) {
|
|
155
|
+
case 'site':
|
|
156
|
+
return t.fromWebsite;
|
|
157
|
+
case 'booking.com':
|
|
158
|
+
return 'Booking.com';
|
|
159
|
+
case 'airbnb':
|
|
160
|
+
return 'Airbnb';
|
|
161
|
+
case 'phone':
|
|
162
|
+
return t.fromPhone;
|
|
163
|
+
case 'email':
|
|
164
|
+
return t.fromEmail;
|
|
165
|
+
default:
|
|
166
|
+
return source;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Generate guest confirmation email
|
|
171
|
+
* Sent to the guest after successful booking submission
|
|
172
|
+
*/
|
|
173
|
+
function generateGuestConfirmationEmail(booking) {
|
|
174
|
+
const config = (0, config_1.getConfig)();
|
|
175
|
+
const lang = getLanguage(booking);
|
|
176
|
+
const t = translations[lang];
|
|
177
|
+
const accommodationName = getDisplayName(booking.accommodation.name, lang);
|
|
178
|
+
const guestName = `${booking.guest.firstName} ${booking.guest.lastName}`;
|
|
179
|
+
const currentYear = new Date().getFullYear();
|
|
180
|
+
const subject = `${t.bookingConfirmation} - ${accommodationName}`;
|
|
181
|
+
const html = `
|
|
182
|
+
<!DOCTYPE html>
|
|
183
|
+
<html>
|
|
184
|
+
<head>
|
|
185
|
+
<meta charset="utf-8">
|
|
186
|
+
<style>
|
|
187
|
+
body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
|
|
188
|
+
.container { max-width: 600px; margin: 0 auto; padding: 20px; }
|
|
189
|
+
.header { background-color: #4CAF50; color: white; padding: 20px; text-align: center; }
|
|
190
|
+
.content { padding: 20px; background-color: #f9f9f9; }
|
|
191
|
+
.details { background-color: white; padding: 15px; margin: 15px 0; border-radius: 4px; }
|
|
192
|
+
.detail-row { display: flex; justify-content: space-between; padding: 8px 0; border-bottom: 1px solid #eee; }
|
|
193
|
+
.detail-label { font-weight: bold; color: #555; }
|
|
194
|
+
.footer { padding: 20px; text-align: center; color: #777; font-size: 12px; }
|
|
195
|
+
.highlight { color: #4CAF50; font-weight: bold; }
|
|
196
|
+
h3 { margin-top: 0; color: #333; }
|
|
197
|
+
</style>
|
|
198
|
+
</head>
|
|
199
|
+
<body>
|
|
200
|
+
<div class="container">
|
|
201
|
+
<div class="header">
|
|
202
|
+
<h1>${config.appName}</h1>
|
|
203
|
+
<h2>${t.bookingConfirmation}</h2>
|
|
204
|
+
</div>
|
|
205
|
+
<div class="content">
|
|
206
|
+
<p>${t.greeting(guestName)}</p>
|
|
207
|
+
<p>${t.thankYou}</p>
|
|
208
|
+
|
|
209
|
+
<div class="details">
|
|
210
|
+
<h3>${t.accommodation}</h3>
|
|
211
|
+
<div class="detail-row">
|
|
212
|
+
<span class="detail-label">${t.accommodationName}:</span>
|
|
213
|
+
<span>${accommodationName}</span>
|
|
214
|
+
</div>
|
|
215
|
+
</div>
|
|
216
|
+
|
|
217
|
+
<div class="details">
|
|
218
|
+
<h3>${t.stayDetails}</h3>
|
|
219
|
+
<div class="detail-row">
|
|
220
|
+
<span class="detail-label">${t.checkIn}:</span>
|
|
221
|
+
<span class="highlight">${formatDate(booking.stay.checkIn, lang)}</span>
|
|
222
|
+
</div>
|
|
223
|
+
<div class="detail-row">
|
|
224
|
+
<span class="detail-label">${t.checkOut}:</span>
|
|
225
|
+
<span class="highlight">${formatDate(booking.stay.checkOut, lang)}</span>
|
|
226
|
+
</div>
|
|
227
|
+
<div class="detail-row">
|
|
228
|
+
<span class="detail-label">${t.nights}:</span>
|
|
229
|
+
<span>${booking.stay.nights} ${t.nightsUnit}</span>
|
|
230
|
+
</div>
|
|
231
|
+
<div class="detail-row">
|
|
232
|
+
<span class="detail-label">${t.guests}:</span>
|
|
233
|
+
<span>${booking.stay.guestCount} ${t.guestsUnit}</span>
|
|
234
|
+
</div>
|
|
235
|
+
</div>
|
|
236
|
+
|
|
237
|
+
<div class="details">
|
|
238
|
+
<h3>${t.paymentInfo}</h3>
|
|
239
|
+
<div class="detail-row">
|
|
240
|
+
<span class="detail-label">${t.amount}:</span>
|
|
241
|
+
<span class="highlight">${formatPrice(booking.priceDetail.totalPrice, booking.priceDetail.currency, lang)}</span>
|
|
242
|
+
</div>
|
|
243
|
+
<div class="detail-row">
|
|
244
|
+
<span class="detail-label">${t.paymentMethod}:</span>
|
|
245
|
+
<span>${getPaymentMethodText(booking.payment.method, lang)}</span>
|
|
246
|
+
</div>
|
|
247
|
+
</div>
|
|
248
|
+
|
|
249
|
+
<p>${t.pendingApproval}</p>
|
|
250
|
+
<p>${t.contactUs}</p>
|
|
251
|
+
</div>
|
|
252
|
+
<div class="footer">
|
|
253
|
+
<p>© ${currentYear} ${config.appName}. ${t.allRightsReserved}</p>
|
|
254
|
+
</div>
|
|
255
|
+
</div>
|
|
256
|
+
</body>
|
|
257
|
+
</html>
|
|
258
|
+
`;
|
|
259
|
+
const text = `
|
|
260
|
+
${t.greeting(guestName)}
|
|
261
|
+
|
|
262
|
+
${t.thankYou}
|
|
263
|
+
|
|
264
|
+
${t.accommodation.toUpperCase()}
|
|
265
|
+
${t.accommodationName}: ${accommodationName}
|
|
266
|
+
|
|
267
|
+
${t.stayDetails.toUpperCase()}
|
|
268
|
+
${t.checkIn}: ${formatDate(booking.stay.checkIn, lang)}
|
|
269
|
+
${t.checkOut}: ${formatDate(booking.stay.checkOut, lang)}
|
|
270
|
+
${t.nights}: ${booking.stay.nights} ${t.nightsUnit}
|
|
271
|
+
${t.guests}: ${booking.stay.guestCount} ${t.guestsUnit}
|
|
272
|
+
|
|
273
|
+
${t.paymentInfo.toUpperCase()}
|
|
274
|
+
${t.amount}: ${formatPrice(booking.priceDetail.totalPrice, booking.priceDetail.currency, lang)}
|
|
275
|
+
${t.paymentMethod}: ${getPaymentMethodText(booking.payment.method, lang)}
|
|
276
|
+
|
|
277
|
+
${t.pendingApprovalText}
|
|
278
|
+
|
|
279
|
+
${t.contactUs}
|
|
280
|
+
|
|
281
|
+
© ${currentYear} ${config.appName}. ${t.allRightsReserved}
|
|
282
|
+
`.trim();
|
|
283
|
+
return { subject, html, text };
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Generate admin/owner notification email
|
|
287
|
+
* Sent to property owner when a new booking is submitted
|
|
288
|
+
* Admin emails are always in Hungarian
|
|
289
|
+
*/
|
|
290
|
+
function generateAdminNotificationEmail(booking) {
|
|
291
|
+
const config = (0, config_1.getConfig)();
|
|
292
|
+
const lang = 'hu'; // Admin emails always in Hungarian
|
|
293
|
+
const t = translations[lang];
|
|
294
|
+
const accommodationName = getDisplayName(booking.accommodation.name, lang);
|
|
295
|
+
const guestName = `${booking.guest.firstName} ${booking.guest.lastName}`;
|
|
296
|
+
const currentYear = new Date().getFullYear();
|
|
297
|
+
const subject = `${t.newBooking} - ${accommodationName}`;
|
|
298
|
+
const html = `
|
|
299
|
+
<!DOCTYPE html>
|
|
300
|
+
<html>
|
|
301
|
+
<head>
|
|
302
|
+
<meta charset="utf-8">
|
|
303
|
+
<style>
|
|
304
|
+
body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
|
|
305
|
+
.container { max-width: 600px; margin: 0 auto; padding: 20px; }
|
|
306
|
+
.header { background-color: #2196F3; color: white; padding: 20px; text-align: center; }
|
|
307
|
+
.content { padding: 20px; background-color: #f9f9f9; }
|
|
308
|
+
.details { background-color: white; padding: 15px; margin: 15px 0; border-radius: 4px; }
|
|
309
|
+
.detail-row { display: flex; justify-content: space-between; padding: 8px 0; border-bottom: 1px solid #eee; }
|
|
310
|
+
.detail-label { font-weight: bold; color: #555; }
|
|
311
|
+
.footer { padding: 20px; text-align: center; color: #777; font-size: 12px; }
|
|
312
|
+
.highlight { color: #2196F3; font-weight: bold; }
|
|
313
|
+
.alert { background-color: #FFF3CD; border: 1px solid #FFECB5; padding: 15px; border-radius: 4px; margin: 15px 0; }
|
|
314
|
+
h3 { margin-top: 0; color: #333; }
|
|
315
|
+
</style>
|
|
316
|
+
</head>
|
|
317
|
+
<body>
|
|
318
|
+
<div class="container">
|
|
319
|
+
<div class="header">
|
|
320
|
+
<h1>${config.appName}</h1>
|
|
321
|
+
<h2>${t.newBooking}!</h2>
|
|
322
|
+
</div>
|
|
323
|
+
<div class="content">
|
|
324
|
+
<div class="alert">
|
|
325
|
+
${t.newBookingAlert}
|
|
326
|
+
</div>
|
|
327
|
+
|
|
328
|
+
<div class="details">
|
|
329
|
+
<h3>${t.guestDetails}</h3>
|
|
330
|
+
<div class="detail-row">
|
|
331
|
+
<span class="detail-label">${t.name}:</span>
|
|
332
|
+
<span class="highlight">${guestName}</span>
|
|
333
|
+
</div>
|
|
334
|
+
<div class="detail-row">
|
|
335
|
+
<span class="detail-label">${t.email}:</span>
|
|
336
|
+
<span>${booking.guest.email}</span>
|
|
337
|
+
</div>
|
|
338
|
+
${booking.guest.phoneNumber
|
|
339
|
+
? `
|
|
340
|
+
<div class="detail-row">
|
|
341
|
+
<span class="detail-label">${t.phone}:</span>
|
|
342
|
+
<span>${booking.guest.phoneNumber}</span>
|
|
343
|
+
</div>
|
|
344
|
+
`
|
|
345
|
+
: ''}
|
|
346
|
+
</div>
|
|
347
|
+
|
|
348
|
+
<div class="details">
|
|
349
|
+
<h3>${t.accommodation}</h3>
|
|
350
|
+
<div class="detail-row">
|
|
351
|
+
<span class="detail-label">${t.accommodationName}:</span>
|
|
352
|
+
<span>${accommodationName}</span>
|
|
353
|
+
</div>
|
|
354
|
+
<div class="detail-row">
|
|
355
|
+
<span class="detail-label">${t.source}:</span>
|
|
356
|
+
<span>${getSourceText(booking.source, lang)}</span>
|
|
357
|
+
</div>
|
|
358
|
+
</div>
|
|
359
|
+
|
|
360
|
+
<div class="details">
|
|
361
|
+
<h3>${t.stayDetails}</h3>
|
|
362
|
+
<div class="detail-row">
|
|
363
|
+
<span class="detail-label">${t.checkIn}:</span>
|
|
364
|
+
<span class="highlight">${formatDate(booking.stay.checkIn, lang)}</span>
|
|
365
|
+
</div>
|
|
366
|
+
<div class="detail-row">
|
|
367
|
+
<span class="detail-label">${t.checkOut}:</span>
|
|
368
|
+
<span class="highlight">${formatDate(booking.stay.checkOut, lang)}</span>
|
|
369
|
+
</div>
|
|
370
|
+
<div class="detail-row">
|
|
371
|
+
<span class="detail-label">${t.nights}:</span>
|
|
372
|
+
<span>${booking.stay.nights} ${t.nightsUnit}</span>
|
|
373
|
+
</div>
|
|
374
|
+
<div class="detail-row">
|
|
375
|
+
<span class="detail-label">${t.guests}:</span>
|
|
376
|
+
<span>${booking.stay.guestCount} ${t.guestsUnit}</span>
|
|
377
|
+
</div>
|
|
378
|
+
</div>
|
|
379
|
+
|
|
380
|
+
<div class="details">
|
|
381
|
+
<h3>${t.paymentInfo}</h3>
|
|
382
|
+
<div class="detail-row">
|
|
383
|
+
<span class="detail-label">${t.amount}:</span>
|
|
384
|
+
<span class="highlight">${formatPrice(booking.priceDetail.totalPrice, booking.priceDetail.currency, lang)}</span>
|
|
385
|
+
</div>
|
|
386
|
+
<div class="detail-row">
|
|
387
|
+
<span class="detail-label">${t.paymentMethod}:</span>
|
|
388
|
+
<span>${getPaymentMethodText(booking.payment.method, lang)}</span>
|
|
389
|
+
</div>
|
|
390
|
+
</div>
|
|
391
|
+
|
|
392
|
+
<p>${t.loginToAdmin}</p>
|
|
393
|
+
</div>
|
|
394
|
+
<div class="footer">
|
|
395
|
+
<p>© ${currentYear} ${config.appName}. ${t.allRightsReserved}</p>
|
|
396
|
+
</div>
|
|
397
|
+
</div>
|
|
398
|
+
</body>
|
|
399
|
+
</html>
|
|
400
|
+
`;
|
|
401
|
+
const text = `
|
|
402
|
+
${t.newBooking.toUpperCase()}!
|
|
403
|
+
|
|
404
|
+
${t.newBookingAlertText}
|
|
405
|
+
|
|
406
|
+
${t.guestDetails.toUpperCase()}
|
|
407
|
+
${t.name}: ${guestName}
|
|
408
|
+
${t.email}: ${booking.guest.email}
|
|
409
|
+
${booking.guest.phoneNumber ? `${t.phone}: ${booking.guest.phoneNumber}` : ''}
|
|
410
|
+
|
|
411
|
+
${t.accommodation.toUpperCase()}
|
|
412
|
+
${t.accommodationName}: ${accommodationName}
|
|
413
|
+
${t.source}: ${getSourceText(booking.source, lang)}
|
|
414
|
+
|
|
415
|
+
${t.stayDetails.toUpperCase()}
|
|
416
|
+
${t.checkIn}: ${formatDate(booking.stay.checkIn, lang)}
|
|
417
|
+
${t.checkOut}: ${formatDate(booking.stay.checkOut, lang)}
|
|
418
|
+
${t.nights}: ${booking.stay.nights} ${t.nightsUnit}
|
|
419
|
+
${t.guests}: ${booking.stay.guestCount} ${t.guestsUnit}
|
|
420
|
+
|
|
421
|
+
${t.paymentInfo.toUpperCase()}
|
|
422
|
+
${t.amount}: ${formatPrice(booking.priceDetail.totalPrice, booking.priceDetail.currency, lang)}
|
|
423
|
+
${t.paymentMethod}: ${getPaymentMethodText(booking.payment.method, lang)}
|
|
424
|
+
|
|
425
|
+
${t.loginToAdmin}
|
|
426
|
+
|
|
427
|
+
© ${currentYear} ${config.appName}. ${t.allRightsReserved}
|
|
428
|
+
`.trim();
|
|
429
|
+
return { subject, html, text };
|
|
430
|
+
}
|
|
431
|
+
//# sourceMappingURL=booking-email.templates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"booking-email.templates.js","sourceRoot":"","sources":["../../../src/modules/booking/booking-email.templates.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Booking Email Trigger Factory
|
|
3
|
+
*
|
|
4
|
+
* Creates Firestore triggers for sending booking confirmation emails.
|
|
5
|
+
* Follows the same factory pattern as effective-permissions.triggers.ts.
|
|
6
|
+
*/
|
|
7
|
+
import { BookingEmailConfig } from './booking-email.models';
|
|
8
|
+
/**
|
|
9
|
+
* Create booking email triggers
|
|
10
|
+
*
|
|
11
|
+
* @param config - Configuration for the booking email system
|
|
12
|
+
* @returns Object containing the trigger functions
|
|
13
|
+
*/
|
|
14
|
+
export declare function createBookingEmailTriggers(config?: Partial<BookingEmailConfig>): {
|
|
15
|
+
/**
|
|
16
|
+
* Trigger when a new booking is created
|
|
17
|
+
* Sends confirmation email to guest and notification to admin/owner
|
|
18
|
+
*/
|
|
19
|
+
onBookingCreated: import("firebase-functions").CloudFunction<import("firebase-functions/v2/firestore").FirestoreEvent<import("firebase-functions/v2/firestore").QueryDocumentSnapshot | undefined, {
|
|
20
|
+
bookingId: string;
|
|
21
|
+
}>>;
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=booking-email.triggers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"booking-email.triggers.d.ts","sourceRoot":"","sources":["../../../src/modules/booking/booking-email.triggers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,EAEL,kBAAkB,EAEnB,MAAM,wBAAwB,CAAC;AAqDhC;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,GAAE,OAAO,CAAC,kBAAkB,CAAM;IAI/E;;;OAGG;;;;EAkGN"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Booking Email Trigger Factory
|
|
4
|
+
*
|
|
5
|
+
* Creates Firestore triggers for sending booking confirmation emails.
|
|
6
|
+
* Follows the same factory pattern as effective-permissions.triggers.ts.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.createBookingEmailTriggers = createBookingEmailTriggers;
|
|
10
|
+
const firebase_functions_1 = require("firebase-functions");
|
|
11
|
+
const firestore_1 = require("firebase-functions/v2/firestore");
|
|
12
|
+
const email_service_1 = require("../email/email.service");
|
|
13
|
+
const email_validator_1 = require("../email/email.validator");
|
|
14
|
+
const booking_email_models_1 = require("./booking-email.models");
|
|
15
|
+
const booking_email_templates_1 = require("./booking-email.templates");
|
|
16
|
+
/**
|
|
17
|
+
* Validate booking data has required fields for sending email
|
|
18
|
+
*/
|
|
19
|
+
function validateBookingForEmail(booking) {
|
|
20
|
+
var _a, _b, _c, _d, _e;
|
|
21
|
+
if (!((_a = booking.guest) === null || _a === void 0 ? void 0 : _a.email)) {
|
|
22
|
+
return 'Booking is missing guest email';
|
|
23
|
+
}
|
|
24
|
+
if (!(0, email_validator_1.validateEmail)(booking.guest.email)) {
|
|
25
|
+
return `Invalid guest email: ${booking.guest.email}`;
|
|
26
|
+
}
|
|
27
|
+
if (!((_b = booking.accommodation) === null || _b === void 0 ? void 0 : _b.name)) {
|
|
28
|
+
return 'Booking is missing accommodation name';
|
|
29
|
+
}
|
|
30
|
+
if (!((_c = booking.stay) === null || _c === void 0 ? void 0 : _c.checkIn) || !((_d = booking.stay) === null || _d === void 0 ? void 0 : _d.checkOut)) {
|
|
31
|
+
return 'Booking is missing stay dates';
|
|
32
|
+
}
|
|
33
|
+
if (!((_e = booking.priceDetail) === null || _e === void 0 ? void 0 : _e.totalPrice)) {
|
|
34
|
+
return 'Booking is missing price details';
|
|
35
|
+
}
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Get admin/owner email for notification
|
|
40
|
+
* Falls back to config fallbackAdminEmail if accommodation contact is missing
|
|
41
|
+
*/
|
|
42
|
+
function getAdminEmail(booking, cfg) {
|
|
43
|
+
var _a, _b;
|
|
44
|
+
// Try accommodation contact email first
|
|
45
|
+
const contactEmail = (_b = (_a = booking.accommodation) === null || _a === void 0 ? void 0 : _a.contact) === null || _b === void 0 ? void 0 : _b.email;
|
|
46
|
+
if (contactEmail && (0, email_validator_1.validateEmail)(contactEmail)) {
|
|
47
|
+
return contactEmail;
|
|
48
|
+
}
|
|
49
|
+
// Fallback to configured admin email
|
|
50
|
+
if (cfg.fallbackAdminEmail && (0, email_validator_1.validateEmail)(cfg.fallbackAdminEmail)) {
|
|
51
|
+
return cfg.fallbackAdminEmail;
|
|
52
|
+
}
|
|
53
|
+
// Try environment variable as last resort
|
|
54
|
+
const envAdminEmail = process.env.ADMIN_NOTIFICATION_EMAIL;
|
|
55
|
+
if (envAdminEmail && (0, email_validator_1.validateEmail)(envAdminEmail)) {
|
|
56
|
+
return envAdminEmail;
|
|
57
|
+
}
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Create booking email triggers
|
|
62
|
+
*
|
|
63
|
+
* @param config - Configuration for the booking email system
|
|
64
|
+
* @returns Object containing the trigger functions
|
|
65
|
+
*/
|
|
66
|
+
function createBookingEmailTriggers(config = {}) {
|
|
67
|
+
const cfg = Object.assign(Object.assign({}, booking_email_models_1.DEFAULT_BOOKING_EMAIL_CONFIG), config);
|
|
68
|
+
return {
|
|
69
|
+
/**
|
|
70
|
+
* Trigger when a new booking is created
|
|
71
|
+
* Sends confirmation email to guest and notification to admin/owner
|
|
72
|
+
*/
|
|
73
|
+
onBookingCreated: (0, firestore_1.onDocumentCreated)({
|
|
74
|
+
document: `${cfg.bookingCollection}/{bookingId}`,
|
|
75
|
+
region: cfg.region,
|
|
76
|
+
maxInstances: cfg.maxInstances,
|
|
77
|
+
}, async (event) => {
|
|
78
|
+
var _a, _b;
|
|
79
|
+
const bookingId = event.params.bookingId;
|
|
80
|
+
const bookingData = (_a = event.data) === null || _a === void 0 ? void 0 : _a.data();
|
|
81
|
+
if (!bookingData) {
|
|
82
|
+
firebase_functions_1.logger.warn(`[BookingEmail] No data for booking ${bookingId}`);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
firebase_functions_1.logger.info(`[BookingEmail] Processing new booking: ${bookingId}`);
|
|
86
|
+
// Only send emails for user-submitted bookings (pending_approval state)
|
|
87
|
+
// Admin-created bookings (confirmed state) might not need the same notification
|
|
88
|
+
const workflowState = (_b = bookingData.workflow) === null || _b === void 0 ? void 0 : _b.currentState;
|
|
89
|
+
if (workflowState && workflowState !== 'pending_approval') {
|
|
90
|
+
firebase_functions_1.logger.info(`[BookingEmail] Skipping email for booking ${bookingId} with state: ${workflowState}`);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
// Validate booking data
|
|
94
|
+
const validationError = validateBookingForEmail(bookingData);
|
|
95
|
+
if (validationError) {
|
|
96
|
+
firebase_functions_1.logger.error(`[BookingEmail] Validation failed for ${bookingId}: ${validationError}`);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
// Add booking ID to data for reference
|
|
100
|
+
const booking = Object.assign(Object.assign({}, bookingData), { uid: bookingId });
|
|
101
|
+
// Send guest confirmation email
|
|
102
|
+
try {
|
|
103
|
+
const guestEmail = (0, booking_email_templates_1.generateGuestConfirmationEmail)(booking);
|
|
104
|
+
const guestResult = await email_service_1.emailService.sendEmail({
|
|
105
|
+
to: booking.guest.email,
|
|
106
|
+
subject: guestEmail.subject,
|
|
107
|
+
html: guestEmail.html,
|
|
108
|
+
text: guestEmail.text,
|
|
109
|
+
});
|
|
110
|
+
if (guestResult.success) {
|
|
111
|
+
firebase_functions_1.logger.info(`[BookingEmail] Guest confirmation sent to ${booking.guest.email} for booking ${bookingId}`);
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
firebase_functions_1.logger.error(`[BookingEmail] Failed to send guest email for ${bookingId}: ${guestResult.error}`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
firebase_functions_1.logger.error(`[BookingEmail] Error sending guest email for ${bookingId}:`, error);
|
|
119
|
+
}
|
|
120
|
+
// Send admin/owner notification email
|
|
121
|
+
if (cfg.adminNotificationEnabled) {
|
|
122
|
+
const adminEmail = getAdminEmail(booking, cfg);
|
|
123
|
+
if (adminEmail) {
|
|
124
|
+
try {
|
|
125
|
+
const adminEmailContent = (0, booking_email_templates_1.generateAdminNotificationEmail)(booking);
|
|
126
|
+
const adminResult = await email_service_1.emailService.sendEmail({
|
|
127
|
+
to: adminEmail,
|
|
128
|
+
subject: adminEmailContent.subject,
|
|
129
|
+
html: adminEmailContent.html,
|
|
130
|
+
text: adminEmailContent.text,
|
|
131
|
+
});
|
|
132
|
+
if (adminResult.success) {
|
|
133
|
+
firebase_functions_1.logger.info(`[BookingEmail] Admin notification sent to ${adminEmail} for booking ${bookingId}`);
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
firebase_functions_1.logger.error(`[BookingEmail] Failed to send admin email for ${bookingId}: ${adminResult.error}`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
firebase_functions_1.logger.error(`[BookingEmail] Error sending admin email for ${bookingId}:`, error);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
firebase_functions_1.logger.warn(`[BookingEmail] No admin email available for booking ${bookingId}, skipping notification`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
firebase_functions_1.logger.info(`[BookingEmail] Completed processing booking ${bookingId}`);
|
|
148
|
+
}),
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=booking-email.triggers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"booking-email.triggers.js","sourceRoot":"","sources":["../../../src/modules/booking/booking-email.triggers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/modules/booking/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Booking Module
|
|
4
|
+
*
|
|
5
|
+
* Firebase Cloud Functions for booking-related operations.
|
|
6
|
+
*/
|
|
7
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
+
if (k2 === undefined) k2 = k;
|
|
9
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(o, k2, desc);
|
|
14
|
+
}) : (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
o[k2] = m[k];
|
|
17
|
+
}));
|
|
18
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
19
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
20
|
+
};
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
__exportStar(require("./booking-email.models"), exports);
|
|
23
|
+
__exportStar(require("./booking-email.templates"), exports);
|
|
24
|
+
__exportStar(require("./booking-email.triggers"), exports);
|
|
25
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/modules/booking/index.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;;;;;;;;;;;;;;AAEH,yDAAuC;AACvC,4DAA0C;AAC1C,2DAAyC"}
|
package/package.json
CHANGED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* User Auth Triggers
|
|
3
|
-
*
|
|
4
|
-
* Firebase Auth triggers that automatically create/sync user documents
|
|
5
|
-
* when users sign up with any provider (email, Google, etc.)
|
|
6
|
-
*/
|
|
7
|
-
import { beforeUserCreated, beforeUserSignedIn } from 'firebase-functions/v2/identity';
|
|
8
|
-
export interface UserAuthTriggersConfig {
|
|
9
|
-
region?: string;
|
|
10
|
-
defaultRoleId?: string;
|
|
11
|
-
firestoreDatabaseId?: string;
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* Create a factory for the beforeUserCreated trigger
|
|
15
|
-
* This trigger runs before a new user is created in Firebase Auth
|
|
16
|
-
* It can be used to validate or modify the user data
|
|
17
|
-
*/
|
|
18
|
-
export declare function createBeforeUserCreatedFunction(triggerConfig?: UserAuthTriggersConfig): ReturnType<typeof beforeUserCreated>;
|
|
19
|
-
/**
|
|
20
|
-
* Create a factory for the beforeUserSignedIn trigger
|
|
21
|
-
* This trigger runs every time a user signs in
|
|
22
|
-
* We use it to ensure the user document exists in Firestore
|
|
23
|
-
*/
|
|
24
|
-
export declare function createBeforeUserSignedInFunction(triggerConfig?: UserAuthTriggersConfig): ReturnType<typeof beforeUserSignedIn>;
|
|
25
|
-
//# sourceMappingURL=user-auth.triggers.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"user-auth.triggers.d.ts","sourceRoot":"","sources":["../../../src/modules/user/user-auth.triggers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAKvF,MAAM,WAAW,sBAAsB;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAWD;;;;GAIG;AAEH,wBAAgB,+BAA+B,CAC7C,aAAa,GAAE,sBAA2B,GACzC,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAoBtC;AAED;;;;GAIG;AAEH,wBAAgB,gCAAgC,CAC9C,aAAa,GAAE,sBAA2B,GACzC,UAAU,CAAC,OAAO,kBAAkB,CAAC,CA0EvC"}
|
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* User Auth Triggers
|
|
4
|
-
*
|
|
5
|
-
* Firebase Auth triggers that automatically create/sync user documents
|
|
6
|
-
* when users sign up with any provider (email, Google, etc.)
|
|
7
|
-
*/
|
|
8
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
-
if (k2 === undefined) k2 = k;
|
|
10
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
-
}
|
|
14
|
-
Object.defineProperty(o, k2, desc);
|
|
15
|
-
}) : (function(o, m, k, k2) {
|
|
16
|
-
if (k2 === undefined) k2 = k;
|
|
17
|
-
o[k2] = m[k];
|
|
18
|
-
}));
|
|
19
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
-
}) : function(o, v) {
|
|
22
|
-
o["default"] = v;
|
|
23
|
-
});
|
|
24
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
-
var ownKeys = function(o) {
|
|
26
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
-
var ar = [];
|
|
28
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
-
return ar;
|
|
30
|
-
};
|
|
31
|
-
return ownKeys(o);
|
|
32
|
-
};
|
|
33
|
-
return function (mod) {
|
|
34
|
-
if (mod && mod.__esModule) return mod;
|
|
35
|
-
var result = {};
|
|
36
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
-
__setModuleDefault(result, mod);
|
|
38
|
-
return result;
|
|
39
|
-
};
|
|
40
|
-
})();
|
|
41
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
-
exports.createBeforeUserCreatedFunction = createBeforeUserCreatedFunction;
|
|
43
|
-
exports.createBeforeUserSignedInFunction = createBeforeUserSignedInFunction;
|
|
44
|
-
const firestore_1 = require("firebase-admin/firestore");
|
|
45
|
-
const logger = __importStar(require("firebase-functions/logger"));
|
|
46
|
-
const identity_1 = require("firebase-functions/v2/identity");
|
|
47
|
-
const config_1 = require("../../config");
|
|
48
|
-
const user_models_1 = require("./user.models");
|
|
49
|
-
/**
|
|
50
|
-
* Get Firestore instance based on config
|
|
51
|
-
*/
|
|
52
|
-
function getFirestoreInstance(config) {
|
|
53
|
-
return config.firestoreDatabaseId
|
|
54
|
-
? (0, firestore_1.getFirestore)(config.firestoreDatabaseId)
|
|
55
|
-
: (0, firestore_1.getFirestore)();
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* Create a factory for the beforeUserCreated trigger
|
|
59
|
-
* This trigger runs before a new user is created in Firebase Auth
|
|
60
|
-
* It can be used to validate or modify the user data
|
|
61
|
-
*/
|
|
62
|
-
// Return type is BlockingFunction from firebase-functions, using ReturnType for better compatibility
|
|
63
|
-
function createBeforeUserCreatedFunction(triggerConfig = {}) {
|
|
64
|
-
const config = (0, config_1.getConfig)();
|
|
65
|
-
const region = triggerConfig.region || config.region;
|
|
66
|
-
return (0, identity_1.beforeUserCreated)({ region }, async (event) => {
|
|
67
|
-
var _a;
|
|
68
|
-
const user = event.data;
|
|
69
|
-
if (!user) {
|
|
70
|
-
logger.warn('beforeUserCreated: No user data in event');
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
logger.info('beforeUserCreated trigger fired:', {
|
|
74
|
-
uid: user.uid,
|
|
75
|
-
email: user.email,
|
|
76
|
-
provider: (_a = event.credential) === null || _a === void 0 ? void 0 : _a.providerId,
|
|
77
|
-
});
|
|
78
|
-
// Can add validation logic here if needed
|
|
79
|
-
// Return nothing to allow user creation to proceed
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* Create a factory for the beforeUserSignedIn trigger
|
|
84
|
-
* This trigger runs every time a user signs in
|
|
85
|
-
* We use it to ensure the user document exists in Firestore
|
|
86
|
-
*/
|
|
87
|
-
// Return type is BlockingFunction from firebase-functions, using ReturnType for better compatibility
|
|
88
|
-
function createBeforeUserSignedInFunction(triggerConfig = {}) {
|
|
89
|
-
const config = (0, config_1.getConfig)();
|
|
90
|
-
const region = triggerConfig.region || config.region;
|
|
91
|
-
return (0, identity_1.beforeUserSignedIn)({ region }, async (event) => {
|
|
92
|
-
var _a, _b;
|
|
93
|
-
const user = event.data;
|
|
94
|
-
if (!user) {
|
|
95
|
-
logger.warn('beforeUserSignedIn: No user data in event');
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
const providerId = ((_a = event.credential) === null || _a === void 0 ? void 0 : _a.providerId) || 'unknown';
|
|
99
|
-
logger.info('beforeUserSignedIn trigger fired:', {
|
|
100
|
-
uid: user.uid,
|
|
101
|
-
email: user.email,
|
|
102
|
-
provider: providerId,
|
|
103
|
-
});
|
|
104
|
-
// Check if user document exists in Firestore
|
|
105
|
-
const firestore = getFirestoreInstance(config);
|
|
106
|
-
const userDocRef = firestore.collection(user_models_1.USER_FEATURE_KEY).doc(user.uid);
|
|
107
|
-
const userDoc = await userDocRef.get();
|
|
108
|
-
if (!userDoc.exists) {
|
|
109
|
-
// Create user document for new OAuth users
|
|
110
|
-
logger.info('Creating user document for OAuth user:', user.uid);
|
|
111
|
-
const now = new Date().toISOString();
|
|
112
|
-
const defaultRoleId = triggerConfig.defaultRoleId || config.defaultUserRoleId;
|
|
113
|
-
// Parse display name into first/last name
|
|
114
|
-
const nameParts = (user.displayName || '').split(' ');
|
|
115
|
-
const firstName = nameParts[0] || '';
|
|
116
|
-
const lastName = nameParts.slice(1).join(' ') || '';
|
|
117
|
-
const userDocument = {
|
|
118
|
-
id: user.uid,
|
|
119
|
-
email: user.email || '',
|
|
120
|
-
displayName: user.displayName || ((_b = user.email) === null || _b === void 0 ? void 0 : _b.split('@')[0]) || 'User',
|
|
121
|
-
firstName,
|
|
122
|
-
lastName,
|
|
123
|
-
photoURL: user.photoURL || null,
|
|
124
|
-
phoneNumber: user.phoneNumber || null,
|
|
125
|
-
emailVerified: user.emailVerified || false,
|
|
126
|
-
authProvider: providerId,
|
|
127
|
-
roleIds: [defaultRoleId],
|
|
128
|
-
meta: {
|
|
129
|
-
createdAt: now,
|
|
130
|
-
updatedAt: now,
|
|
131
|
-
createdBy: 'auth-trigger',
|
|
132
|
-
updatedBy: 'auth-trigger',
|
|
133
|
-
},
|
|
134
|
-
};
|
|
135
|
-
await userDocRef.set(userDocument);
|
|
136
|
-
logger.info('User document created successfully:', user.uid);
|
|
137
|
-
}
|
|
138
|
-
else {
|
|
139
|
-
// Optionally update some fields for existing users
|
|
140
|
-
const existingData = userDoc.data();
|
|
141
|
-
// Update photoURL if it changed (e.g., user updated their Google profile picture)
|
|
142
|
-
if (user.photoURL && (existingData === null || existingData === void 0 ? void 0 : existingData.photoURL) !== user.photoURL) {
|
|
143
|
-
await userDocRef.update({
|
|
144
|
-
photoURL: user.photoURL,
|
|
145
|
-
'meta.updatedAt': new Date().toISOString(),
|
|
146
|
-
'meta.updatedBy': 'auth-trigger',
|
|
147
|
-
});
|
|
148
|
-
logger.info('Updated user photoURL:', user.uid);
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
// Return nothing to allow sign-in to proceed
|
|
152
|
-
});
|
|
153
|
-
}
|
|
154
|
-
//# sourceMappingURL=user-auth.triggers.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"user-auth.triggers.js","sourceRoot":"","sources":["../../../src/modules/user/user-auth.triggers.ts"],"names":[],"mappings":"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"}
|