From b84621f9b2b7161a5ad4f0b194264e9df3e65dbf Mon Sep 17 00:00:00 2001 From: dujinkim Date: Tue, 8 Jul 2025 11:23:40 +0000 Subject: (대표님) 20250708 미반영분 커밋 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/mail/mailer.ts | 146 ++++++++++++++++-------- lib/mail/sendEmail.ts | 15 ++- lib/mail/templates/letter-of-regret.hbs | 190 ++++++++++++++++++++++++++++++++ 3 files changed, 304 insertions(+), 47 deletions(-) create mode 100644 lib/mail/templates/letter-of-regret.hbs (limited to 'lib/mail') diff --git a/lib/mail/mailer.ts b/lib/mail/mailer.ts index 61201e99..0387d7dd 100644 --- a/lib/mail/mailer.ts +++ b/lib/mail/mailer.ts @@ -23,54 +23,96 @@ function registerHandlebarsHelpers() { return i18next.t(key, options.hash || {}); }); - // eq 헬퍼 등록 - 두 값을 비교 (블록 헬퍼) - handlebars.registerHelper('eq', function(a: any, b: any, options: any) { - if (a === b) { - return options.fn(this); - } else { - return options.inverse(this); + // eq 헬퍼 등록 - 인라인과 블록 헬퍼 둘 다 지원 + handlebars.registerHelper('eq', function(a: any, b: any, options?: any) { + const result = a === b; + + // 블록 헬퍼로 사용된 경우 (options가 있고 fn 함수가 있는 경우) + if (options && typeof options.fn === 'function') { + if (result) { + return options.fn(this); + } else { + return options.inverse(this); + } } + + // 인라인 헬퍼로 사용된 경우 + return result; }); - // 기타 유용한 헬퍼들 - handlebars.registerHelper('ne', function(a: any, b: any, options: any) { - if (a !== b) { - return options.fn(this); - } else { - return options.inverse(this); + // ne 헬퍼 - 인라인과 블록 헬퍼 둘 다 지원 + handlebars.registerHelper('ne', function(a: any, b: any, options?: any) { + const result = a !== b; + + if (options && typeof options.fn === 'function') { + if (result) { + return options.fn(this); + } else { + return options.inverse(this); + } } + + return result; }); - handlebars.registerHelper('gt', function(a: any, b: any, options: any) { - if (a > b) { - return options.fn(this); - } else { - return options.inverse(this); + // gt 헬퍼 - 인라인과 블록 헬퍼 둘 다 지원 + handlebars.registerHelper('gt', function(a: any, b: any, options?: any) { + const result = a > b; + + if (options && typeof options.fn === 'function') { + if (result) { + return options.fn(this); + } else { + return options.inverse(this); + } } + + return result; }); - handlebars.registerHelper('gte', function(a: any, b: any, options: any) { - if (a >= b) { - return options.fn(this); - } else { - return options.inverse(this); + // gte 헬퍼 - 인라인과 블록 헬퍼 둘 다 지원 + handlebars.registerHelper('gte', function(a: any, b: any, options?: any) { + const result = a >= b; + + if (options && typeof options.fn === 'function') { + if (result) { + return options.fn(this); + } else { + return options.inverse(this); + } } + + return result; }); - handlebars.registerHelper('lt', function(a: any, b: any, options: any) { - if (a < b) { - return options.fn(this); - } else { - return options.inverse(this); + // lt 헬퍼 - 인라인과 블록 헬퍼 둘 다 지원 + handlebars.registerHelper('lt', function(a: any, b: any, options?: any) { + const result = a < b; + + if (options && typeof options.fn === 'function') { + if (result) { + return options.fn(this); + } else { + return options.inverse(this); + } } + + return result; }); - handlebars.registerHelper('lte', function(a: any, b: any, options: any) { - if (a <= b) { - return options.fn(this); - } else { - return options.inverse(this); + // lte 헬퍼 - 인라인과 블록 헬퍼 둘 다 지원 + handlebars.registerHelper('lte', function(a: any, b: any, options?: any) { + const result = a <= b; + + if (options && typeof options.fn === 'function') { + if (result) { + return options.fn(this); + } else { + return options.inverse(this); + } } + + return result; }); // and 헬퍼 - 모든 조건이 true인지 확인 (블록 헬퍼) @@ -78,12 +120,17 @@ function registerHandlebarsHelpers() { // 마지막 인자는 Handlebars 옵션 const options = args[args.length - 1]; const values = args.slice(0, -1); + const result = values.every(Boolean); - if (values.every(Boolean)) { - return options.fn(this); - } else { - return options.inverse(this); + if (typeof options.fn === 'function') { + if (result) { + return options.fn(this); + } else { + return options.inverse(this); + } } + + return result; }); // or 헬퍼 - 하나라도 true인지 확인 (블록 헬퍼) @@ -91,21 +138,32 @@ function registerHandlebarsHelpers() { // 마지막 인자는 Handlebars 옵션 const options = args[args.length - 1]; const values = args.slice(0, -1); + const result = values.some(Boolean); - if (values.some(Boolean)) { - return options.fn(this); - } else { - return options.inverse(this); + if (typeof options.fn === 'function') { + if (result) { + return options.fn(this); + } else { + return options.inverse(this); + } } + + return result; }); // not 헬퍼 - 값 반전 (블록 헬퍼) handlebars.registerHelper('not', function(value: any, options: any) { - if (!value) { - return options.fn(this); - } else { - return options.inverse(this); + const result = !value; + + if (typeof options.fn === 'function') { + if (result) { + return options.fn(this); + } else { + return options.inverse(this); + } } + + return result; }); // formatDate 헬퍼 - 날짜 포맷팅 diff --git a/lib/mail/sendEmail.ts b/lib/mail/sendEmail.ts index 3f88cb04..b4d2707a 100644 --- a/lib/mail/sendEmail.ts +++ b/lib/mail/sendEmail.ts @@ -29,14 +29,23 @@ export async function sendEmail({ // i18n 설정 const { t, i18n } = await useTranslation(context.language ?? "en", "translation"); - // t 헬퍼만 동적으로 등록 (이미 mailer.ts에서 기본 등록되어 있지만, 언어별로 다시 등록) + // t 헬퍼를 언어별로 동적으로 재등록 (기존 헬퍼 덮어쓰기) + // 헬퍼가 이미 등록되어 있더라도 안전하게 재등록 + handlebars.unregisterHelper('t'); // 기존 헬퍼 제거 handlebars.registerHelper("t", function (key: string, options: any) { // 여기서 i18n은 로컬 인스턴스 - return i18n.t(key, options.hash || {}); + return i18n.t(key, options?.hash || {}); }); + // 템플릿 데이터에 i18n 인스턴스와 번역 함수 추가 + const templateData = { + ...context, + t: (key: string, options?: any) => i18n.t(key, options || {}), + i18n: i18n + }; + // 템플릿 컴파일 및 HTML 생성 - const html = loadTemplate(template, context); + const html = loadTemplate(template, templateData); // 이메일 발송 const result = await transporter.sendMail({ diff --git a/lib/mail/templates/letter-of-regret.hbs b/lib/mail/templates/letter-of-regret.hbs new file mode 100644 index 00000000..13fab6fc --- /dev/null +++ b/lib/mail/templates/letter-of-regret.hbs @@ -0,0 +1,190 @@ + + + + + + {{#if (eq language 'ko')}}Letter of Regret{{else}}Letter of Regret{{/if}} + + + +
+
+ +

