Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 11 additions & 6 deletions src/services/email/EmailService.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import sgMail from "@sendgrid/mail"

import { Cashout, SendGridConfig } from "@config"
import { Cashout, FrappeConfig, SendGridConfig } from "@config"
import { baseLogger } from "@services/logger"
import { CashoutDetails } from "@app/offers"

import { CashoutBody } from "./templates/cashout"
import Offer from "@app/offers/Offer"
import { InitiatedCashout } from "@app/offers/ValidOffer"

type EmailHeaders = {
Expand All @@ -21,12 +19,19 @@ sgMail.setApiKey(SendGridConfig.apiKey)

class EmailService {
sendCashoutInitiatedEmail = async (cashout: InitiatedCashout) => {
const username = cashout.offer.account.username
const offer = cashout.offer.details
const account = cashout.offer.account

const username = account.username ?? ""
const customerName = account.erpParty ?? username
const cashoutId = cashout.cashoutId
const erpNextLink = `${FrappeConfig.url}/app/cashout/${cashoutId}`

const body = CashoutBody({
...offer,
...cashout.offer.details,
username,
customerName,
cashoutId,
erpNextLink,
formattedDate: new Date().toLocaleString("en-US", {
month: "short",
day: "numeric",
Expand Down
60 changes: 48 additions & 12 deletions src/services/email/templates/cashout.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,25 @@
import { CashoutDetails } from "@app/offers"
import { JMDAmount } from "@domain/shared"
import { JMDAmount, USDAmount } from "@domain/shared"

type CashoutBodyArgs = CashoutDetails & { username: Username, formattedDate: string }
type CashoutBodyArgs = CashoutDetails & {
username: string
customerName: string
cashoutId: string
erpNextLink: string
formattedDate: string
}

export const CashoutBody = (args: CashoutBodyArgs) => {
const currency = args.payout.amount instanceof JMDAmount ? "JMD" : "USD"
const payoutString = `${args.payout.amount.asDollars()} ${currency}`
const payoutCurrency = args.payout.amount instanceof JMDAmount ? "JMD" : "USD"
const payoutString = `${args.payout.amount.asDollars()} ${payoutCurrency}`

const serviceFeeString = args.payout.serviceFee instanceof USDAmount
? args.payout.serviceFee.asDollars()
: null

const feeDetails = serviceFeeString
? `Service fee: $${serviceFeeString} USD`
: ""

return {
html: `
Expand All @@ -14,28 +28,41 @@ export const CashoutBody = (args: CashoutBodyArgs) => {
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Flash Cashout Notification</title>
<title>Flash Cashout Notification — ${args.cashoutId}</title>
</head>
<body style="margin: 0; padding: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; color: #333333; background-color: #f7f7f7;">
<!-- Header -->
<div style="background-color: #0066cc; padding: 20px; text-align: center;">
<h1 style="margin: 0; color: white; font-size: 28px; font-weight: 700; letter-spacing: 1px;">FLASH</h1>
<p style="margin: 5px 0 0; color: rgba(255,255,255,0.9); font-size: 16px;">Received Cashout Transaction</p>
<p style="margin: 5px 0 0; color: rgba(255,255,255,0.9); font-size: 16px;">Cashout Initiated — ${args.cashoutId}</p>
</div>

<!-- Content -->
<div style="background-color: white; padding: 25px; border-radius: 5px; margin: 20px; box-shadow: 0 2px 5px rgba(0,0,0,0.05);">
<h2 style="margin: 0 0 20px; color: #0066cc; font-size: 20px;">Transaction Details</h2>

<table style="width: 100%; border-collapse: collapse;">
<tr>
<td style="padding: 10px 5px; border-bottom: 1px solid #eeeeee; width: 40%; color: #666666; font-weight: 500;">Cashout ID</td>
<td style="padding: 10px 5px; border-bottom: 1px solid #eeeeee; font-weight: 600; font-family: monospace;">${args.cashoutId}</td>
</tr>
<tr>
<td style="padding: 10px 5px; border-bottom: 1px solid #eeeeee; width: 40%; color: #666666; font-weight: 500;">ERPNext Link</td>
<td style="padding: 10px 5px; border-bottom: 1px solid #eeeeee;"><a href="${args.erpNextLink}" style="color: #0066cc;">${args.erpNextLink}</a></td>
</tr>
<tr>
<td style="padding: 10px 5px; border-bottom: 1px solid #eeeeee; width: 40%; color: #666666; font-weight: 500;">Ibex Payment</td>
<td style="padding: 10px 5px; border-bottom: 1px solid #eeeeee; font-weight: 600;">${args.payment.invoice.paymentHash}</td>
<td style="padding: 10px 5px; border-bottom: 1px solid #eeeeee; font-weight: 600; font-family: monospace; font-size: 13px;">${args.payment.invoice.paymentHash}</td>
</tr>
<tr>
<td style="padding: 10px 5px; border-bottom: 1px solid #eeeeee; width: 40%; color: #666666; font-weight: 500;">Owed to user</td>
<td style="padding: 10px 5px; border-bottom: 1px solid #eeeeee; width: 40%; color: #666666; font-weight: 500;">Payout Amount</td>
<td style="padding: 10px 5px; border-bottom: 1px solid #eeeeee; font-weight: 600;">${payoutString}</td>
</tr>
${serviceFeeString ? `
<tr>
<td style="padding: 10px 5px; border-bottom: 1px solid #eeeeee; width: 40%; color: #666666; font-weight: 500;">Service Fee</td>
<td style="padding: 10px 5px; border-bottom: 1px solid #eeeeee;">$${serviceFeeString} USD</td>
</tr>` : ""}
<tr>
<td style="padding: 10px 5px; border-bottom: 1px solid #eeeeee; width: 40%; color: #666666; font-weight: 500;">Date & Time</td>
<td style="padding: 10px 5px; border-bottom: 1px solid #eeeeee;">${args.formattedDate}</td>
Expand All @@ -46,7 +73,11 @@ export const CashoutBody = (args: CashoutBodyArgs) => {
<h3 style="margin: 0 0 15px; color: #0066cc; font-size: 16px;">User Information</h3>
<table style="width: 100%; border-collapse: collapse; background-color: #f9f9f9; border-radius: 4px;">
<tr>
<td style="padding: 8px 5px; color: #666666; font-weight: 500; width: 40%;">Username</td>
<td style="padding: 8px 5px; color: #666666; font-weight: 500; width: 40%;">Customer</td>
<td style="padding: 8px 5px; font-weight: 600;">${args.customerName}</td>
</tr>
<tr>
<td style="padding: 8px 5px; color: #666666; font-weight: 500;">Username</td>
<td style="padding: 8px 5px;">${args.username}</td>
</tr>
<tr>
Expand All @@ -66,16 +97,21 @@ export const CashoutBody = (args: CashoutBodyArgs) => {
</html>
`,
text: `
FLASH - Cashout Initiated
FLASH - Cashout Initiated [${args.cashoutId}]

ERPNext: ${args.erpNextLink}

Transaction Details:
--------------------
Cashout ID: ${args.cashoutId}
Ibex Payment: ${args.payment.invoice.paymentHash}
Amount owed: ${payoutString}
Payout Amount: ${payoutString}
${feeDetails}
Date & Time: ${args.formattedDate}

User Information:
-------------------
Customer: ${args.customerName}
Username: ${args.username}
Wallet ID: ${args.payment.userAcct}

Expand All @@ -84,4 +120,4 @@ export const CashoutBody = (args: CashoutBodyArgs) => {
© ${new Date().getFullYear()} Flash. All rights reserved.
`
}
}
}