diff options
Diffstat (limited to 'lib/mail')
| -rw-r--r-- | lib/mail/sendEmail.ts | 15 | ||||
| -rw-r--r-- | lib/mail/templates/po-rfq-invite-en.hbs | 116 | ||||
| -rw-r--r-- | lib/mail/templates/po-rfq-invite-ko.hbs | 86 | ||||
| -rw-r--r-- | lib/mail/templates/rfq-notification.hbs | 166 |
4 files changed, 380 insertions, 3 deletions
diff --git a/lib/mail/sendEmail.ts b/lib/mail/sendEmail.ts index c4171082..97617e7a 100644 --- a/lib/mail/sendEmail.ts +++ b/lib/mail/sendEmail.ts @@ -7,7 +7,9 @@ interface SendEmailOptions { subject: string; template: string; // 템플릿 파일명(확장자 제외) context: Record<string, any>; // 템플릿에 주입할 데이터 - attachments?: { // NodeMailer "Attachment" 타입 + cc?: string | string[]; // cc 필드 추가 - 단일 이메일 또는 이메일 배열 + attachments?: { + // NodeMailer "Attachment" 타입 filename?: string path?: string content?: Buffer | string @@ -15,7 +17,14 @@ interface SendEmailOptions { }[] } -export async function sendEmail({ to, subject, template, context, attachments = []}: SendEmailOptions) { +export async function sendEmail({ + to, + subject, + template, + context, + cc, // cc 매개변수 추가 + attachments = [] +}: SendEmailOptions) { const { t, i18n } = await useTranslation(context.language ?? "en", "translation"); handlebars.registerHelper("t", function (key: string, options: any) { @@ -28,9 +37,9 @@ export async function sendEmail({ to, subject, template, context, attachments = await transporter.sendMail({ from: `"${process.env.Email_From_Name}" <${process.env.Email_From_Address}>`, to, + cc, // cc 필드 추가 subject, html, attachments }); } - diff --git a/lib/mail/templates/po-rfq-invite-en.hbs b/lib/mail/templates/po-rfq-invite-en.hbs new file mode 100644 index 00000000..5b47851c --- /dev/null +++ b/lib/mail/templates/po-rfq-invite-en.hbs @@ -0,0 +1,116 @@ +{{> header logoUrl=logoUrl }}
+
+<h1 style="font-size:28px; line-height:40px; margin-bottom:16px;">
+ SHI RFQ NO. : #{{rfqCode}}
+</h1>
+
+<p style="font-size:16px; line-height:32px; margin-bottom:16px;">
+ Dear Sirs,
+</p>
+
+<p style="font-size:16px; line-height:32px; margin-bottom:16px;">
+ We hope your business continuously will be thriving in the years ahead and we are pleased to send you RFQ for the subject item.
+</p>
+
+<p style="font-size:16px; line-height:32px; margin-bottom:16px;">
+ It would be appreciated if we receive your competitive quotation in compliance with the following terms and conditions
+ by the bid closing date (COB of {{DLDate}})
+ Otherwise we will consider that you have no interest on this RFQ.
+</p>
+
+<div style="margin-bottom:24px;">
+ <h2 style="font-size:20px; margin-bottom:12px;">A. Commercial terms and conditions</h2>
+ <p style="font-size:16px; line-height:24px; margin-bottom:8px;">
+ <strong>A-1 Project: {{projectName}} + Option {{projectOption}} (Validity: {{ProjectOptionValidity}})</strong>
+ <br>* Ship's Delivery date('YY.MM.DD): {{DLDate}}
+ </p>
+ <p style="font-size:16px; line-height:24px; margin-bottom:8px;">
+ <strong>A-2 Spec. & Scope of the Supply : See the attached PGS/SGS/POS</strong>
+ </p>
+ <p style="font-size:16px; line-height:24px; margin-bottom:8px;">
+ <strong>A-3 Terms of Delivery : {{incoterms}}</strong>
+ </p>
+ <p style="font-size:16px; line-height:24px; margin-bottom:8px;">
+ <strong>A-4 Estimated Delivery Date: {{EstimatedDeliveryDate}}</strong>
+ <br>- The delivery date can be adjusted by the buyer's procurement part.
+ </p>
+ <p style="font-size:16px; line-height:24px; margin-bottom:8px;">
+ <strong>A-5 Terms of Payment : {{paymentCondition}}</strong>
+ </p>
+ <p style="font-size:16px; line-height:24px; margin-bottom:8px;">
+ <strong>A-6 Warranty Period</strong>
+ <br>The Goods supplied and the works performed under this contract shall be guaranteed for {{warrantyPeriod}} months after vessel's delivery.
+ <br>However, the guaranteed period for repair or replacement shall be extended to {{repairAdditionalPeriod}} months,
+ <br>but total guaranteed period shall not exceed {{totalPeriod}} months after vessel's delivery date.
+ </p>
+ <p style="font-size:16px; line-height:24px; margin-bottom:8px;">
+ <strong>A-7 Others not mentioned here are as per previous contract terms.</strong>
+ </p>
+</div>
+
+<div style="margin-bottom:24px;">
+ <h2 style="font-size:20px; margin-bottom:12px;">B. The following information should be included in the Bidder's quotation.</h2>
+ <p style="font-size:16px; line-height:24px; margin-bottom:8px;">
+ <strong>B-1 Detailed and Break-Down price (excluding VAT) for the supplies, the spare parts for start-up & commissioning and documentation.</strong>
+ </p>
+ <p style="font-size:16px; line-height:24px; margin-bottom:8px;">
+ <strong>B-2 Deviations, if any, from the Buyer's spec and scope of the supply should be specified on the quotation.</strong>
+ <br>Unless specified herein, the Bidder shall be regarded as fully complying with the buyer's spec. and scope of supply.
+ </p>
+ <p style="font-size:16px; line-height:24px; margin-bottom:8px;">
+ <strong>B-3 The earliest possible date for Technical meeting at Geoje Shipyard</strong>
+ </p>
+ <p style="font-size:16px; line-height:24px; margin-bottom:8px;">
+ <strong>B-4 Any suggestions in order for both parties to be competitive shall be suggested, if available.</strong>
+ </p>
+</div>
+
+<div style="margin-bottom:24px;">
+ <h2 style="font-size:20px; margin-bottom:12px;">C. Bid Closing Date : {{deadline}}</h2>
+</div>
+
+<div style="margin-bottom:24px;">
+ <h2 style="font-size:20px; margin-bottom:12px;">D. Buyer's Right</h2>
+ <p style="font-size:16px; line-height:24px; margin-bottom:8px;">
+ <strong>D-1 Buyer may select seller which did not submit the lowest bid</strong>
+ </p>
+ <p style="font-size:16px; line-height:24px; margin-bottom:8px;">
+ <strong>D-2 Buyer may accept or reject some or all of a price quotation, without obligation to notify any person or entity of such rejection.</strong>
+ </p>
+ <p style="font-size:16px; line-height:24px; margin-bottom:8px;">
+ <strong>D-3 and Buyer shall have no obligation to notify a bidder of the final decision of rejecting a bid.</strong>
+ </p>
+</div>
+
+<div style="margin-bottom:24px;">
+ <h2 style="font-size:20px; margin-bottom:12px;">E. Seller's Obligation</h2>
+ <p style="font-size:16px; line-height:24px; margin-bottom:8px;">
+ <strong>E-1 Seller shall be liable for all costs incurred in submitting a price quotation.</strong>
+ </p>
+ <p style="font-size:16px; line-height:24px; margin-bottom:8px;">
+ <strong>E-2 Under no circumstances will a subcontractor not finally selected as Seller have the right to claim for compensation against Buyer.</strong>
+ </p>
+ <p style="font-size:16px; line-height:24px; margin-bottom:8px;">
+ <strong>E-3 Selected Seller on condition of shipowner's approval is not allowed to start work without first obtaining the approval of shipowner,</strong>
+ <br>otherwise Seller has no right to make a claim for compensation.
+ </p>
+</div>
+
+<p style="font-size:16px; line-height:24px; margin-top:16px;">
+ If you have any question, please do not hesitate to contact us.
+</p>
+
+<p style="font-size:16px; line-height:24px; margin-top:16px;">
+ Best regards,
+ <br>OOO / Procurement Manager / oooo@samsung.com
+ <br>SAMSUNG HEAVY INDUSTRIES CO., LTD.
+ <br>80, Jangpyeong 3-ro, Geoje-si, Gyeongsangnam-do, Republic of Korea, 53261
+</p>
+
+<p>
+ <a href="{{loginUrl}}" target="_blank" style="display: inline-block; width: 250px; padding: 12px 20px; background-color: #163CC4; color: #ffffff !important; text-decoration: none; border-radius: 8px; text-align: center; line-height: 28px;">
+ View Quotation
+ </a>
+</p>
+
+{{> footer logoUrl=logoUrl companyName=companyName year=year }}
\ No newline at end of file diff --git a/lib/mail/templates/po-rfq-invite-ko.hbs b/lib/mail/templates/po-rfq-invite-ko.hbs new file mode 100644 index 00000000..372aadb2 --- /dev/null +++ b/lib/mail/templates/po-rfq-invite-ko.hbs @@ -0,0 +1,86 @@ +{{> header logoUrl=logoUrl }}
+
+<h1 style="font-size:28px; line-height:40px; margin-bottom:16px;">
+ SHI RFQ NO. : #{{rfqCode}}
+</h1>
+
+<p style="font-size:16px; line-height:32px; margin-bottom:16px;">
+ 안녕하세요, <strong>Vendor #{{vendorId}}</strong>님.
+</p>
+
+<p style="font-size:16px; line-height:32px; margin-bottom:16px;">
+ 귀사의 일익 번창하심을 기원합니다.
+</p>
+
+<p style="font-size:16px; line-height:32px; margin-bottom:16px;">
+ 표제 품목에 대한 견적을 요청하오니 하기 및 첨부 내용 확인하시어 견적서 및 기술사양서 자료를 eVCP를 통해 제출 바랍니다.
+ 또한, 귀사의 신제품 적용 방안이나, 당사 사양 및 공급 범위에 Deviation이 있는 경우
+ 별도의 견적을 제출하시어 당사에서 적극 검토할 수 있도록 협조 바랍니다.
+ 귀사의 견적은 아래의 견적 마감일 이전에 당사로 제출 되어야하며, 견적 마감일 및 당사의 지연 통보없이 미 제출될 경우에는 대상에서 제외될 수 있습니다.
+</p>
+
+<div style="margin-bottom:24px;">
+ <h2 style="font-size:20px; margin-bottom:12px;">가. 거래조건</h2>
+ <p style="font-size:16px; line-height:24px; margin-bottom:8px;">
+ <strong>1) 프로젝트 : {{projectName}} + 옵션 {{projectOption}} (Validity : {{ProjectOptionValidity}})</strong>
+ <br>* 호선별 D/L 일정('YY.MM.DD) : {{DLDate}}
+ </p>
+ <p style="font-size:16px; line-height:24px; margin-bottom:8px;">
+ <strong>2) Spec, & Scope of Supply : 첨부 POS 참조</strong>
+ </p>
+ <p style="font-size:16px; line-height:24px; margin-bottom:8px;">
+ <strong>3) Class / Flag : 첨부 POS 참조</strong>
+ </p>
+ <p style="font-size:16px; line-height:24px; margin-bottom:8px;">
+ <strong>4) Estimated Delivery Date : {{EstimatedDeliveryDate}}</strong>
+ <br>* 상세 납기는 조선소 스케쥴에 따라 변경될 수 있으며, 당사 조달/현업/생산 부서와 협의하여 결정됨.
+ <br>* 안전보건에 관한 사항을 고려하여 납기(또는 계약기간)의 적정성을 검토하고,
+ <br>안전보건확보를 위해 납기의 조정이 필요한 경우 기간 조정을 신청하시기 바랍니다.
+ <br>* (당사 사업장 내에서 수행하는 작업이 포함된 계약)
+ </p>
+ <p style="font-size:16px; line-height:24px; margin-bottom:8px;">
+ <strong>5) Warranty : 선박 인도 후 {{warrantyPeriod}}개월 시점까지 납품한 "자재" 또는 "용역"이 계약 내용과 동일함을 보증하며,</strong>
+ <br>Repair 시 {{repairAdditionalPeriod}}개월 추가되나, 총 인도 후 {{totalPeriod}}개월을 넘지 않음.
+ </p>
+ <p style="font-size:16px; line-height:24px; margin-bottom:8px;">
+ <strong>6) 견적마감기한 : {{deadline}}</strong>
+ </p>
+ <p style="font-size:16px; line-height:24px; margin-bottom:8px;">
+ <strong>7) 대금지급조건 : {{paymentCondition}}</strong>
+ </p>
+ <p style="font-size:16px; line-height:24px; margin-bottom:8px;">
+ <strong>8) 기타 일반사항은 삼성중공업 표준하도급기본계약서, 안전보건관리 약정서 및 자재 안전 납품/하역을 위한 표준규정에 준함.</strong>
+ </p>
+ <p style="font-size:16px; line-height:24px; margin-bottom:8px;">
+ <strong>9) 유의사항</strong>
+ <br>- 발주자는 최저가 견적을 제출하지 않은 협력사를 선정할 수 있으며,
+ <br> 견적의 일부 또는 전부를 승인하거나 거절할 수 있고 거부하는 경우 별도 통보할 의무가 없다.
+ <br> 또한, 최종 탈락 사실을 통보할 의무도 없다.
+ <br>- 협력사는 견적 제출을 위해 소요되는 비용 일체를 부담하며,
+ <br> 최종 계약자로 선정되지 못한 경우에도 발주자에게 보상을 청구할 수 없다.
+ <br> 또한, 선주 승인조건으로 선정된 협력사는 반드시 선주 승인을 득한 후 작업에 착수하여야 하며,
+ <br> 승인 거절 시 계약은 미 체결, 해제될 수 있고 이 경우 협력사는 어떠한 보상도 청구할 수 없다.
+ </p>
+</div>
+
+<div style="margin-bottom:24px;">
+ <h2 style="font-size:20px; margin-bottom:12px;">나. 견적 내용</h2>
+ <p style="font-size:16px; line-height:24px; margin-bottom:8px;">
+ <strong>1) 품목별 단가 및 총액</strong>
+ </p>
+ <p style="font-size:16px; line-height:24px; margin-bottom:8px;">
+ <strong>2) 가격 기재(VAT 제외) 견적서 / 가격 미기재 견적서 / 설계 Technical Bid Evaluation(TBE) 자료 제출</strong>
+ </p>
+ <p style="font-size:16px; line-height:24px; margin-bottom:8px;">
+ <strong>3) 당사 PGS, SGS & POS에 대한 Deviation List</strong>
+ <br style="color:red">* 별도 Deviation이 없는 경우 견적서 상에 명기
+ </p>
+</div>
+
+<p>
+ <a href="{{loginUrl}}" target="_blank" style="display: inline-block; width: 250px; padding: 12px 20px; background-color: #163CC4; color: #ffffff !important; text-decoration: none; border-radius: 8px; text-align: center; line-height: 28px;">
+ 견적서 확인하기
+ </a>
+</p>
+
+{{> footer logoUrl=logoUrl companyName=companyName year=year }}
\ No newline at end of file diff --git a/lib/mail/templates/rfq-notification.hbs b/lib/mail/templates/rfq-notification.hbs new file mode 100644 index 00000000..fc510ad0 --- /dev/null +++ b/lib/mail/templates/rfq-notification.hbs @@ -0,0 +1,166 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>{{t "email.rfq.title"}}</title> + <style> + body { + font-family: Arial, sans-serif; + line-height: 1.6; + color: #333; + margin: 0; + padding: 0; + } + .container { + max-width: 600px; + margin: 0 auto; + padding: 20px; + } + .header { + background-color: #1a56db; + color: #ffffff; + padding: 20px; + text-align: center; + border-radius: 5px 5px 0 0; + } + .content { + padding: 20px; + background-color: #ffffff; + border: 1px solid #e5e7eb; + border-top: none; + border-radius: 0 0 5px 5px; + } + .footer { + text-align: center; + margin-top: 20px; + font-size: 0.8em; + color: #6b7280; + } + table { + width: 100%; + border-collapse: collapse; + margin-bottom: 20px; + } + th, td { + border: 1px solid #e5e7eb; + padding: 12px; + text-align: left; + } + th { + background-color: #f3f4f6; + } + .button { + display: inline-block; + background-color: #1a56db; + color: #ffffff; + padding: 12px 24px; + text-decoration: none; + border-radius: 5px; + font-weight: bold; + margin-top: 20px; + } + .section-title { + margin-top: 25px; + margin-bottom: 10px; + font-weight: bold; + border-bottom: 1px solid #e5e7eb; + padding-bottom: 5px; + } + </style> +</head> +<body> + <div class="container"> + <div class="header"> + <h1>{{t "email.rfq.notification_title"}}</h1> + </div> + <div class="content"> + <p>{{t "email.greeting" name=vendor.user.fullName}},</p> + + <p>{{t "email.rfq.introduction"}}</p> + + <div class="section-title">{{t "email.rfq.details_section"}}</div> + <table> + <tr> + <th>{{t "email.rfq.code_label"}}</th> + <td>{{rfq.code}}</td> + </tr> + <tr> + <th>{{t "email.rfq.title_label"}}</th> + <td>{{rfq.title}}</td> + </tr> + <tr> + <th>{{t "email.rfq.description_label"}}</th> + <td>{{rfq.description}}</td> + </tr> + <tr> + <th>{{t "email.rfq.vendor_label"}}</th> + <td>{{vendor.name}}</td> + </tr> + <tr> + <th>{{t "email.rfq.quotation_code_label"}}</th> + <td>{{quotationCode}}</td> + </tr> + <tr> + <th>{{t "email.rfq.due_date_label"}}</th> + <td>{{rfq.dueDate}}</td> + </tr> + <tr> + <th>{{t "email.rfq.delivery_date_label"}}</th> + <td>{{rfq.deliveryDate}}</td> + </tr> + <tr> + <th>{{t "email.rfq.currency_label"}}</th> + <td>{{details.currency}}</td> + </tr> + <tr> + <th>{{t "email.rfq.payment_terms_label"}}</th> + <td>{{details.paymentTerms}}</td> + </tr> + <tr> + <th>{{t "email.rfq.incoterms_label"}}</th> + <td>{{details.incoterms}}</td> + </tr> + </table> + + <div class="section-title">{{t "email.rfq.items_section"}}</div> + <table> + <thead> + <tr> + <th>{{t "email.rfq.item_number"}}</th> + <th>{{t "email.rfq.item_description"}}</th> + <th>{{t "email.rfq.item_quantity"}}</th> + <th>{{t "email.rfq.item_uom"}}</th> + </tr> + </thead> + <tbody> + {{#each items}} + <tr> + <td>{{itemNumber}}</td> + <td>{{description}}</td> + <td>{{quantity}}</td> + <td>{{uom}}</td> + </tr> + {{/each}} + </tbody> + </table> + + <p>{{t "email.rfq.action_instructions"}}</p> + + <p style="text-align: center;"> + <a href="{{systemUrl}}/vendor/quotations/{{quotationCode}}" class="button"> + {{t "email.rfq.view_button"}} + </a> + </p> + + <p>{{t "email.rfq.closing"}}</p> + <p>{{t "email.rfq.sender_signature" name=sender.fullName}}<br> + {{sender.email}}</p> + </div> + <div class="footer"> + <p>{{t "email.footer.copyright"}} © {{year}} {{t "email.footer.company_name"}}</p> + <p>{{t "email.footer.address"}}</p> + </div> + </div> +</body> +</html>
\ No newline at end of file |