+ {{#if (eq language 'ko')}} + 협력 제안 결과 안내서 (Letter of Regret) + {{else}} + Letter of Regret + {{/if}} +

+
+ +
+
+ {{#if (eq language 'ko')}} + {{vendorName}} 귀하 + {{else}} + Dear {{vendorName}}, + {{/if}} +
+ +
+ {{#if (eq language 'ko')}} + 안녕하십니까. {{companyName}}입니다. + {{else}} + Greetings from {{companyName}}. + {{/if}} +
+ +
+ {{#if (eq language 'ko')}} + 먼저 저희 프로젝트에 관심을 가져주시고 귀중한 시간을 할애하여 RFQ에 응답해 주신 점에 대해 깊이 감사드립니다. + {{else}} + First, we would like to express our sincere gratitude for your interest in our project and for taking the time to respond to our RFQ. + {{/if}} +
+ +
+ + {{#if (eq language 'ko')}}프로젝트 정보{{else}}Project Information{{/if}}: +
+ RFQ {{#if (eq language 'ko')}}번호{{else}}Number{{/if}}: {{rfqCode}}
+ {{#if (eq language 'ko')}}프로젝트명{{else}}Project Title{{/if}}: {{projectTitle}}
+ {{#if (eq language 'ko')}}통지일{{else}}Notification Date{{/if}}: {{dateTime}} +
+ +
+ {{#if (eq language 'ko')}} + 신중한 검토와 평가를 거쳐 진행한 결과, 아쉽게도 이번 프로젝트에서는 다른 업체와 함께 진행하기로 결정하였음을 알려드립니다. + {{else}} + After careful review and evaluation, we regret to inform you that we have decided to proceed with another vendor for this project. + {{/if}} +
+ +
+ {{#if (eq language 'ko')}} + 이번 결정이 귀하의 기술력이나 역량에 대한 평가와는 무관함을 말씀드리며, 향후 다른 프로젝트에서 함께 할 수 있는 기회가 있기를 기대합니다. + {{else}} + Please note that this decision is not a reflection of your technical capabilities or competence, and we look forward to potential collaboration opportunities in future projects. + {{/if}} +
+ +
+ {{#if (eq language 'ko')}} + 다시 한번 저희 RFQ에 참여해 주신 것에 대해 진심으로 감사드리며, 앞으로도 지속적인 관심과 협력을 부탁드립니다. + {{else}} + Once again, we sincerely thank you for your participation in our RFQ process and look forward to your continued interest and cooperation. + {{/if}} +
+ +
+ {{#if (eq language 'ko')}} + 감사합니다. + {{else}} + Thank you for your understanding. + {{/if}} +
+
+ +
+
+ {{#if (eq language 'ko')}}발신{{else}}From{{/if}}: {{companyName}} +
+
+ {{#if (eq language 'ko')}}구매팀{{else}}Procurement Department{{/if}} +
+
+ {{#if (eq language 'ko')}}일자{{else}}Date{{/if}}: {{dateTime}} +
+
+ + +
+ + \ No newline at end of file -- cgit v1.2.3