diff --git a/backend/src/emails/contributionConfirmed/html.pug b/backend/src/emails/contributionConfirmed/html.pug index e60e6c700..32626b147 100644 --- a/backend/src/emails/contributionConfirmed/html.pug +++ b/backend/src/emails/contributionConfirmed/html.pug @@ -7,7 +7,7 @@ html(lang=locale) #container.col p(style='margin-bottom: 24px;')= t('emails.general.helloName', { firstName, lastName }) p= t('emails.contributionConfirmed.commonGoodContributionConfirmed', { senderFirstName, senderLastName, contributionMemo }) - p= t('emails.contributionConfirmed.contributionAmount', { contributionAmount }) + p= t('emails.general.amountGDD', { amountGDD: contributionAmount }) p= t('emails.general.linkToYourAccount') span= " " a(href=overviewURL) #{overviewURL} diff --git a/backend/src/emails/sendEmailVariants.ts b/backend/src/emails/sendEmailVariants.ts index e8f208eb0..953ac4af5 100644 --- a/backend/src/emails/sendEmailVariants.ts +++ b/backend/src/emails/sendEmailVariants.ts @@ -1,6 +1,6 @@ -import i18n from 'i18n' import Decimal from 'decimal.js-light' import CONFIG from '@/config' +import { decimalSeparatorByLanguage } from '@/util/utilities' import { sendEmailTranslated } from './sendEmailTranslated' export const sendAddedContributionMessageEmail = (data: { @@ -79,12 +79,6 @@ export const sendContributionConfirmedEmail = (data: { contributionMemo: string contributionAmount: Decimal }): Promise | null> => { - const rememberLocaleToRestore = i18n.getLocale() - i18n.setLocale(data.language) - const contributionAmount = data.contributionAmount - .toFixed(2) - .replace('.', i18n.__('emails.general.decimalSeparator')) - i18n.setLocale(rememberLocaleToRestore) return sendEmailTranslated({ receiver: { to: `${data.firstName} ${data.lastName} <${data.email}>` }, template: 'contributionConfirmed', @@ -95,7 +89,7 @@ export const sendContributionConfirmedEmail = (data: { senderFirstName: data.senderFirstName, senderLastName: data.senderLastName, contributionMemo: data.contributionMemo, - contributionAmount, + contributionAmount: decimalSeparatorByLanguage(data.contributionAmount, data.language), overviewURL: CONFIG.EMAIL_LINK_OVERVIEW, }, }) @@ -146,3 +140,31 @@ export const sendResetPasswordEmail = (data: { }, }) } + +export const sendTransactionLinkRedeemedEmail = (data: { + firstName: string + lastName: string + email: string + language: string + senderFirstName: string + senderLastName: string + senderEmail: string + transactionMemo: string + transactionAmount: Decimal +}): Promise | null> => { + return sendEmailTranslated({ + receiver: { to: `${data.firstName} ${data.lastName} <${data.email}>` }, + template: 'transactionLinkRedeemed', + locals: { + firstName: data.firstName, + lastName: data.lastName, + locale: data.language, + senderFirstName: data.senderFirstName, + senderLastName: data.senderLastName, + senderEmail: data.senderEmail, + transactionMemo: data.transactionMemo, + transactionAmount: decimalSeparatorByLanguage(data.transactionAmount, data.language), + overviewURL: CONFIG.EMAIL_LINK_OVERVIEW, + }, + }) +} diff --git a/backend/src/emails/transactionLinkRedeemed/html.pug b/backend/src/emails/transactionLinkRedeemed/html.pug new file mode 100644 index 000000000..f15a278c9 --- /dev/null +++ b/backend/src/emails/transactionLinkRedeemed/html.pug @@ -0,0 +1,19 @@ +doctype html +html(lang=locale) + head + title= t('emails.transactionLinkRedeemed.subject') + body + h1(style='margin-bottom: 24px;')= t('emails.transactionLinkRedeemed.subject') + #container.col + p(style='margin-bottom: 24px;')= t('emails.general.helloName', { firstName, lastName }) + p= t('emails.transactionLinkRedeemed.hasRedeemedYourLink', { senderFirstName, senderLastName, senderEmail }) + p= t('emails.general.amountGDD', { amountGDD: transactionAmount }) + br + span= t('emails.transactionLinkRedeemed.memo', { transactionMemo }) + p= t('emails.transactionLinkRedeemed.detailsYouFindOnLinkToYourAccount') + span= " " + a(href=overviewURL) #{overviewURL} + p= t('emails.general.pleaseDoNotReply') + p(style='margin-top: 24px;')= t('emails.general.sincerelyYours') + br + span= t('emails.general.yourGradidoTeam') diff --git a/backend/src/emails/transactionLinkRedeemed/subject.pug b/backend/src/emails/transactionLinkRedeemed/subject.pug new file mode 100644 index 000000000..6f4f74f04 --- /dev/null +++ b/backend/src/emails/transactionLinkRedeemed/subject.pug @@ -0,0 +1 @@ += t('emails.transactionLinkRedeemed.subject') diff --git a/backend/src/graphql/resolver/TransactionResolver.ts b/backend/src/graphql/resolver/TransactionResolver.ts index f0fb2f452..d83d99132 100644 --- a/backend/src/graphql/resolver/TransactionResolver.ts +++ b/backend/src/graphql/resolver/TransactionResolver.ts @@ -36,7 +36,7 @@ import Decimal from 'decimal.js-light' import { BalanceResolver } from './BalanceResolver' import { MEMO_MAX_CHARS, MEMO_MIN_CHARS } from './const/const' import { findUserByEmail } from './UserResolver' -import { sendTransactionLinkRedeemedEmail } from '@/mailer/sendTransactionLinkRedeemed' +import { sendTransactionLinkRedeemedEmail } from '@/emails/sendEmailVariants' import { Event, EventTransactionReceive, EventTransactionSend } from '@/event/Event' import { eventProtocol } from '@/event/EventProtocolEmitter' import { Decay } from '../model/Decay' @@ -182,15 +182,15 @@ export const executeTransaction = async ( }) if (transactionLink) { await sendTransactionLinkRedeemedEmail({ + firstName: sender.firstName, + lastName: sender.lastName, + email: sender.emailContact.email, + language: sender.language, senderFirstName: recipient.firstName, senderLastName: recipient.lastName, - recipientFirstName: sender.firstName, - recipientLastName: sender.lastName, - email: sender.emailContact.email, senderEmail: recipient.emailContact.email, - amount, - memo, - overviewURL: CONFIG.EMAIL_LINK_OVERVIEW, + transactionAmount: amount, + transactionMemo: memo, }) } logger.info(`finished executeTransaction successfully`) diff --git a/backend/src/locales/de.json b/backend/src/locales/de.json index fd9b74662..de1e657fe 100644 --- a/backend/src/locales/de.json +++ b/backend/src/locales/de.json @@ -21,7 +21,6 @@ }, "contributionConfirmed": { "commonGoodContributionConfirmed": "dein Gemeinwohl-Beitrag „{contributionMemo}“ wurde soeben von {senderFirstName} {senderLastName} bestätigt und in deinem Gradido-Konto gutgeschrieben.", - "contributionAmount": "Betrag: {contributionAmount} GDD", "subject": "Gradido: Dein Gemeinwohl-Beitrag wurde bestätigt" }, "contributionRejected": { @@ -29,20 +28,29 @@ "subject": "Gradido: Dein Gemeinwohl-Beitrag wurde abgelehnt", "toSeeContributionsAndMessages": "Um deine Gemeinwohl-Beiträge und dazugehörige Nachrichten zu sehen, gehe in deinem Gradido-Konto ins Menü „Gemeinschaft“ auf den Tab „Meine Beiträge zum Gemeinwohl“!" }, - "resetPassword": { - "duration": "Der Link hat eine Gültigkeit von {hours} Stunden und {minutes} Minuten. Sollte die Gültigkeit des Links bereits abgelaufen sein, kannst du dir hier einen neuen Link schicken lassen, in dem du deine E-Mail-Adresse eingibst:", - "pleaseClickLink": "Wenn du es warst, klicke bitte auf den Link:", - "subject": "Gradido: Passwort zurücksetzen", - "youOrSomeoneResetPassword": "du, oder jemand anderes, hast für dieses Konto ein Zurücksetzen des Passworts angefordert." - }, "general": { - "decimalSeparator": ",", + "amountGDD": "Betrag: {amountGDD} GDD", "helloName": "Hallo {firstName} {lastName},", "linkToYourAccount": "Link zu deinem Konto:", "orCopyLink": "oder kopiere den obigen Link in dein Browserfenster.", "pleaseDoNotReply": "Bitte antworte nicht auf diese E-Mail!", "sincerelyYours": "Liebe Grüße", "yourGradidoTeam": "dein Gradido-Team" + }, + "resetPassword": { + "duration": "Der Link hat eine Gültigkeit von {hours} Stunden und {minutes} Minuten. Sollte die Gültigkeit des Links bereits abgelaufen sein, kannst du dir hier einen neuen Link schicken lassen, in dem du deine E-Mail-Adresse eingibst:", + "pleaseClickLink": "Wenn du es warst, klicke bitte auf den Link:", + "subject": "Gradido: Passwort zurücksetzen", + "youOrSomeoneResetPassword": "du, oder jemand anderes, hast für dieses Konto ein Zurücksetzen des Passworts angefordert." + }, + "transactionLinkRedeemed": { + "detailsYouFindOnLinkToYourAccount": "Details zur Transaktion findest du in deinem Gradido-Konto:", + "hasRedeemedYourLink": "{senderFirstName} {senderLastName} ({senderEmail}) hat soeben deinen Link eingelöst.", + "memo": "Memo: {transactionMemo}", + "subject": "Gradido: Dein Gradido-Link wurde eingelöst" } + }, + "general": { + "decimalSeparator": "," } -} \ No newline at end of file +} diff --git a/backend/src/locales/en.json b/backend/src/locales/en.json index c688102c6..34cf2512f 100644 --- a/backend/src/locales/en.json +++ b/backend/src/locales/en.json @@ -21,7 +21,6 @@ }, "contributionConfirmed": { "commonGoodContributionConfirmed": "Your public good contribution “{contributionMemo}” has just been confirmed by {senderFirstName} {senderLastName} and credited to your Gradido account.", - "contributionAmount": "Amount: {contributionAmount} GDD", "subject": "Gradido: Your common good contribution was confirmed" }, "contributionRejected": { @@ -29,20 +28,29 @@ "subject": "Gradido: Your common good contribution was rejected", "toSeeContributionsAndMessages": "To see your common good contributions and related messages, go to the “Community” menu in your Gradido account and click on the “My contributions to the common good” tab!" }, - "resetPassword": { - "duration": "The link has a validity of {hours} hours and {minutes} minutes. If the validity of the link has already expired, you can have a new link sent to you here by entering your email address:", - "pleaseClickLink": "If it was you, please click on the link:", - "subject": "Gradido: Reset password", - "youOrSomeoneResetPassword": "You, or someone else, requested a password reset for this account." - }, "general": { - "decimalSeparator": ".", + "amountGDD": "Amount: {amountGDD} GDD", "helloName": "Hello {firstName} {lastName}", "linkToYourAccount": "Link to your account:", "orCopyLink": "or copy the link above into your browser window.", "pleaseDoNotReply": "Please do not reply to this email!", "sincerelyYours": "Kind regards,", "yourGradidoTeam": "your Gradido team" + }, + "resetPassword": { + "duration": "The link has a validity of {hours} hours and {minutes} minutes. If the validity of the link has already expired, you can have a new link sent to you here by entering your email address:", + "pleaseClickLink": "If it was you, please click on the link:", + "subject": "Gradido: Reset password", + "youOrSomeoneResetPassword": "You, or someone else, requested a password reset for this account." + }, + "transactionLinkRedeemed": { + "detailsYouFindOnLinkToYourAccount": "You can find transaction details in your Gradido account:", + "hasRedeemedYourLink": "{senderFirstName} {senderLastName} ({senderEmail}) has just redeemed your link.", + "memo": "Memo: {transactionMemo}", + "subject": "Gradido: Your Gradido link has been redeemed" } + }, + "general": { + "decimalSeparator": "." } -} \ No newline at end of file +} diff --git a/backend/src/util/utilities.ts b/backend/src/util/utilities.ts index 65214ebb5..f24def721 100644 --- a/backend/src/util/utilities.ts +++ b/backend/src/util/utilities.ts @@ -1,4 +1,5 @@ import Decimal from 'decimal.js-light' +import i18n from 'i18n' export const objectValuesToArray = (obj: { [x: string]: string }): Array => { return Object.keys(obj).map(function (key) { @@ -15,3 +16,11 @@ export const decimalAddition = (a: Decimal, b: Decimal): Decimal => { export const decimalSubtraction = (a: Decimal, b: Decimal): Decimal => { return a.minus(b.toString()) } + +export const decimalSeparatorByLanguage = (a: Decimal, language: string): string => { + const rememberLocaleToRestore = i18n.getLocale() + i18n.setLocale(language) + const result = a.toFixed(2).replace('.', i18n.__('general.decimalSeparator')) + i18n.setLocale(rememberLocaleToRestore) + return result +}